提交 f31cb792 编写于 作者: C CyrusNajmabadi

Support doc comments for symbols declared off an anonymous type.

上级 ee44aee1
......@@ -2835,6 +2835,20 @@ protected override INamedTypeSymbol CommonCreateTupleTypeSymbol(INamedTypeSymbol
return TupleTypeSymbol.Create(csharpUnderlyingTuple, elementNames);
}
protected override INamedTypeSymbol CommonCreateAnonymousTypeSymbol(
ImmutableArray<ITypeSymbol> memberTypes, ImmutableArray<string> memberNames)
{
for (int i = 0, n = memberTypes.Length; i < n; i++)
{
memberTypes[i].EnsureCSharpSymbolOrNull<ITypeSymbol, TypeSymbol>($"{nameof(memberTypes)}[{i}]");
}
var fields = memberTypes.Select((t, i) => new AnonymousTypeField(memberNames[i], Location.None, (TypeSymbol)t)).ToImmutableArray();
var descriptor = new AnonymousTypeDescriptor(fields, Location.None);
return this.AnonymousTypeManager.ConstructAnonymousTypeSymbol(descriptor);
}
protected override ITypeSymbol CommonDynamicType
{
get { return DynamicType; }
......
......@@ -851,6 +851,31 @@ public INamedTypeSymbol CreateTupleTypeSymbol(INamedTypeSymbol underlyingType, I
protected abstract INamedTypeSymbol CommonCreateTupleTypeSymbol(INamedTypeSymbol underlyingType, ImmutableArray<string> elementNames);
/// <summary>
/// Returns a new anonymous type symbol with the given member types member names.
/// </summary>
public INamedTypeSymbol CreateAnonymousTypeSymbol(
ImmutableArray<ITypeSymbol> memberTypes, ImmutableArray<string> memberNames)
{
if (memberTypes.Length != memberNames.Length)
{
throw new ArgumentException($"{nameof(memberTypes)} and {nameof(memberNames)} must have the same length.");
}
for (int i = 0, n = memberTypes.Length; i < n; i++)
{
if (memberTypes[i] == null)
{
throw new ArgumentNullException($"{nameof(memberTypes)}[{i}]");
}
}
return CommonCreateAnonymousTypeSymbol(memberTypes, memberNames);
}
protected abstract INamedTypeSymbol CommonCreateAnonymousTypeSymbol(
ImmutableArray<ITypeSymbol> memberTypes, ImmutableArray<string> memberNames);
#endregion
#region Diagnostics
......
Microsoft.CodeAnalysis.Compilation.CreateAnonymousTypeSymbol(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ITypeSymbol> memberTypes, System.Collections.Immutable.ImmutableArray<string> memberNames) -> Microsoft.CodeAnalysis.INamedTypeSymbol
Microsoft.CodeAnalysis.Compilation.CreateTupleTypeSymbol(Microsoft.CodeAnalysis.INamedTypeSymbol underlyingType, System.Collections.Immutable.ImmutableArray<string> elementNames = default(System.Collections.Immutable.ImmutableArray<string>)) -> Microsoft.CodeAnalysis.INamedTypeSymbol
Microsoft.CodeAnalysis.Compilation.CreateTupleTypeSymbol(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ITypeSymbol> elementTypes, System.Collections.Immutable.ImmutableArray<string> elementNames = default(System.Collections.Immutable.ImmutableArray<string>)) -> Microsoft.CodeAnalysis.INamedTypeSymbol
Microsoft.CodeAnalysis.Diagnostics.AnalysisContext.RegisterOperationAction(System.Action<Microsoft.CodeAnalysis.Diagnostics.OperationAnalysisContext> action, params Microsoft.CodeAnalysis.OperationKind[] operationKinds) -> void
......@@ -908,4 +909,4 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.Vi
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitVariableDeclarationStatement(Microsoft.CodeAnalysis.Semantics.IVariableDeclarationStatement operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitWhileUntilLoopStatement(Microsoft.CodeAnalysis.Semantics.IWhileUntilLoopStatement operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitWithStatement(Microsoft.CodeAnalysis.Semantics.IWithStatement operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitYieldBreakStatement(Microsoft.CodeAnalysis.Semantics.IReturnStatement operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitYieldBreakStatement(Microsoft.CodeAnalysis.Semantics.IReturnStatement operation, TArgument argument) -> TResult
\ No newline at end of file
......@@ -2605,6 +2605,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Throw New NotSupportedException(VBResources.ThereAreNoPointerTypesInVB)
End Function
Protected Overrides Function CommonCreateAnonymousTypeSymbol(
memberTypes As ImmutableArray(Of ITypeSymbol),
memberNames As ImmutableArray(Of String)) As INamedTypeSymbol
Dim index = 0
For Each t In memberTypes
t.EnsureVbSymbolOrNothing(Of TypeSymbol)($"{NameOf(memberTypes)}({index})")
index = index + 1
Next
Dim fields = memberTypes.Select(Function(t, i) New AnonymousTypeField(memberNames(i), DirectCast(t, TypeSymbol), Location.None)).
ToImmutableArray()
Dim descriptor = New AnonymousTypeDescriptor(fields, Location.None, isImplicitlyDeclared:=False)
Return Me.AnonymousTypeManager.ConstructAnonymousTypeSymbol(descriptor)
End Function
Protected Overrides ReadOnly Property CommonDynamicType As ITypeSymbol
Get
Throw New NotSupportedException(VBResources.ThereIsNoDynamicTypeInVB)
......
......@@ -47,10 +47,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Get
End Property
Public Sub New(fields As ImmutableArray(Of AnonymousTypeField), _location As Location, _isImplicitlyDeclared As Boolean)
Public Sub New(fields As ImmutableArray(Of AnonymousTypeField), location As Location, isImplicitlyDeclared As Boolean)
Me.Fields = fields
Me.Location = _location
Me.IsImplicitlyDeclared = _isImplicitlyDeclared
Me.Location = location
Me.IsImplicitlyDeclared = isImplicitlyDeclared
Me.Key = ComputeKey(fields, Function(f) f.Name, Function(f) f.IsKey)
End Sub
......
......@@ -1859,5 +1859,29 @@ class Program
Await state.AssertSelectedCompletionItem("value", isHardSelected:=True).ConfigureAwait(True)
End Using
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
<WorkItem(12530, "https://github.com/dotnet/roslyn/issues/12530")>
Public Async Function TestAnonymousTypeDescription() As Task
Using state = TestState.CreateCSharpTestState(
<Document><![CDATA[
using System.Linq;
class Program
{
static void Main(string[] args)
{
new[] { new { x = 1 } }.ToArr$$
}
}]]></Document>, extraExportedTypes:={GetType(CSharpEditorFormattingService)}.ToList())
state.SendInvokeCompletionList()
Await state.WaitForAsynchronousOperationsAsync()
Await state.AssertSelectedCompletionItem(description:=
"(extension) 'a[] System.Collections.Generic.IEnumerable<'a>.ToArray<'a>()
Anonymous Types:
'a is new { int x }")
End Using
End Function
End Class
End Namespace
......@@ -2432,5 +2432,28 @@ End Class]]></Document>)
Await state.AssertSelectedCompletionItem("value", isHardSelected:=False, isSoftSelected:=True).ConfigureAwait(True)
End Using
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.Completion)>
<WorkItem(12530, "https://github.com/dotnet/roslyn/issues/12530")>
Public Async Function TestAnonymousTypeDescription() As Task
Using state = TestState.CreateVisualBasicTestState(
<Document><![CDATA[
Imports System.Linq
Public Class Class1
Sub Method()
Dim x = {New With {.x = 1}}.ToArr$$
End Sub
End Class
]]></Document>)
state.SendInvokeCompletionList()
Await state.WaitForAsynchronousOperationsAsync()
Await state.AssertSelectedCompletionItem(description:=
"<Extension> Function IEnumerable(Of 'a).ToArray() As 'a()
Anonymous Types:
'a is New With { .x As Integer }")
End Using
End Function
End Class
End Namespace
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
namespace Microsoft.CodeAnalysis
{
internal partial struct SymbolKey
{
private static class AnonymousTypeSymbolKey
{
public static void Create(INamedTypeSymbol symbol, SymbolKeyWriter visitor)
{
Debug.Assert(symbol.IsAnonymousType);
var properties = symbol.GetMembers().OfType<IPropertySymbol>().ToArray();
var propertyTypes = properties.Select(p => p.Type).ToImmutableArray();
var propertyNames = properties.Select(p => p.Name).ToImmutableArray();
visitor.WriteSymbolKeyArray(propertyTypes);
visitor.WriteStringArray(propertyNames);
}
public static int GetHashCode(GetHashCodeReader reader)
{
// The hash of the underlying type is good enough, we don't need to include names.
var symbolKeyHashCode = reader.ReadSymbolKeyArrayHashCode();
var elementNames = reader.ReadStringArray();
return symbolKeyHashCode;
}
public static SymbolKeyResolution Resolve(SymbolKeyReader reader)
{
var propertyTypeSymbols = reader.ReadSymbolKeyArray();
var propertyTypes = propertyTypeSymbols.Select(r => GetFirstSymbol<ITypeSymbol>(r)).ToImmutableArray();
var propertyNames = reader.ReadStringArray();
if (propertyTypes.Length == propertyNames.Length)
{
try
{
var anonymousType = reader.Compilation.CreateAnonymousTypeSymbol(propertyTypes, propertyNames);
return new SymbolKeyResolution(anonymousType);
}
catch (ArgumentException)
{
}
}
return new SymbolKeyResolution(reader.Compilation.ObjectType);
}
}
}
}
\ No newline at end of file
......@@ -365,6 +365,7 @@ protected override int ReadWorker(SymbolKeyType type)
case SymbolKeyType.Event: return EventSymbolKey.GetHashCode(this);
case SymbolKeyType.ReducedExtensionMethod: return ReducedExtensionMethodSymbolKey.GetHashCode(this);
case SymbolKeyType.TypeParameter: return TypeParameterSymbolKey.GetHashCode(this);
case SymbolKeyType.AnonymousType: return AnonymousTypeSymbolKey.GetHashCode(this);
case SymbolKeyType.TypeParameterOrdinal: return TypeParameterOrdinalSymbolKey.GetHashCode(this);
}
......@@ -520,6 +521,7 @@ protected override SymbolKeyResolution ReadWorker(SymbolKeyType type)
case SymbolKeyType.Event: return EventSymbolKey.Resolve(this);
case SymbolKeyType.ReducedExtensionMethod: return ReducedExtensionMethodSymbolKey.Resolve(this);
case SymbolKeyType.TypeParameter: return TypeParameterSymbolKey.Resolve(this);
case SymbolKeyType.AnonymousType: return AnonymousTypeSymbolKey.Resolve(this);
case SymbolKeyType.TypeParameterOrdinal: return TypeParameterOrdinalSymbolKey.Resolve(this);
}
......
......@@ -33,6 +33,7 @@ private enum SymbolKeyType
Event = 'V',
ReducedExtensionMethod = 'X',
TypeParameter = 'Y',
AnonymousType = 'Z',
// Not to be confused with ArrayType. This indicates an array of elements in the stream.
Array = '%',
......@@ -334,6 +335,11 @@ public override object VisitNamedType(INamedTypeSymbol namedTypeSymbol)
WriteType(SymbolKeyType.TupleType);
TupleTypeSymbolKey.Create(namedTypeSymbol, this);
}
else if (namedTypeSymbol.IsAnonymousType)
{
WriteType(SymbolKeyType.AnonymousType);
AnonymousTypeSymbolKey.Create(namedTypeSymbol, this);
}
else
{
WriteType(SymbolKeyType.NamedType);
......
......@@ -435,6 +435,7 @@
<Compile Include="SymbolId\SymbolKey.ComparisonOptions.cs" />
<Compile Include="SymbolId\SymbolKey.SymbolKeyComparer.cs" />
<Compile Include="SymbolId\SymbolKey.PropertySymbolKey.cs" />
<Compile Include="SymbolId\SymbolKey.AnonymousTypeSymbolKey.cs" />
<Compile Include="SymbolId\SymbolKey.TypeParameterOrdinalSymbolKey.cs" />
<Compile Include="SymbolId\SymbolKey.TypeParameterSymbolKey.cs" />
<Compile Include="SymbolId\SymbolKey.ErrorTypeSymbolKey.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册