-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Find the right symbol when following type forwards #62406
Changes from 12 commits
731ef67
f199e1f
5265792
81d06b3
9cc43b9
67132d1
07125d1
8583e64
416f459
927e2c0
5fd9a3d
5b458f1
8c5fd03
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -457,6 +457,50 @@ public class C | |
{ | ||
} | ||
} | ||
"; | ||
|
||
await RunTestAsync(async path => | ||
{ | ||
MarkupTestFile.GetSpan(source, out var metadataSource, out var expectedSpan); | ||
|
||
var packDir = Directory.CreateDirectory(Path.Combine(path, "packs", "MyPack.Ref", "1.0", "ref", "net6.0")).FullName; | ||
var dataDir = Directory.CreateDirectory(Path.Combine(path, "packs", "MyPack.Ref", "1.0", "data")).FullName; | ||
var sharedDir = Directory.CreateDirectory(Path.Combine(path, "shared", "MyPack", "1.0")).FullName; | ||
|
||
var sourceText = SourceText.From(metadataSource, Encoding.UTF8); | ||
var (project, symbol) = await CompileAndFindSymbolAsync(packDir, Location.Embedded, Location.Embedded, sourceText, c => c.GetMember("C.M"), buildReferenceAssembly: true); | ||
|
||
var workspace = TestWorkspace.Create(@$" | ||
<Workspace> | ||
<Project Language=""{LanguageNames.CSharp}"" CommonReferences=""true"" ReferencesOnDisk=""true""> | ||
</Project> | ||
</Workspace>", composition: GetTestComposition()); | ||
|
||
var implProject = workspace.CurrentSolution.Projects.First(); | ||
|
||
// Compile implementation assembly | ||
CompileTestSource(sharedDir, sourceText, project, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); | ||
|
||
// Create FrameworkList.xml | ||
File.WriteAllText(Path.Combine(dataDir, "FrameworkList.xml"), """ | ||
<FileList FrameworkName="MyPack"> | ||
</FileList> | ||
"""); | ||
|
||
await GenerateFileAndVerifyAsync(project, symbol, Location.Embedded, metadataSource.ToString(), expectedSpan, expectNullResult: false); | ||
}); | ||
} | ||
|
||
[Fact] | ||
public async Task Net6SdkLayout_TypeForward() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test is actually entirely new, and correctly tests type forwards, in the manner that the .NET sdk uses them. This test fails without the changes in this PR. |
||
{ | ||
var source = @" | ||
public class [|C|] | ||
{ | ||
public void M(string d) | ||
{ | ||
} | ||
} | ||
"; | ||
var typeForwardSource = @" | ||
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(C))] | ||
|
@@ -471,7 +515,7 @@ public class C | |
var sharedDir = Directory.CreateDirectory(Path.Combine(path, "shared", "MyPack", "1.0")).FullName; | ||
|
||
var sourceText = SourceText.From(metadataSource, Encoding.UTF8); | ||
var (project, symbol) = await CompileAndFindSymbolAsync(packDir, Location.Embedded, Location.Embedded, sourceText, c => c.GetMember("C.M"), buildReferenceAssembly: true); | ||
var (project, symbol) = await CompileAndFindSymbolAsync(packDir, Location.Embedded, Location.Embedded, sourceText, c => c.GetMember("C"), buildReferenceAssembly: true); | ||
|
||
var workspace = TestWorkspace.Create(@$" | ||
<Workspace> | ||
|
@@ -482,15 +526,20 @@ public class C | |
var implProject = workspace.CurrentSolution.Projects.First(); | ||
|
||
// Compile implementation assembly | ||
CompileTestSource(sharedDir, sourceText, project, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); | ||
var implementationDllFilePath = Path.Combine(sharedDir, "implementation.dll"); | ||
var sourceCodePath = Path.Combine(sharedDir, "implementation.cs"); | ||
var pdbFilePath = Path.Combine(sharedDir, "implementation.pdb"); | ||
var assemblyName = "implementation"; | ||
|
||
CompileTestSource(implementationDllFilePath, sourceCodePath, pdbFilePath, assemblyName, sourceText, project, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); | ||
|
||
// Compile type forwarding implementation DLL | ||
var typeForwardDllFilePath = Path.Combine(sharedDir, "typeforward.dll"); | ||
var sourceCodePath = Path.Combine(sharedDir, "typeforward.cs"); | ||
var pdbFilePath = Path.Combine(sharedDir, "typeforward.pdb"); | ||
var assemblyName = "typeforward"; | ||
// Compile type forwarding implementation DLL, that looks like reference.dll | ||
var typeForwardDllFilePath = Path.Combine(sharedDir, "reference.dll"); | ||
sourceCodePath = Path.Combine(sharedDir, "reference.cs"); | ||
pdbFilePath = Path.Combine(sharedDir, "reference.pdb"); | ||
assemblyName = "reference"; | ||
|
||
implProject = implProject.AddMetadataReference(MetadataReference.CreateFromFile(GetDllPath(sharedDir))); | ||
implProject = implProject.AddMetadataReference(MetadataReference.CreateFromFile(implementationDllFilePath)); | ||
sourceText = SourceText.From(typeForwardSource, Encoding.UTF8); | ||
CompileTestSource(typeForwardDllFilePath, sourceCodePath, pdbFilePath, assemblyName, sourceText, implProject, Location.Embedded, Location.Embedded, buildReferenceAssembly: false, windowsPdb: false); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,11 @@ public bool TryFindImplementationAssemblyPath(string referencedDllPath, [NotNull | |
// Only the top most containing type in the ExportedType table actually points to an assembly | ||
// so no point looking for nested types. | ||
var typeSymbol = MetadataAsSourceHelpers.GetTopLevelContainingNamedType(symbol); | ||
// We need to generate the namespace name in the same format that is used in metadata, which | ||
// is SymbolDisplayFormat.QualifiedNameOnlyFormat, which this is a copy of. | ||
var namespaceName = typeSymbol.ContainingNamespace.ToDisplayString(new SymbolDisplayFormat( | ||
globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, | ||
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider storing the format in a static field. |
||
|
||
try | ||
{ | ||
|
@@ -66,7 +71,7 @@ public bool TryFindImplementationAssemblyPath(string referencedDllPath, [NotNull | |
{ | ||
// If there are no type forwards in this DLL, or not one for this type, then it means | ||
// we've found the right DLL | ||
if (typeForwards?.TryGetValue((typeSymbol.ContainingNamespace.MetadataName, typeSymbol.MetadataName), out var assemblyName) != true) | ||
if (typeForwards?.TryGetValue((namespaceName, typeSymbol.MetadataName), out var assemblyName) != true) | ||
{ | ||
return dllPath; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The diff on this is weird. This test is actually old, just with a few bits of code removed. This wasn't testing type forwards at all, but their presence made me think I was correctly testing them.. which I wasn't!