-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Support duplicated type names with src gen #58448
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
Merged
steveharter
merged 2 commits into
dotnet:main
from
steveharter:RemoveGetTypeByMetadataName
Sep 7, 2021
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
138 changes: 138 additions & 0 deletions
138
src/libraries/Common/src/Roslyn/GetBestTypeByMetadataName.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using Microsoft.CodeAnalysis; | ||
|
|
||
| namespace System.Text.Json.Reflection | ||
| { | ||
| internal static partial class RoslynExtensions | ||
| { | ||
| // Copied from: https://github.com/dotnet/roslyn/blob/main/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/CompilationExtensions.cs | ||
| /// <summary> | ||
| /// Gets a type by its metadata name to use for code analysis within a <see cref="Compilation"/>. This method | ||
| /// attempts to find the "best" symbol to use for code analysis, which is the symbol matching the first of the | ||
| /// following rules. | ||
| /// | ||
| /// <list type="number"> | ||
| /// <item><description> | ||
| /// If only one type with the given name is found within the compilation and its referenced assemblies, that | ||
| /// type is returned regardless of accessibility. | ||
| /// </description></item> | ||
| /// <item><description> | ||
| /// If the current <paramref name="compilation"/> defines the symbol, that symbol is returned. | ||
| /// </description></item> | ||
| /// <item><description> | ||
| /// If exactly one referenced assembly defines the symbol in a manner that makes it visible to the current | ||
| /// <paramref name="compilation"/>, that symbol is returned. | ||
| /// </description></item> | ||
| /// <item><description> | ||
| /// Otherwise, this method returns <see langword="null"/>. | ||
| /// </description></item> | ||
| /// </list> | ||
| /// </summary> | ||
| /// <param name="compilation">The <see cref="Compilation"/> to consider for analysis.</param> | ||
| /// <param name="fullyQualifiedMetadataName">The fully-qualified metadata type name to find.</param> | ||
| /// <returns>The symbol to use for code analysis; otherwise, <see langword="null"/>.</returns> | ||
| public static INamedTypeSymbol? GetBestTypeByMetadataName(this Compilation compilation, string fullyQualifiedMetadataName) | ||
| { | ||
| // Try to get the unique type with this name, ignoring accessibility | ||
| var type = compilation.GetTypeByMetadataName(fullyQualifiedMetadataName); | ||
|
|
||
| // Otherwise, try to get the unique type with this name originally defined in 'compilation' | ||
| type ??= compilation.Assembly.GetTypeByMetadataName(fullyQualifiedMetadataName); | ||
|
|
||
| // Otherwise, try to get the unique accessible type with this name from a reference | ||
| if (type is null) | ||
| { | ||
| foreach (var module in compilation.Assembly.Modules) | ||
| { | ||
| foreach (var referencedAssembly in module.ReferencedAssemblySymbols) | ||
| { | ||
| var currentType = referencedAssembly.GetTypeByMetadataName(fullyQualifiedMetadataName); | ||
| if (currentType is null) | ||
| continue; | ||
|
|
||
| switch (currentType.GetResultantVisibility()) | ||
| { | ||
| case SymbolVisibility.Public: | ||
| case SymbolVisibility.Internal when referencedAssembly.GivesAccessTo(compilation.Assembly): | ||
| break; | ||
|
|
||
| default: | ||
| continue; | ||
| } | ||
|
|
||
| if (type is object) | ||
| { | ||
| // Multiple visible types with the same metadata name are present | ||
| return null; | ||
| } | ||
|
|
||
| type = currentType; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return type; | ||
| } | ||
|
|
||
| // copied from https://github.com/dotnet/roslyn/blob/main/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs | ||
| private static SymbolVisibility GetResultantVisibility(this ISymbol symbol) | ||
| { | ||
| // Start by assuming it's visible. | ||
| SymbolVisibility visibility = SymbolVisibility.Public; | ||
|
|
||
| switch (symbol.Kind) | ||
| { | ||
| case SymbolKind.Alias: | ||
| // Aliases are uber private. They're only visible in the same file that they | ||
| // were declared in. | ||
| return SymbolVisibility.Private; | ||
|
|
||
| case SymbolKind.Parameter: | ||
| // Parameters are only as visible as their containing symbol | ||
| return GetResultantVisibility(symbol.ContainingSymbol); | ||
|
|
||
| case SymbolKind.TypeParameter: | ||
| // Type Parameters are private. | ||
| return SymbolVisibility.Private; | ||
| } | ||
|
|
||
| while (symbol != null && symbol.Kind != SymbolKind.Namespace) | ||
| { | ||
| switch (symbol.DeclaredAccessibility) | ||
| { | ||
| // If we see anything private, then the symbol is private. | ||
| case Accessibility.NotApplicable: | ||
| case Accessibility.Private: | ||
| return SymbolVisibility.Private; | ||
|
|
||
| // If we see anything internal, then knock it down from public to | ||
| // internal. | ||
| case Accessibility.Internal: | ||
| case Accessibility.ProtectedAndInternal: | ||
| visibility = SymbolVisibility.Internal; | ||
| break; | ||
|
|
||
| // For anything else (Public, Protected, ProtectedOrInternal), the | ||
| // symbol stays at the level we've gotten so far. | ||
| } | ||
|
|
||
| symbol = symbol.ContainingSymbol; | ||
| } | ||
|
|
||
| return visibility; | ||
| } | ||
|
|
||
| // Copied from: https://github.com/dotnet/roslyn/blob/main/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/SymbolVisibility.cs | ||
| #pragma warning disable CA1027 // Mark enums with FlagsAttribute | ||
| private enum SymbolVisibility | ||
| #pragma warning restore CA1027 // Mark enums with FlagsAttribute | ||
| { | ||
| Public = 0, | ||
| Internal = 1, | ||
| Private = 2, | ||
| Friend = Internal, | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Very minor nit: this could have been a helper method.
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.
Thanks; left as-is. Note there are other tests that have the same pattern.