未验证 提交 dfe146dc 编写于 作者: A AlekseyTs 提交者: GitHub

Add IAssemblySymbol.GetForwardedTypes API. (#44307)

Closes #36274
上级 cff5424c
......@@ -492,16 +492,29 @@ private ImmutableArray<Cci.ExportedType> CalculateExportedTypes()
}
}
Debug.Assert(OutputKind.IsNetModule() == sourceAssembly.DeclaringCompilation.Options.OutputKind.IsNetModule());
GetForwardedTypes(sourceAssembly, builder);
return builder.ToImmutableAndFree();
}
#nullable enable
/// <summary>
/// Returns a set of top-level forwarded types
/// </summary>
internal static HashSet<NamedTypeSymbol> GetForwardedTypes(SourceAssemblySymbol sourceAssembly, ArrayBuilder<Cci.ExportedType>? builder)
{
var seenTopLevelForwardedTypes = new HashSet<NamedTypeSymbol>();
GetForwardedTypes(seenTopLevelForwardedTypes, sourceAssembly.GetSourceDecodedWellKnownAttributeData(), builder);
if (!OutputKind.IsNetModule())
if (!sourceAssembly.DeclaringCompilation.Options.OutputKind.IsNetModule())
{
GetForwardedTypes(seenTopLevelForwardedTypes, sourceAssembly.GetNetModuleDecodedWellKnownAttributeData(), builder);
}
return builder.ToImmutableAndFree();
return seenTopLevelForwardedTypes;
}
#nullable restore
private void ReportExportedTypeNameCollisions(ImmutableArray<Cci.ExportedType> exportedTypes, DiagnosticBag diagnostics)
{
......@@ -568,10 +581,11 @@ private void ReportExportedTypeNameCollisions(ImmutableArray<Cci.ExportedType> e
}
}
#nullable enable
private static void GetForwardedTypes(
HashSet<NamedTypeSymbol> seenTopLevelTypes,
CommonAssemblyWellKnownAttributeData<NamedTypeSymbol> wellKnownAttributeData,
ArrayBuilder<Cci.ExportedType> builder)
ArrayBuilder<Cci.ExportedType>? builder)
{
if (wellKnownAttributeData?.ForwardedTypes?.Count > 0)
{
......@@ -579,7 +593,12 @@ private void ReportExportedTypeNameCollisions(ImmutableArray<Cci.ExportedType> e
var stack = ArrayBuilder<(NamedTypeSymbol type, int parentIndex)>.GetInstance();
// Hashset enumeration is not guaranteed to be deterministic. Emitting in the order of fully qualified names.
var orderedForwardedTypes = wellKnownAttributeData.ForwardedTypes.OrderBy(t => t.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat));
IEnumerable<NamedTypeSymbol> orderedForwardedTypes = wellKnownAttributeData.ForwardedTypes;
if (builder is object)
{
orderedForwardedTypes = orderedForwardedTypes.OrderBy(t => t.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat));
}
foreach (NamedTypeSymbol forwardedType in orderedForwardedTypes)
{
......@@ -590,34 +609,37 @@ private void ReportExportedTypeNameCollisions(ImmutableArray<Cci.ExportedType> e
// level, we need to de-dup the original definitions before emitting.
if (!seenTopLevelTypes.Add(originalDefinition)) continue;
// Return all nested types.
// Note the order: depth first, children in reverse order (to match dev10, not a requirement).
Debug.Assert(stack.Count == 0);
stack.Push((originalDefinition, -1));
while (stack.Count > 0)
if (builder is object)
{
var (type, parentIndex) = stack.Pop();
// Return all nested types.
// Note the order: depth first, children in reverse order (to match dev10, not a requirement).
Debug.Assert(stack.Count == 0);
stack.Push((originalDefinition, -1));
// In general, we don't want private types to appear in the ExportedTypes table.
// BREAK: dev11 emits these types. The problem was discovered in dev10, but failed
// to meet the bar Bug: Dev10/258038 and was left as-is.
if (type.DeclaredAccessibility == Accessibility.Private)
while (stack.Count > 0)
{
// NOTE: this will also exclude nested types of type
continue;
}
var (type, parentIndex) = stack.Pop();
// In general, we don't want private types to appear in the ExportedTypes table.
// BREAK: dev11 emits these types. The problem was discovered in dev10, but failed
// to meet the bar Bug: Dev10/258038 and was left as-is.
if (type.DeclaredAccessibility == Accessibility.Private)
{
// NOTE: this will also exclude nested types of type
continue;
}
// NOTE: not bothering to put nested types in seenTypes - the top-level type is adequate protection.
// NOTE: not bothering to put nested types in seenTypes - the top-level type is adequate protection.
int index = builder.Count;
builder.Add(new Cci.ExportedType(type, parentIndex, isForwarder: true));
int index = builder.Count;
builder.Add(new Cci.ExportedType(type, parentIndex, isForwarder: true));
// Iterate backwards so they get popped in forward order.
ImmutableArray<NamedTypeSymbol> nested = type.GetTypeMembers(); // Ordered.
for (int i = nested.Length - 1; i >= 0; i--)
{
stack.Push((nested[i], index));
// Iterate backwards so they get popped in forward order.
ImmutableArray<NamedTypeSymbol> nested = type.GetTypeMembers(); // Ordered.
for (int i = nested.Length - 1; i >= 0; i--)
{
stack.Push((nested[i], index));
}
}
}
}
......@@ -625,6 +647,7 @@ private void ReportExportedTypeNameCollisions(ImmutableArray<Cci.ExportedType> e
stack.Free();
}
}
#nullable restore
internal IEnumerable<AssemblySymbol> GetReferencedAssembliesUsedSoFar()
{
......
......@@ -382,6 +382,8 @@ internal ErrorTypeSymbol CreateMultipleForwardingErrorTypeSymbol(ref MetadataTyp
return new MissingMetadataTypeSymbol.TopLevel(forwardingModule, ref emittedName, diagnosticInfo);
}
internal abstract IEnumerable<NamedTypeSymbol> GetAllTopLevelForwardedTypes();
/// <summary>
/// Lookup declaration for predefined CorLib type in this Assembly.
/// </summary>
......
......@@ -150,6 +150,11 @@ public override ImmutableArray<CSharpAttributeData> GetAttributes()
return this.PrimaryModule.GetAssembliesForForwardedType(ref emittedName);
}
internal override IEnumerable<NamedTypeSymbol> GetAllTopLevelForwardedTypes()
{
return this.PrimaryModule.GetForwardedTypes();
}
internal override NamedTypeSymbol TryLookupForwardedMetadataTypeWithCycleDetection(ref MetadataTypeName emittedName, ConsList<AssemblySymbol> visitedAssemblies)
{
// Check if it is a forwarded type.
......
......@@ -190,5 +190,10 @@ public override bool MightContainExtensionMethods
}
public override AssemblyMetadata GetMetadata() => null;
internal sealed override IEnumerable<NamedTypeSymbol> GetAllTopLevelForwardedTypes()
{
return SpecializedCollections.EmptyEnumerable<NamedTypeSymbol>();
}
}
}
......@@ -55,6 +55,12 @@ INamedTypeSymbol IAssemblySymbol.ResolveForwardedType(string fullyQualifiedMetad
return UnderlyingAssemblySymbol.ResolveForwardedType(fullyQualifiedMetadataName).GetPublicSymbol();
}
ImmutableArray<INamedTypeSymbol> IAssemblySymbol.GetForwardedTypes()
{
return UnderlyingAssemblySymbol.GetAllTopLevelForwardedTypes().Select(t => t.GetPublicSymbol()).
OrderBy(t => t.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat)).AsImmutable();
}
bool IAssemblySymbol.GivesAccessTo(IAssemblySymbol assemblyWantingAccess)
{
if (Equals(this, assemblyWantingAccess))
......
......@@ -289,6 +289,14 @@ internal override NamedTypeSymbol TryLookupForwardedMetadataTypeWithCycleDetecti
return this.RetargetingTranslator.Retarget(underlying, RetargetOptions.RetargetPrimitiveTypesByName);
}
internal override IEnumerable<NamedTypeSymbol> GetAllTopLevelForwardedTypes()
{
foreach (NamedTypeSymbol underlying in _underlyingAssembly.GetAllTopLevelForwardedTypes())
{
yield return this.RetargetingTranslator.Retarget(underlying, RetargetOptions.RetargetPrimitiveTypesByName);
}
}
public override AssemblyMetadata GetMetadata() => _underlyingAssembly.GetMetadata();
}
}
......@@ -2665,6 +2665,11 @@ internal override NamedTypeSymbol TryLookupForwardedMetadataTypeWithCycleDetecti
return null;
}
internal override IEnumerable<NamedTypeSymbol> GetAllTopLevelForwardedTypes()
{
return PEModuleBuilder.GetForwardedTypes(this, builder: null);
}
public override AssemblyMetadata GetMetadata() => null;
protected override ISymbol CreateISymbol()
......
......@@ -14,6 +14,8 @@
using System.Reflection.PortableExecutable;
using Roslyn.Test.Utilities;
using Xunit;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Emit
{
......@@ -290,8 +292,8 @@ public class GenericType<T> {}
public class GenericType<T, U> {}
}
";
var forwardedToCompilation = CreateEmptyCompilation(forwardedToCode);
var forwardedToReference = new CSharpCompilationReference(forwardedToCompilation);
var forwardedToCompilation1 = CreateCompilation(forwardedToCode, assemblyName: "ForwardedTo");
var forwardedToReference1 = new CSharpCompilationReference(forwardedToCompilation1);
var forwardingCode = @"
using System.Runtime.CompilerServices;
......@@ -308,7 +310,8 @@ public class GenericType<T, U> {}
[assembly: TypeForwardedTo(typeof(Namespace3.GenericType<int, int>))]
";
var forwardingCompilation = CreateCompilation(forwardingCode, new MetadataReference[] { forwardedToReference });
var forwardingCompilation = CreateCompilation(forwardingCode, new MetadataReference[] { forwardedToReference1 });
var forwardingReference = new CSharpCompilationReference(forwardingCompilation);
var sortedFullNames = new string[]
{
......@@ -325,6 +328,14 @@ public class GenericType<T, U> {}
"Namespace4.Embedded.Type2"
};
Action<ModuleSymbol> metadataValidator = module =>
{
var assembly = module.ContainingAssembly;
Assert.Equal(sortedFullNames, getNamesOfForwardedTypes(assembly));
};
CompileAndVerify(forwardingCompilation, symbolValidator: metadataValidator, sourceSymbolValidator: metadataValidator, verify: Verification.Skipped);
using (var stream = forwardingCompilation.EmitToStream())
{
using (var block = ModuleMetadata.CreateFromStream(stream))
......@@ -333,6 +344,29 @@ public class GenericType<T, U> {}
Assert.Equal(sortedFullNames, metadataFullNames);
}
}
var forwardedToCompilation2 = CreateCompilation(forwardedToCode, assemblyName: "ForwardedTo");
var forwardedToReference2 = new CSharpCompilationReference(forwardedToCompilation2);
var withRetargeting = CreateCompilation("", new MetadataReference[] { forwardedToReference2, forwardingReference });
var retargeting = (RetargetingAssemblySymbol)withRetargeting.GetReferencedAssemblySymbol(forwardingReference);
Assert.Equal(sortedFullNames, getNamesOfForwardedTypes(retargeting));
foreach (var type in getForwardedTypes(retargeting))
{
Assert.Same(forwardedToCompilation2.Assembly.GetPublicSymbol(), type.ContainingAssembly);
}
static IEnumerable<string> getNamesOfForwardedTypes(AssemblySymbol assembly)
{
return getForwardedTypes(assembly).Select(t => t.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat));
}
static ImmutableArray<INamedTypeSymbol> getForwardedTypes(AssemblySymbol assembly)
{
return assembly.GetPublicSymbol().GetForwardedTypes();
}
}
[ConditionalFact(typeof(ClrOnly), Reason = "Static execution is runtime defined and this tests Clr behavior only")]
......
......@@ -753,6 +753,8 @@ static void Main()
// (2,7): error CS0012: The type 'Base' is defined in an assembly that is not referenced. You must add a reference to assembly 'pe3, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// class Test : Derived
Diagnostic(ErrorCode.ERR_NoTypeDef, "Derived").WithArguments("Base", "pe3, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"));
Assert.Empty(comp3.GetReferencedAssemblySymbol(ref2).Modules[0].ReferencedAssemblySymbols.OfType<MissingAssemblySymbol>().First().GetPublicSymbol().GetForwardedTypes());
}
[Fact]
......@@ -1459,7 +1461,10 @@ private void CheckForwarderEmit(string source1, string source2, params string[]
var assembly = module.ContainingAssembly;
// Attributes should not actually be emitted.
Assert.Equal(0, assembly.GetAttributes(AttributeDescription.TypeForwardedToAttribute).Count());
if (module is PEModuleSymbol)
{
Assert.Equal(0, assembly.GetAttributes(AttributeDescription.TypeForwardedToAttribute).Count());
}
var topLevelTypes = new HashSet<string>();
......@@ -1484,9 +1489,11 @@ private void CheckForwarderEmit(string source1, string source2, params string[]
Assert.NotEqual(TypeKind.Error, type.TypeKind);
Assert.Equal("Asm1", type.ContainingAssembly.Name);
}
Assert.Equal(topLevelTypes.OrderBy(s => s), GetNamesOfForwardedTypes(assembly));
};
var verifier2 = CompileAndVerify(comp2, symbolValidator: metadataValidator);
var verifier2 = CompileAndVerify(comp2, symbolValidator: metadataValidator, sourceSymbolValidator: metadataValidator);
using (ModuleMetadata metadata = ModuleMetadata.CreateFromImage(verifier2.EmittedAssemblyData))
{
......@@ -1503,6 +1510,16 @@ private void CheckForwarderEmit(string source1, string source2, params string[]
}
}
private static IEnumerable<string> GetNamesOfForwardedTypes(AssemblySymbol assembly)
{
return GetNamesOfForwardedTypes(assembly.GetPublicSymbol());
}
private static IEnumerable<string> GetNamesOfForwardedTypes(IAssemblySymbol assembly)
{
return assembly.GetForwardedTypes().Select(t => t.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat));
}
[WorkItem(545911, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545911")]
[ConditionalFact(typeof(DesktopOnly), typeof(ClrOnly))]
public void EmitForwarder_ModuleInReferencedAssembly()
......@@ -1592,6 +1609,8 @@ public class CF1
var modCompilation = CreateCompilation(mod, references: new[] { new CSharpCompilationReference(forwardedTypesCompilation) }, options: TestOptions.ReleaseModule);
var modRef1 = modCompilation.EmitToImageReference();
Assert.Equal(new[] { "CF1" }, GetNamesOfForwardedTypes(modCompilation.Assembly));
string app =
@"
public class Test { }
......@@ -1599,6 +1618,8 @@ public class Test { }
var appCompilation = CreateCompilation(app, references: new[] { modRef1, new CSharpCompilationReference(forwardedTypesCompilation) }, options: TestOptions.ReleaseDll);
Assert.Equal(new[] { "CF1" }, GetNamesOfForwardedTypes(appCompilation.Assembly));
var module = (PEModuleSymbol)appCompilation.Assembly.Modules[1];
var metadata = module.Module;
......
......@@ -110,5 +110,10 @@ internal override NamedTypeSymbol TryLookupForwardedMetadataTypeWithCycleDetecti
}
public override AssemblyMetadata GetMetadata() => null;
internal override IEnumerable<NamedTypeSymbol> GetAllTopLevelForwardedTypes()
{
throw new NotImplementedException();
}
}
}
Microsoft.CodeAnalysis.Compilation.CreateNativeIntegerTypeSymbol(bool signed) -> Microsoft.CodeAnalysis.INamedTypeSymbol
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.AssemblyLoader.get -> Microsoft.CodeAnalysis.IAnalyzerAssemblyLoader
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.Equals(Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference other) -> bool
Microsoft.CodeAnalysis.IAssemblySymbol.GetForwardedTypes() -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.INamedTypeSymbol>
Microsoft.CodeAnalysis.INamedTypeSymbol.NativeIntegerUnderlyingType.get -> Microsoft.CodeAnalysis.INamedTypeSymbol
Microsoft.CodeAnalysis.ITypeSymbol.IsNativeIntegerType.get -> bool
Microsoft.CodeAnalysis.OperationKind.BinaryPattern = 110 -> Microsoft.CodeAnalysis.OperationKind
......
......@@ -5,6 +5,7 @@
#nullable enable
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis
......@@ -76,6 +77,11 @@ public interface IAssemblySymbol : ISymbol
/// </summary>
INamedTypeSymbol? ResolveForwardedType(string fullyQualifiedMetadataName);
/// <summary>
/// Returns type symbols for top-level (non-nested) types forwarded by this assembly.
/// </summary>
ImmutableArray<INamedTypeSymbol> GetForwardedTypes();
/// <summary>
/// If this symbol represents a metadata assembly returns the underlying <see cref="AssemblyMetadata"/>.
///
......
......@@ -832,6 +832,10 @@ Friend Class MockAssemblySymbol
Return Nothing
End Function
Friend Overrides Function GetAllTopLevelForwardedTypes() As IEnumerable(Of NamedTypeSymbol)
Throw New NotImplementedException()
End Function
Public Overrides Function GetMetadata() As AssemblyMetadata
Return Nothing
End Function
......
......@@ -404,14 +404,23 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Next
End If
Debug.Assert(OutputKind.IsNetModule() = sourceAssembly.DeclaringCompilation.Options.OutputKind.IsNetModule())
GetForwardedTypes(sourceAssembly, builder)
Return builder.ToImmutableAndFree()
End Function
''' <summary>
''' Returns a set of top-level forwarded types
''' </summary>
Friend Shared Function GetForwardedTypes(sourceAssembly As SourceAssemblySymbol, builderOpt As ArrayBuilder(Of Cci.ExportedType)) As HashSet(Of NamedTypeSymbol)
Dim seenTopLevelForwardedTypes = New HashSet(Of NamedTypeSymbol)()
GetForwardedTypes(seenTopLevelForwardedTypes, sourceAssembly.GetSourceDecodedWellKnownAttributeData(), builder)
GetForwardedTypes(seenTopLevelForwardedTypes, sourceAssembly.GetSourceDecodedWellKnownAttributeData(), builderOpt)
If Not OutputKind.IsNetModule() Then
GetForwardedTypes(seenTopLevelForwardedTypes, sourceAssembly.GetNetModuleDecodedWellKnownAttributeData(), builder)
If Not sourceAssembly.DeclaringCompilation.Options.OutputKind.IsNetModule() Then
GetForwardedTypes(seenTopLevelForwardedTypes, sourceAssembly.GetNetModuleDecodedWellKnownAttributeData(), builderOpt)
End If
Return builder.ToImmutableAndFree()
Return seenTopLevelForwardedTypes
End Function
Private Sub ReportExportedTypeNameCollisions(exportedTypes As ImmutableArray(Of Cci.ExportedType), diagnostics As DiagnosticBag)
......@@ -506,14 +515,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Private Shared Sub GetForwardedTypes(
seenTopLevelTypes As HashSet(Of NamedTypeSymbol),
wellKnownAttributeData As CommonAssemblyWellKnownAttributeData(Of NamedTypeSymbol),
builder As ArrayBuilder(Of Cci.ExportedType))
builderOpt As ArrayBuilder(Of Cci.ExportedType))
If wellKnownAttributeData?.ForwardedTypes?.Count > 0 Then
' (type, index of the parent exported type in builder, or -1 if the type is a top-level type)
Dim stack = ArrayBuilder(Of (type As NamedTypeSymbol, parentIndex As Integer)).GetInstance()
' Hashset enumeration is not guaranteed to be deterministic. Emitting in the order of fully qualified names.
Dim orderedForwardedTypes = wellKnownAttributeData.ForwardedTypes.OrderBy(Function(t) t.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat))
Dim orderedForwardedTypes As IEnumerable(Of NamedTypeSymbol) = wellKnownAttributeData.ForwardedTypes
If builderOpt IsNot Nothing Then
orderedForwardedTypes = orderedForwardedTypes.OrderBy(Function(t) t.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat))
End If
For Each forwardedType As NamedTypeSymbol In orderedForwardedTypes
Dim originalDefinition As NamedTypeSymbol = forwardedType.OriginalDefinition
......@@ -524,31 +537,32 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Continue For
End If
' Return all nested types.
' Note the order: depth first, children in reverse order (to match dev10, not a requirement).
Debug.Assert(stack.Count = 0)
stack.Push((originalDefinition, -1))
While stack.Count > 0
Dim entry = stack.Pop()
' In general, we don't want private types to appear in the ExportedTypes table.
If entry.type.DeclaredAccessibility = Accessibility.Private Then
' NOTE: this will also exclude nested types of curr.
Continue While
End If
' NOTE: not bothering to put nested types in seenTypes - the top-level type is adequate protection.
Dim index = builder.Count
builder.Add(New Cci.ExportedType(entry.type, entry.parentIndex, isForwarder:=True))
' Iterate backwards so they get popped in forward order.
Dim nested As ImmutableArray(Of NamedTypeSymbol) = entry.type.GetTypeMembers() ' Ordered.
For i As Integer = nested.Length - 1 To 0 Step -1
stack.Push((nested(i), index))
Next
End While
If builderOpt IsNot Nothing Then
' Return all nested types.
' Note the order: depth first, children in reverse order (to match dev10, not a requirement).
Debug.Assert(stack.Count = 0)
stack.Push((originalDefinition, -1))
While stack.Count > 0
Dim entry = stack.Pop()
' In general, we don't want private types to appear in the ExportedTypes table.
If entry.type.DeclaredAccessibility = Accessibility.Private Then
' NOTE: this will also exclude nested types of curr.
Continue While
End If
' NOTE: not bothering to put nested types in seenTypes - the top-level type is adequate protection.
Dim index = builderOpt.Count
builderOpt.Add(New Cci.ExportedType(entry.type, entry.parentIndex, isForwarder:=True))
' Iterate backwards so they get popped in forward order.
Dim nested As ImmutableArray(Of NamedTypeSymbol) = entry.type.GetTypeMembers() ' Ordered.
For i As Integer = nested.Length - 1 To 0 Step -1
stack.Push((nested(i), index))
Next
End While
End If
Next
stack.Free()
......
......@@ -310,6 +310,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return New MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(forwardingModule, emittedName, diagnosticInfo)
End Function
Friend MustOverride Function GetAllTopLevelForwardedTypes() As IEnumerable(Of NamedTypeSymbol)
''' <summary>
''' Lookup declaration for predefined CorLib type in this Assembly. Only valid if this
''' assembly is the Cor Library
......@@ -643,6 +645,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return Me.ResolveForwardedType(metadataName)
End Function
Private Function IAssemblySymbol_GetForwardedTypes() As ImmutableArray(Of INamedTypeSymbol) Implements IAssemblySymbol.GetForwardedTypes
Return ImmutableArrayExtensions.AsImmutable(Of INamedTypeSymbol)(GetAllTopLevelForwardedTypes().OrderBy(Function(t) t.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat)))
End Function
Private Function IAssemblySymbol_GetTypeByMetadataName(metadataName As String) As INamedTypeSymbol Implements IAssemblySymbol.GetTypeByMetadataName
Return Me.GetTypeByMetadataName(metadataName)
End Function
......
......@@ -163,6 +163,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Return PrimaryModule.GetAssembliesForForwardedType(emittedName, ignoreCase, matchedName)
End Function
Friend Overrides Function GetAllTopLevelForwardedTypes() As IEnumerable(Of NamedTypeSymbol)
Return PrimaryModule.GetForwardedTypes()
End Function
Friend Overrides Function TryLookupForwardedMetadataTypeWithCycleDetection(ByRef emittedName As MetadataTypeName, visitedAssemblies As ConsList(Of AssemblySymbol), ignoreCase As Boolean) As NamedTypeSymbol
' Check if it is a forwarded type.
Dim matchedName As String = Nothing
......
......@@ -142,6 +142,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return result
End Function
Friend NotOverridable Overrides Function GetAllTopLevelForwardedTypes() As IEnumerable(Of NamedTypeSymbol)
Return SpecializedCollections.EmptyEnumerable(Of NamedTypeSymbol)()
End Function
Friend Overrides Function GetDeclaredSpecialType(type As SpecialType) As NamedTypeSymbol
Throw ExceptionUtilities.Unreachable
End Function
......
......@@ -255,6 +255,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting
Return Me.RetargetingTranslator.Retarget(underlying, RetargetOptions.RetargetPrimitiveTypesByName)
End Function
Friend Overrides Iterator Function GetAllTopLevelForwardedTypes() As IEnumerable(Of NamedTypeSymbol)
For Each underlying As NamedTypeSymbol In UnderlyingAssembly.GetAllTopLevelForwardedTypes()
Yield Me.RetargetingTranslator.Retarget(underlying, RetargetOptions.RetargetPrimitiveTypesByName)
Next
End Function
Public Overrides Function GetMetadata() As AssemblyMetadata
Return _underlyingAssembly.GetMetadata()
End Function
......
......@@ -435,6 +435,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Debug.Assert(lazyNetModuleAttributesBag.IsSealed)
End Sub
Friend Overrides Function GetAllTopLevelForwardedTypes() As IEnumerable(Of NamedTypeSymbol)
Return Emit.PEModuleBuilder.GetForwardedTypes(Me, builderOpt:=Nothing)
End Function
Private Sub EnsureNetModuleAttributesAreBound()
If _lazyNetModuleAttributesBag Is Nothing Then
LoadAndValidateNetModuleAttributes(_lazyNetModuleAttributesBag)
......
......@@ -9,6 +9,7 @@ Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Roslyn.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Emit
......@@ -168,11 +169,11 @@ namespace Namespace3 {
public class GenericType<T, U> {}
}
"
Dim forwardedToCompilation = CreateCSharpCompilation(
forwardedToCode,
Dim forwardedToCompilation1 = CreateCSharpCompilation(
forwardedToCode, assemblyName:="ForwardedTo",
compilationOptions:=New CSharp.CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
Dim forwardedToReference = forwardedToCompilation.EmitToImageReference()
Dim forwardedToReference1 = forwardedToCompilation1.EmitToImageReference()
Dim forwardingCode = "
using System.Runtime.CompilerServices;
......@@ -192,7 +193,7 @@ using System.Runtime.CompilerServices;
"ForwardingAssembly",
forwardingCode,
compilationOptions:=New CSharp.CSharpCompilationOptions(OutputKind.NetModule),
referencedAssemblies:={MscorlibRef, SystemRef, forwardedToReference})
referencedAssemblies:={MscorlibRef, SystemRef, forwardedToReference1})
Dim forwardingNetModuleReference = forwardingNetModule.EmitToImageReference()
......@@ -200,7 +201,8 @@ using System.Runtime.CompilerServices;
assemblyName:="ForwardingAssembly",
source:=String.Empty,
options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
references:={forwardingNetModuleReference, forwardedToReference})
references:={forwardingNetModuleReference, forwardedToReference1})
Dim forwardingReference = new VisualBasicCompilationReference(forwardingCompilation)
Dim sortedFullNames =
{
......@@ -217,14 +219,48 @@ using System.Runtime.CompilerServices;
"Namespace4.Embedded.Type2"
}
Dim metadataValidator As Action(Of ModuleSymbol) = Sub(m)
Dim assembly = m.ContainingAssembly
Assert.Equal(sortedFullNames, GetNamesOfForwardedTypes(assembly))
End Sub
CompileAndVerify(forwardingCompilation, symbolValidator:=metadataValidator, sourceSymbolValidator:=metadataValidator, verify:=Verification.Skipped)
Using stream = forwardingCompilation.EmitToStream()
Using block = ModuleMetadata.CreateFromStream(stream)
Dim metadataFullNames = MetadataValidation.GetExportedTypesFullNames(block.MetadataReader)
Assert.Equal(sortedFullNames, metadataFullNames)
End Using
End Using
Dim forwardedToCompilation2 = CreateCSharpCompilation(
forwardedToCode, assemblyName:="ForwardedTo",
compilationOptions:=New CSharp.CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
Dim forwardedToReference2 = forwardedToCompilation2.EmitToImageReference()
Dim withRetargeting = CreateCompilationWithMscorlib40(
source:=String.Empty,
options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
references:={forwardedToReference2, forwardingReference})
Dim retargeting = DirectCast(withRetargeting.GetReferencedAssemblySymbol(forwardingReference), Retargeting.RetargetingAssemblySymbol)
Dim orwardedToAssembly2 = withRetargeting.GetReferencedAssemblySymbol(forwardedToReference2)
Assert.Equal(sortedFullNames, GetNamesOfForwardedTypes(retargeting))
For Each t In GetForwardedTypes(retargeting)
Assert.Same(orwardedToAssembly2, t.ContainingAssembly)
Next
End Sub
Private Shared Function GetNamesOfForwardedTypes(assembly As AssemblySymbol) As IEnumerable(Of String)
Return GetForwardedTypes(assembly).Select(Function(t) t.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat))
End Function
Private Shared Function GetForwardedTypes(assembly As AssemblySymbol) As IEnumerable(Of INamedTypeSymbol)
Return DirectCast(assembly, IAssemblySymbol).GetForwardedTypes()
End Function
<Fact>
Public Sub TestInterfacesPartialClassDeterminism()
' When we have parts of a class in different trees,
......
......@@ -478,6 +478,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Symbols.Metadata.PE
Assert.True(missingAssembly.Equals(missingAssembly))
Assert.NotEqual(New Object(), missingAssembly)
Assert.False(missingAssembly.Equals(Nothing))
Assert.Empty(DirectCast(missingAssembly, IAssemblySymbol).GetForwardedTypes())
End Sub
......
......@@ -1035,6 +1035,8 @@ End class
appCompilation = CreateCompilationWithMscorlib40AndReferences(app, {modRef1, New VisualBasicCompilationReference(forwardedTypesCompilation)}, TestOptions.ReleaseDll)
Assert.Equal({"CF1"}, GetNamesOfForwardedTypes(appCompilation))
peModule = DirectCast(appCompilation.Assembly.Modules(1), PEModuleSymbol)
metadata = peModule.Module
......@@ -1051,6 +1053,7 @@ End class
Dim metadataReader1 = DirectCast(m, PEModuleSymbol).Module.GetMetadataReader()
Assert.Equal(1, metadataReader1.GetTableRowCount(TableIndex.ExportedType))
ValidateExportedTypeRow(metadataReader1.ExportedTypes.First(), metadataReader1, "CF1")
Assert.Equal({"CF1"}, GetNamesOfForwardedTypes(m.ContainingAssembly))
' Attributes should not actually be emitted.
Assert.Equal(0, m.ContainingAssembly.GetAttributes(AttributeDescription.TypeForwardedToAttribute).Count())
......@@ -1131,6 +1134,14 @@ BC30652: Reference required to assembly 'ForwarderTargetAssembly, Version=0.0.0.
</expected>)
End Sub
Private Shared Function GetNamesOfForwardedTypes(appCompilation As VisualBasicCompilation) As IEnumerable(Of String)
Return GetNamesOfForwardedTypes(appCompilation.Assembly)
End Function
Private Shared Function GetNamesOfForwardedTypes(assembly As AssemblySymbol) As IEnumerable(Of String)
Return DirectCast(assembly, IAssemblySymbol).GetForwardedTypes().Select(Function(t) t.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat))
End Function
Private Shared Sub ValidateExportedTypeRow(exportedTypeHandle As ExportedTypeHandle, reader As MetadataReader, expectedFullName As String)
Dim exportedTypeRow As ExportedType = reader.GetExportedType(exportedTypeHandle)
Dim split = expectedFullName.Split("."c)
......@@ -1212,11 +1223,13 @@ End class
</compilation>
Dim appCompilation = CreateCompilationWithMscorlib40AndReferences(app, {modRef, New VisualBasicCompilationReference(forwardedTypesCompilation)}, TestOptions.ReleaseDll)
Assert.Equal({"CF1"}, GetNamesOfForwardedTypes(appCompilation))
' Exported types in .NET module cause PEVerify to fail.
CompileAndVerify(appCompilation, verify:=Verification.Fails,
symbolValidator:=Sub(m)
Dim peReader1 = DirectCast(m, PEModuleSymbol).Module.GetMetadataReader()
Assert.Equal({"CF1"}, GetNamesOfForwardedTypes(m.ContainingAssembly))
Assert.Equal(2, peReader1.GetTableRowCount(TableIndex.ExportedType))
ValidateExportedTypeRow(peReader1.ExportedTypes.First(), peReader1, "CF1")
ValidateExportedTypeRow(peReader1.ExportedTypes(1), peReader1, "CF1+CF2")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册