提交 29015e53 编写于 作者: V VSadov 提交者: GitHub

Merge pull request #13923 from VSadov/vbMetaExp

Metadata export for tuple element names in VB
......@@ -580,11 +580,6 @@ private IEnumerable<CSharpAttributeData> GetReturnValueCustomAttributesToEmit()
userDefined = this.GetReturnTypeAttributes();
this.AddSynthesizedReturnTypeAttributes(ref synthesized);
if (userDefined.IsEmpty && synthesized == null)
{
return SpecializedCollections.EmptyEnumerable<CSharpAttributeData>();
}
// Note that callers of this method (CCI and ReflectionEmitter) have to enumerate
// all items of the returned iterator, otherwise the synthesized ArrayBuilder may leak.
return GetCustomAttributesToEmit(userDefined, synthesized, isReturnType: true, emittingAssemblyAttributesInNetModule: false);
......
......@@ -72,11 +72,6 @@ internal IEnumerable<CSharpAttributeData> GetCustomAttributesToEmit(ModuleCompil
userDefined = this.GetAttributes();
this.AddSynthesizedAttributes(compilationState, ref synthesized);
if (userDefined.IsEmpty && synthesized == null)
{
return SpecializedCollections.EmptyEnumerable<CSharpAttributeData>();
}
// Note that callers of this method (CCI and ReflectionEmitter) have to enumerate
// all items of the returned iterator, otherwise the synthesized ArrayBuilder may leak.
return GetCustomAttributesToEmit(userDefined, synthesized, isReturnType: false, emittingAssemblyAttributesInNetModule: emittingAssemblyAttributesInNetModule);
......@@ -94,6 +89,23 @@ internal IEnumerable<CSharpAttributeData> GetCustomAttributesToEmit(ModuleCompil
{
CheckDefinitionInvariant();
//PERF: Avoid creating an iterator for the common case of no attributes.
if (userDefined.IsEmpty && synthesized == null)
{
return SpecializedCollections.EmptyEnumerable<CSharpAttributeData>();
}
return GetCustomAttributesToEmitIterator(userDefined, synthesized, isReturnType, emittingAssemblyAttributesInNetModule);
}
private IEnumerable<CSharpAttributeData> GetCustomAttributesToEmitIterator(
ImmutableArray<CSharpAttributeData> userDefined,
ArrayBuilder<SynthesizedAttributeData> synthesized,
bool isReturnType,
bool emittingAssemblyAttributesInNetModule)
{
CheckDefinitionInvariant();
if (synthesized != null)
{
foreach (var attribute in synthesized)
......
......@@ -499,7 +499,7 @@ internal SynthesizedAttributeData SynthesizeDynamicAttribute(TypeSymbol type, in
}
}
internal SynthesizedAttributeData SynthesizeTupleNamesAttributeOpt(TypeSymbol type)
internal SynthesizedAttributeData SynthesizeTupleNamesAttribute(TypeSymbol type)
{
Debug.Assert((object)type != null);
Debug.Assert(type.ContainsTuple());
......@@ -508,11 +508,7 @@ internal SynthesizedAttributeData SynthesizeTupleNamesAttributeOpt(TypeSymbol ty
Debug.Assert((object)stringType != null);
var names = TupleNamesEncoder.Encode(type, stringType);
// If there are no names, elide the attribute entirely
if (names.IsDefault)
{
return null;
}
Debug.Assert(!names.IsDefault, "should not need the attribute when no tuple names");
var stringArray = ArrayTypeSymbol.CreateSZArray(stringType.ContainingAssembly, stringType, customModifiers: ImmutableArray<CustomModifier>.Empty);
var args = ImmutableArray.Create(new TypedConstant(stringArray, names));
......
......@@ -301,10 +301,10 @@ internal override void AddSynthesizedAttributes(ModuleCompilationState compilati
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(this.Type, customModifiersCount: 0));
}
if (Type.ContainsTuple())
if (Type.ContainsTupleNames())
{
AddSynthesizedAttribute(ref attributes,
DeclaringCompilation.SynthesizeTupleNamesAttributeOpt(Type));
DeclaringCompilation.SynthesizeTupleNamesAttribute(Type));
}
}
......
......@@ -465,10 +465,10 @@ internal override void AddSynthesizedAttributes(ModuleCompilationState compilati
DeclaringCompilation.SynthesizeDynamicAttribute(Type, CustomModifiers.Length));
}
if (Type.ContainsTuple())
if (Type.ContainsTupleNames())
{
AddSynthesizedAttribute(ref attributes,
DeclaringCompilation.SynthesizeTupleNamesAttributeOpt(Type));
DeclaringCompilation.SynthesizeTupleNamesAttribute(Type));
}
}
......
......@@ -957,10 +957,10 @@ internal override void AddSynthesizedReturnTypeAttributes(ref ArrayBuilder<Synth
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(this.ReturnType, this.ReturnTypeCustomModifiers.Length));
}
if (ReturnType.ContainsTuple())
if (ReturnType.ContainsTupleNames())
{
AddSynthesizedAttribute(ref attributes,
DeclaringCompilation.SynthesizeTupleNamesAttributeOpt(ReturnType));
DeclaringCompilation.SynthesizeTupleNamesAttribute(ReturnType));
}
}
......
......@@ -1089,9 +1089,9 @@ internal override void AddSynthesizedAttributes(ModuleCompilationState compilati
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(baseType, customModifiersCount: 0));
}
if (baseType.ContainsTuple())
if (baseType.ContainsTupleNames())
{
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeTupleNamesAttributeOpt(baseType));
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeTupleNamesAttribute(baseType));
}
}
}
......
......@@ -82,10 +82,10 @@ internal sealed override void AddSynthesizedAttributes(ModuleCompilationState co
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(this.Type, this.CustomModifiers.Length, this.RefKind));
}
if (Type.ContainsTuple())
if (Type.ContainsTupleNames())
{
AddSynthesizedAttribute(ref attributes,
compilation.SynthesizeTupleNamesAttributeOpt(Type));
compilation.SynthesizeTupleNamesAttribute(Type));
}
}
......
......@@ -1050,10 +1050,10 @@ internal override void AddSynthesizedAttributes(ModuleCompilationState compilati
DeclaringCompilation.SynthesizeDynamicAttribute(Type, TypeCustomModifiers.Length));
}
if (Type.ContainsTuple())
if (Type.ContainsTupleNames())
{
AddSynthesizedAttribute(ref attributes,
DeclaringCompilation.SynthesizeTupleNamesAttributeOpt(Type));
DeclaringCompilation.SynthesizeTupleNamesAttribute(Type));
}
}
......
......@@ -57,12 +57,12 @@ internal override void AddSynthesizedAttributes(ModuleCompilationState compilati
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(this.Type, this.CustomModifiers.Length));
}
if (Type.ContainsTuple() &&
if (Type.ContainsTupleNames() &&
compilation.HasTupleNamesAttributes &&
compilation.CanEmitSpecialType(SpecialType.System_String))
{
AddSynthesizedAttribute(ref attributes,
compilation.SynthesizeTupleNamesAttributeOpt(Type));
compilation.SynthesizeTupleNamesAttribute(Type));
}
}
......
......@@ -87,12 +87,12 @@ internal override void AddSynthesizedAttributes(ModuleCompilationState compilati
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(this.ReturnType, this.ReturnTypeCustomModifiers.Length));
}
if (ReturnType.ContainsTuple() &&
if (ReturnType.ContainsTupleNames() &&
compilation.HasTupleNamesAttributes &&
compilation.CanEmitSpecialType(SpecialType.System_String))
{
AddSynthesizedAttribute(ref attributes,
compilation.SynthesizeTupleNamesAttributeOpt(ReturnType));
compilation.SynthesizeTupleNamesAttribute(ReturnType));
}
}
......
......@@ -164,12 +164,12 @@ internal override void AddSynthesizedAttributes(ModuleCompilationState compilati
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(this.Type, this.CustomModifiers.Length, this.RefKind));
}
if (Type.ContainsTuple() &&
if (Type.ContainsTupleNames() &&
compilation.HasTupleNamesAttributes &&
compilation.CanEmitSpecialType(SpecialType.System_String))
{
AddSynthesizedAttribute(ref attributes,
compilation.SynthesizeTupleNamesAttributeOpt(Type));
compilation.SynthesizeTupleNamesAttribute(Type));
}
}
......
......@@ -815,7 +815,7 @@ public static bool ContainsDynamic(this TypeSymbol type)
/// Return true if the type contains any tuples with element names.
/// </summary>
internal static bool ContainsTupleNames(this TypeSymbol type) =>
(object)type.VisitType((TypeSymbol t, object _1, bool _2) => t.IsTupleType && !t.TupleElementNames.IsDefault , null) != null;
(object)type.VisitType((TypeSymbol t, object _1, bool _2) => !t.TupleElementNames.IsDefault , null) != null;
/// <summary>
/// Guess the non-error type that the given type was intended to represent.
......@@ -1470,9 +1470,9 @@ private static bool NormalizeTaskTypesInPointer(CSharpCompilation compilation, r
CSharpCompilation declaringCompilation,
Cci.ITypeReference typeRef)
{
if (type.ContainsTuple())
if (type.ContainsTupleNames())
{
var attr = declaringCompilation.SynthesizeTupleNamesAttributeOpt(type);
var attr = declaringCompilation.SynthesizeTupleNamesAttribute(type);
if (attr != null)
{
return new Cci.TypeReferenceWithAttributes(
......
......@@ -3273,6 +3273,7 @@ internal static bool IsSynthesizedAttributeOptional(WellKnownMember attributeMem
case WellKnownMember.System_STAThreadAttribute__ctor:
case WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor:
case WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor:
case WellKnownMember.System_Runtime_CompilerServices_TupleElementNamesAttribute__ctorTransformNames:
return true;
default:
......
......@@ -1829,6 +1829,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return ArrayTypeSymbol.CreateVBArray(elementType, Nothing, rank, Me)
End Function
Friend ReadOnly Property HasTupleNamesAttributes As Boolean
Get
Return GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_TupleElementNamesAttribute__ctorTransformNames) IsNot Nothing
End Get
End Property
Friend Function CanEmitSpecialType(type As SpecialType) As Boolean
Dim typeSymbol = GetSpecialType(type)
Dim diagnostic = typeSymbol.GetUseSiteErrorInfo
Return diagnostic Is Nothing OrElse diagnostic.Severity <> DiagnosticSeverity.Error
End Function
#End Region
#Region "Binding"
......
......@@ -453,11 +453,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Private ReadOnly Property IMethodDefinitionReturnValueAttributes As IEnumerable(Of Cci.ICustomAttribute) Implements Cci.IMethodDefinition.ReturnValueAttributes
Get
CheckDefinitionInvariant()
Return GetCustomAttributesToEmit(Me.GetReturnTypeAttributes(), synthesized:=Nothing, isReturnType:=True, emittingAssemblyAttributesInNetModule:=False)
Return GetReturnValueCustomAttributesToEmit()
End Get
End Property
Private Function GetReturnValueCustomAttributesToEmit() As IEnumerable(Of Cci.ICustomAttribute)
CheckDefinitionInvariant()
Dim userDefined As ImmutableArray(Of VisualBasicAttributeData)
Dim synthesized As ArrayBuilder(Of SynthesizedAttributeData) = Nothing
userDefined = Me.GetReturnTypeAttributes()
Me.AddSynthesizedReturnTypeAttributes(synthesized)
' Note that callers of this method (CCI and ReflectionEmitter) have to enumerate
' all items of the returned iterator, otherwise the synthesized ArrayBuilder may leak.
Return GetCustomAttributesToEmit(userDefined, synthesized, isReturnType:=True, emittingAssemblyAttributesInNetModule:=False)
End Function
Private ReadOnly Property IMethodDefinitionReturnValueIsMarshalledExplicitly As Boolean Implements Cci.IMethodDefinition.ReturnValueIsMarshalledExplicitly
Get
CheckDefinitionInvariant()
......
......@@ -399,14 +399,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Dim moduleBeingBuilt As PEModuleBuilder = DirectCast(context.Module, PEModuleBuilder)
For Each [interface] In GetInterfacesToEmit()
Dim translated = moduleBeingBuilt.Translate([interface],
Dim typeRef = moduleBeingBuilt.Translate([interface],
syntaxNodeOpt:=DirectCast(context.SyntaxNodeOpt, VisualBasicSyntaxNode),
diagnostics:=context.Diagnostics,
fromImplements:=True)
' TODO(https://github.com/dotnet/roslyn/issues/12592):
' TODO: Add support for tuple attributes on interface implementations
Yield New Cci.TypeReferenceWithAttributes(translated)
Yield [interface].GetTypeRefWithAttributes(Me.DeclaringCompilation, typeRef)
Next
End Function
......
......@@ -82,13 +82,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit.NoPia
Dim moduleBeingBuilt = DirectCast(context.Module, PEModuleBuilder)
For Each [interface] In UnderlyingNamedType.GetInterfacesToEmit()
Dim translated = moduleBeingBuilt.Translate([interface],
Dim typeRef = moduleBeingBuilt.Translate([interface],
DirectCast(context.SyntaxNodeOpt, VisualBasicSyntaxNode),
context.Diagnostics)
' TODO(https://github.com/dotnet/roslyn/issues/12592):
' TODO: Add support for tuple attributes on interface implementations
Yield New Cci.TypeReferenceWithAttributes(translated)
Yield [interface].GetTypeRefWithAttributes(UnderlyingNamedType.DeclaringCompilation, typeRef)
Next
End Function
......
......@@ -196,9 +196,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
syntaxNodeOpt:=DirectCast(context.SyntaxNodeOpt, VisualBasicSyntaxNode),
diagnostics:=context.Diagnostics)
' TODO(https://github.com/dotnet/roslyn/issues/12592):
' Add support for tuple attributes on interface implementations
Yield New Cci.TypeReferenceWithAttributes(typeRef)
Yield t.GetTypeRefWithAttributes(Me.DeclaringCompilation, typeRef)
Next
If Me.HasValueTypeConstraint AndAlso Not seenValueType Then
' Add System.ValueType constraint to comply with Dev11 C# output
......
......@@ -140,6 +140,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return ImmutableArray(Of VisualBasicAttributeData).Empty
End Function
''' <summary>
''' Build and add synthesized return type attributes for this method symbol.
''' </summary>
Friend Overridable Sub AddSynthesizedReturnTypeAttributes(ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
End Sub
''' <summary>
''' Optimization: in many cases, the parameter count (fast) is sufficient and we
''' don't need the actual parameter symbols (slow).
......
......@@ -745,5 +745,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Get
End Property
Friend Overrides Sub AddSynthesizedAttributes(compilationState As ModuleCompilationState, ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
MyBase.AddSynthesizedAttributes(compilationState, attributes)
If Me.Type.ContainsTupleNames() Then
AddSynthesizedAttribute(attributes, DeclaringCompilation.SynthesizeTupleNamesAttribute(Type))
End If
End Sub
End Class
End Namespace
......@@ -280,6 +280,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End If
End If
End If
If Me.Type.ContainsTupleNames() Then
AddSynthesizedAttribute(attributes, DeclaringCompilation.SynthesizeTupleNamesAttribute(Type))
End If
End Sub
Friend NotOverridable Overrides Function EarlyDecodeWellKnownAttribute(ByRef arguments As EarlyDecodeWellKnownAttributeArguments(Of EarlyWellKnownAttributeBinder, NamedTypeSymbol, AttributeSyntax, AttributeLocation)) As VisualBasicAttributeData
......
......@@ -1444,6 +1444,14 @@ lReportErrorOnTwoTokens:
End If
End Sub
Friend Overrides Sub AddSynthesizedReturnTypeAttributes(ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
MyBase.AddSynthesizedReturnTypeAttributes(attributes)
If Me.ReturnType.ContainsTupleNames() Then
AddSynthesizedAttribute(attributes, DeclaringCompilation.SynthesizeTupleNamesAttribute(Me.ReturnType))
End If
End Sub
Protected Function GetDecodedWellKnownAttributeData() As MethodWellKnownAttributeData
Dim attributesBag As CustomAttributesBag(Of VisualBasicAttributeData) = Me.m_lazyCustomAttributesBag
If attributesBag Is Nothing OrElse Not attributesBag.IsDecodedWellKnownAttributeDataComputed Then
......
......@@ -2381,7 +2381,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Get
End Property
Friend Overrides Sub AddSynthesizedAttributes(compilationState as ModuleCompilationState, ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
Friend Overrides Sub AddSynthesizedAttributes(compilationState As ModuleCompilationState, ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
MyBase.AddSynthesizedAttributes(compilationState, attributes)
Dim compilation = Me.DeclaringCompilation
......@@ -2439,6 +2439,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
New TypedConstant(GetSpecialType(SpecialType.System_String), TypedConstantKind.Primitive, eventInterfaceName))))
End If
End If
Dim baseType As NamedTypeSymbol = Me.BaseTypeNoUseSiteDiagnostics
If baseType IsNot Nothing Then
If baseType.ContainsTupleNames() Then
AddSynthesizedAttribute(attributes, compilation.SynthesizeTupleNamesAttribute(baseType))
End If
End If
End Sub
Private Function HasDefaultMemberAttribute() As Boolean
......
......@@ -64,6 +64,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
AddSynthesizedAttribute(attributes, compilation.SynthesizeDecimalConstantAttribute(defaultValue.DecimalValue))
End Select
End If
If Me.Type.ContainsTupleNames() Then
AddSynthesizedAttribute(attributes, DeclaringCompilation.SynthesizeTupleNamesAttribute(Type))
End If
End Sub
Friend Overrides ReadOnly Property CountOfCustomModifiersPrecedingByRef As UShort
......
......@@ -1189,6 +1189,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return False
End Get
End Property
Friend Overrides Sub AddSynthesizedAttributes(compilationState As ModuleCompilationState, ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
MyBase.AddSynthesizedAttributes(compilationState, attributes)
If Me.Type.ContainsTupleNames() Then
AddSynthesizedAttribute(attributes, DeclaringCompilation.SynthesizeTupleNamesAttribute(Type))
End If
End Sub
End Class
End Namespace
......@@ -59,6 +59,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return
End If
Dim compilation = Me.DeclaringCompilation
If Type.ContainsTupleNames() AndAlso
compilation.HasTupleNamesAttributes AndAlso
compilation.CanEmitSpecialType(SpecialType.System_String) Then
AddSynthesizedAttribute(attributes, compilation.SynthesizeTupleNamesAttribute(Type))
End If
Dim sourceType = TryCast(ContainingSymbol, SourceMemberContainerTypeSymbol)
' if parent is not from source, it must be a frame.
......@@ -68,7 +76,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End If
' Attribute: System.Runtime.CompilerServices.CompilerGeneratedAttribute()
AddSynthesizedAttribute(attributes, sourceType.DeclaringCompilation.TrySynthesizeAttribute(
AddSynthesizedAttribute(attributes, compilation.TrySynthesizeAttribute(
WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor))
End Sub
......
......@@ -131,6 +131,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End If
AddSynthesizedAttribute(attributes, compilation.SynthesizeDebuggerBrowsableNeverAttribute())
If Type.ContainsTupleNames() AndAlso
compilation.HasTupleNamesAttributes AndAlso
compilation.CanEmitSpecialType(SpecialType.System_String) Then
AddSynthesizedAttribute(attributes, compilation.SynthesizeTupleNamesAttribute(Type))
End If
End Sub
Friend Overrides ReadOnly Property HasSpecialName As Boolean
......
......@@ -186,6 +186,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
AddSynthesizedAttribute(attributes, compilation.SynthesizeDebuggerHiddenAttribute())
End Sub
Friend Overrides Sub AddSynthesizedReturnTypeAttributes(ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
MyBase.AddSynthesizedReturnTypeAttributes(attributes)
Dim compilation = Me.DeclaringCompilation
If Me.ReturnType.ContainsTupleNames() AndAlso
compilation.HasTupleNamesAttributes AndAlso
compilation.CanEmitSpecialType(SpecialType.System_String) Then
AddSynthesizedAttribute(attributes, compilation.SynthesizeTupleNamesAttribute(Me.ReturnType))
End If
End Sub
Friend Overrides ReadOnly Property GenerateDebugInfoImpl As Boolean
Get
Return False
......
......@@ -830,6 +830,26 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Private ReadOnly s_isTypeParameterFunc As Func(Of TypeSymbol, Object, Boolean) = Function(type, arg) (type.TypeKind = TypeKind.TypeParameter)
''' <summary>
''' Return true if the type contains any tuples.
''' </summary>
<Extension()>
Friend Function ContainsTuple(type As TypeSymbol) As Boolean
Return type.VisitType(s_isTupleTypeFunc, Nothing) IsNot Nothing
End Function
Private ReadOnly s_isTupleTypeFunc As Func(Of TypeSymbol, Object, Boolean) = Function(type, arg) type.IsTupleType
''' <summary>
''' Return true if the type contains any tuples with element names.
''' </summary>
<Extension()>
Friend Function ContainsTupleNames(type As TypeSymbol) As Boolean
Return type.VisitType(s_hasTupleNamesFunc, Nothing) IsNot Nothing
End Function
Private ReadOnly s_hasTupleNamesFunc As Func(Of TypeSymbol, Object, Boolean) = Function(type, arg) Not type.TupleElementNames.IsDefault
''' <summary>
''' Visit the given type and, in the case of compound types, visit all "sub type"
''' (such as A in A(), or { A(Of T), T, U } in A(Of T).B(Of U)) invoking 'predicate'
......@@ -838,45 +858,77 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' completes without the predicate returning true for any type, this method returns null.
''' </summary>
<Extension()>
Friend Function VisitType(Of T)(this As TypeSymbol, predicate As Func(Of TypeSymbol, T, Boolean), arg As T) As TypeSymbol
Friend Function VisitType(Of T)(type As TypeSymbol, predicate As Func(Of TypeSymbol, T, Boolean), arg As T) As TypeSymbol
' In order to handle extremely "deep" types like "Integer()()()()()()()()()...()"
' we implement manual tail recursion rather than doing the natural recursion.
Select Case this.Kind
Case SymbolKind.TypeParameter
If predicate(this, arg) Then
Return this
End If
Dim current As TypeSymbol = type
Case SymbolKind.ArrayType
If predicate(this, arg) Then
Return this
End If
Do
' Visit containing types from outer-most to inner-most.
Select Case current.TypeKind
Return DirectCast(this, ArrayTypeSymbol).ElementType.VisitType(predicate, arg)
Case TypeKind.Class,
TypeKind.Struct,
TypeKind.Interface,
TypeKind.Enum,
TypeKind.Delegate
Case SymbolKind.NamedType, SymbolKind.ErrorType
Dim typeToCheck = DirectCast(this, NamedTypeSymbol)
Dim containingType = current.ContainingType
If containingType IsNot Nothing Then
Dim result = containingType.VisitType(predicate, arg)
Do
If predicate(typeToCheck, arg) Then
Return typeToCheck
If result IsNot Nothing Then
Return result
End If
End If
Case TypeKind.Submission
Debug.Assert(current.ContainingType Is Nothing)
End Select
If predicate(current, arg) Then
Return current
End If
Select Case current.TypeKind
Case TypeKind.Dynamic,
TypeKind.TypeParameter,
TypeKind.Submission,
TypeKind.Enum,
TypeKind.Module
Return Nothing
Case TypeKind.Class,
TypeKind.Struct,
TypeKind.Interface,
TypeKind.Delegate,
TypeKind.Error
If current.IsTupleType Then
' turn tuple type elements into parameters
current = current.TupleUnderlyingType
End If
For Each typeArg In typeToCheck.TypeArgumentsNoUseSiteDiagnostics
Dim result = typeArg.VisitType(predicate, arg)
For Each nestedType In DirectCast(current, NamedTypeSymbol).TypeArgumentsNoUseSiteDiagnostics
Dim result = nestedType.VisitType(predicate, arg)
If result IsNot Nothing Then
Return result
End If
Next
typeToCheck = typeToCheck.ContainingType
Loop While typeToCheck IsNot Nothing
Return Nothing
Case Else
Throw ExceptionUtilities.UnexpectedValue(this.Kind)
End Select
Case TypeKind.Array
current = DirectCast(current, ArrayTypeSymbol).ElementType
Continue Do
Return Nothing
Case Else
Throw ExceptionUtilities.UnexpectedValue(current.TypeKind)
End Select
Loop
End Function
''' <summary>
......@@ -1266,6 +1318,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return (name.Length = length) AndAlso (String.Compare(name, 0, namespaceName, offset, length, comparison) = 0)
End Function
<Extension>
Friend Function GetTypeRefWithAttributes(type As TypeSymbol, declaringCompilation As VisualBasicCompilation, typeRef As Cci.ITypeReference) As Cci.TypeReferenceWithAttributes
If type.ContainsTupleNames() Then
Dim attr = declaringCompilation.SynthesizeTupleNamesAttribute(type)
If attr IsNot Nothing Then
Return New Cci.TypeReferenceWithAttributes(
typeRef,
ImmutableArray.Create(Of Cci.ICustomAttribute)(attr))
End If
End If
Return New Cci.TypeReferenceWithAttributes(typeRef)
End Function
End Module
End Namespace
......
......@@ -8,7 +8,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Namespace Microsoft.CodeAnalysis.VisualBasic
Public Partial Class VisualBasicCompilation
Partial Public Class VisualBasicCompilation
Private ReadOnly _wellKnownMemberSignatureComparer As New WellKnownMembersSignatureComparer(Me)
......@@ -126,7 +126,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' <summary>
''' Synthesizes a custom attribute.
''' Returns null if the <paramref name="constructor"/> symbol is missing,
''' Returns Nothing if the <paramref name="constructor"/> symbol is missing,
''' or any of the members in <paramref name="namedArguments" /> are missing.
''' The attribute is synthesized only if present.
''' </summary>
......@@ -653,6 +653,72 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return MyBase.MatchTypeToTypeId(type, typeId)
End Function
End Class
Friend Function SynthesizeTupleNamesAttribute(type As TypeSymbol) As SynthesizedAttributeData
Debug.Assert(type IsNot Nothing)
Debug.Assert(type.ContainsTuple())
Dim stringType = GetSpecialType(SpecialType.System_String)
Debug.Assert(stringType IsNot Nothing)
Dim names As ImmutableArray(Of TypedConstant) = TupleNamesEncoder.Encode(type, stringType)
Debug.Assert(Not names.IsDefault, "should not need the attribute when no tuple names")
Dim stringArray = ArrayTypeSymbol.CreateSZArray(stringType, ImmutableArray(Of CustomModifier).Empty, stringType.ContainingAssembly)
Dim args = ImmutableArray.Create(New TypedConstant(stringArray, names))
Return TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_TupleElementNamesAttribute__ctorTransformNames, args)
End Function
Friend Class TupleNamesEncoder
Public Shared Function Encode(type As TypeSymbol) As ImmutableArray(Of String)
Dim namesBuilder = ArrayBuilder(Of String).GetInstance()
If Not TryGetNames(type, namesBuilder) Then
namesBuilder.Free()
Return Nothing
End If
Return namesBuilder.ToImmutableAndFree()
End Function
Public Shared Function Encode(type As TypeSymbol, stringType As TypeSymbol) As ImmutableArray(Of TypedConstant)
Dim namesBuilder = ArrayBuilder(Of String).GetInstance()
If Not TryGetNames(type, namesBuilder) Then
namesBuilder.Free()
Return Nothing
End If
Dim names = namesBuilder.SelectAsArray(Function(name, constantType)
Return New TypedConstant(constantType, TypedConstantKind.Primitive, name)
End Function,
stringType)
namesBuilder.Free()
Return names
End Function
Private Shared Function TryGetNames(type As TypeSymbol, namesBuilder As ArrayBuilder(Of String)) As Boolean
type.VisitType(Function(t As TypeSymbol, builder As ArrayBuilder(Of String)) AddNames(t, builder), namesBuilder)
Debug.Assert(namesBuilder.Any())
Return namesBuilder.Any(Function(name) name IsNot Nothing)
End Function
Private Shared Function AddNames(type As TypeSymbol, namesBuilder As ArrayBuilder(Of String)) As Boolean
If type.IsTupleType Then
If type.TupleElementNames.IsDefaultOrEmpty Then
' If none of the tuple elements have names, put
' null placeholders in.
namesBuilder.AddMany(Nothing, type.TupleElementTypes.Length)
Else
namesBuilder.AddRange(type.TupleElementNames)
End If
End If
' Always recur into nested types
Return False
End Function
End Class
End Class
End Namespace
......@@ -6743,6 +6743,188 @@ End Module
vbexeVerifier.VerifyDiagnostics()
End Sub
<Fact>
Public Sub TupleNamesFromVB001()
Dim classLib = CreateVisualBasicCompilation("VBClass",
<![CDATA[
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks
Namespace ClassLibrary1
Public Class Class1
Public foo As (Alice As Integer, Bob As Integer) = (2, 3)
Public Function Bar() As (Alice As Integer, Bob As Integer)
Return (4, 5)
End Function
Public ReadOnly Property Baz As (Alice As Integer, Bob As Integer)
Get
Return (6, 7)
End Get
End Property
End Class
Public Class Class2
Public foo As (Alice As Integer, q As Integer, w As Integer, e As Integer, f As Integer, g As Integer, h As Integer, j As Integer, Bob As Integer) = SetBob(11)
Public Function Bar() As (Alice As Integer, q As Integer, w As Integer, e As Integer, f As Integer, g As Integer, h As Integer, j As Integer, Bob As Integer)
Return SetBob(12)
End Function
Public ReadOnly Property Baz As (Alice As Integer, q As Integer, w As Integer, e As Integer, f As Integer, g As Integer, h As Integer, j As Integer, Bob As Integer)
Get
Return SetBob(13)
End Get
End Property
Private Shared Function SetBob(x As Integer) As (Alice As Integer, q As Integer, w As Integer, e As Integer, f As Integer, g As Integer, h As Integer, j As Integer, Bob As Integer)
Dim result As (Alice As Integer, q As Integer, w As Integer, e As Integer, f As Integer, g As Integer, h As Integer, j As Integer, Bob As Integer) = Nothing
result.Bob = x
Return result
End Function
End Class
Public Class class3
Implements IEnumerable(Of (Alice As Integer, Bob As Integer))
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Throw New NotImplementedException()
End Function
Public Iterator Function GetEnumerator() As IEnumerator(Of (Alice As Integer, Bob As Integer)) Implements IEnumerable(Of (Alice As Integer, Bob As Integer)).GetEnumerator
Yield (1, 2)
Yield (3, 4)
End Function
End Class
End Namespace
]]>,
compilationOptions:=New Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
referencedAssemblies:=s_valueTupleRefsAndDefault)
Dim vbCompilation = CreateVisualBasicCompilation("VBDll",
<![CDATA[
Module Module1
Sub Main()
Dim x As New ClassLibrary1.Class1
System.Console.WriteLine(x.foo.Alice)
System.Console.WriteLine(x.foo.Bob)
System.Console.WriteLine(x.Bar.Alice)
System.Console.WriteLine(x.Bar.Bob)
System.Console.WriteLine(x.Baz.Alice)
System.Console.WriteLine(x.Baz.Bob)
Dim y As New ClassLibrary1.Class2
System.Console.WriteLine(y.foo.Alice)
System.Console.WriteLine(y.foo.Bob)
System.Console.WriteLine(y.Bar.Alice)
System.Console.WriteLine(y.Bar.Bob)
System.Console.WriteLine(y.Baz.Alice)
System.Console.WriteLine(y.Baz.Bob)
Dim z As New ClassLibrary1.class3
For Each item In z
System.Console.WriteLine(item.Alice)
System.Console.WriteLine(item.Bob)
Next
End Sub
End Module
]]>,
compilationOptions:=New VisualBasicCompilationOptions(OutputKind.ConsoleApplication),
referencedCompilations:={classLib},
referencedAssemblies:=s_valueTupleRefsAndDefault)
Dim vbexeVerifier = CompileAndVerify(vbCompilation,
expectedOutput:="
2
3
4
5
6
7
0
11
0
12
0
13
1
2
3
4")
vbexeVerifier.VerifyDiagnostics()
End Sub
<Fact>
Public Sub TupleNamesFromVB001_InterfaceImpl()
Dim classLib = CreateVisualBasicCompilation("VBClass",
<![CDATA[
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks
Namespace ClassLibrary1
Public Class class3
Implements IEnumerable(Of (Alice As Integer, Bob As Integer))
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Throw New NotImplementedException()
End Function
Private Iterator Function GetEnumerator() As IEnumerator(Of (Alice As Integer, Bob As Integer)) Implements IEnumerable(Of (Alice As Integer, Bob As Integer)).GetEnumerator
Yield (1, 2)
Yield (3, 4)
End Function
End Class
End Namespace
]]>,
compilationOptions:=New Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
referencedAssemblies:=s_valueTupleRefsAndDefault)
Dim vbCompilation = CreateVisualBasicCompilation("VBDll",
<![CDATA[
Module Module1
Sub Main()
Dim z As New ClassLibrary1.class3
For Each item In z
System.Console.WriteLine(item.Alice)
System.Console.WriteLine(item.Bob)
Next
End Sub
End Module
]]>,
compilationOptions:=New VisualBasicCompilationOptions(OutputKind.ConsoleApplication),
referencedCompilations:={classLib},
referencedAssemblies:=s_valueTupleRefsAndDefault)
Dim vbexeVerifier = CompileAndVerify(vbCompilation,
expectedOutput:="
1
2
3
4")
vbexeVerifier.VerifyDiagnostics()
End Sub
<Fact>
Public Sub TupleNamesFromCS002()
......@@ -6822,6 +7004,88 @@ End Module
vbexeVerifier.VerifyDiagnostics()
End Sub
<Fact>
Public Sub TupleNamesFromVB002()
Dim classLib = CreateVisualBasicCompilation("VBClass",
<![CDATA[
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks
Namespace ClassLibrary1
Public Class Class1
Public foo As (Alice As Integer, Bob As (Alice As Integer, Bob As Integer)) = (2, (2, 3))
Public Function Bar() As (Alice As (Alice As Integer, Bob As Integer)(), Bob As Integer)
Return (New(Integer, Integer)() {(4, 5)}, 5)
End Function
Public ReadOnly Property Baz As (Alice As Integer, Bob As List(Of (Alice As Integer, Bob As Integer) ?))
Get
Return (6, New List(Of (Alice As Integer, Bob As Integer) ?)() From {(8, 9)})
End Get
End Property
Public Shared Event foo1 As Action(Of (i0 As Integer, i1 As Integer, i2 As Integer, i3 As Integer, i4 As Integer, i5 As Integer, i6 As Integer, i7 As Integer, Bob As (Alice As Integer, Bob As Integer)))
Public Shared Sub raise()
RaiseEvent foo1((0, 1, 2, 3, 4, 5, 6, 7, (8, 42)))
End Sub
End Class
End Namespace
]]>,
compilationOptions:=New Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
referencedAssemblies:=s_valueTupleRefsAndDefault)
Dim vbCompilation = CreateVisualBasicCompilation("VBDll",
<![CDATA[
Module Module1
Sub Main()
Dim x As New ClassLibrary1.Class1
System.Console.WriteLine(x.foo.Bob.Bob)
System.Console.WriteLine(x.foo.Item2.Item2)
System.Console.WriteLine(x.Bar.Alice(0).Bob)
System.Console.WriteLine(x.Bar.Item1(0).Item2)
System.Console.WriteLine(x.Baz.Bob(0).Value)
System.Console.WriteLine(x.Baz.Item2(0).Value)
AddHandler ClassLibrary1.Class1.foo1, Sub(p)
System.Console.WriteLine(p.Bob.Bob)
System.Console.WriteLine(p.Rest.Item2.Bob)
End Sub
ClassLibrary1.Class1.raise()
End Sub
End Module
]]>,
compilationOptions:=New VisualBasicCompilationOptions(OutputKind.ConsoleApplication),
referencedCompilations:={classLib},
referencedAssemblies:=s_valueTupleRefsAndDefault)
Dim vbexeVerifier = CompileAndVerify(vbCompilation,
expectedOutput:="
3
3
5
5
(8, 9)
(8, 9)
42
42")
vbexeVerifier.VerifyDiagnostics()
End Sub
<Fact>
Public Sub TupleNamesFromCS003()
......@@ -6881,9 +7145,7 @@ End Module
)
End Sub
' Need to port the changes to the tuple field ID from C#
' Otherwise the partially named tuples throw exceptions.
<Fact(Skip:="https://github.com/dotnet/roslyn/issues/13470")>
<Fact>
Public Sub TupleNamesFromCS004()
Dim csCompilation = CreateCSharpCompilation("CSDll",
......@@ -6922,7 +7184,7 @@ Module Module1
Dim f = x.foo
System.Console.WriteLine(f.Item1)
System.Console.WriteLine(f.Item2)
System.Console.WriteLine(x.Item3)
System.Console.WriteLine(f.Item3)
System.Console.WriteLine(f.Alice)
System.Console.WriteLine(f.alice)
......@@ -6936,7 +7198,12 @@ End Module
referencedCompilations:={csCompilation},
referencedAssemblies:=s_valueTupleRefsAndDefault)
vbCompilation.VerifyDiagnostics()
vbCompilation.VerifyDiagnostics(
Diagnostic(ERRID.ERR_MetadataMembersAmbiguous3, "x.foo.Alice").WithArguments("Alice", "structure", "(Alice As Integer, alice As Integer, Integer)").WithLocation(9, 34),
Diagnostic(ERRID.ERR_MetadataMembersAmbiguous3, "x.foo.alice").WithArguments("Alice", "structure", "(Alice As Integer, alice As Integer, Integer)").WithLocation(10, 34),
Diagnostic(ERRID.ERR_MetadataMembersAmbiguous3, "f.Alice").WithArguments("Alice", "structure", "(Alice As Integer, alice As Integer, Integer)").WithLocation(16, 34),
Diagnostic(ERRID.ERR_MetadataMembersAmbiguous3, "f.alice").WithArguments("Alice", "structure", "(Alice As Integer, alice As Integer, Integer)").WithLocation(17, 34)
)
End Sub
<Fact>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册