diff --git a/src/EditorFeatures/CSharpTest/CodeLens/CSharpCodeLensTests.cs b/src/EditorFeatures/CSharpTest/CodeLens/CSharpCodeLensTests.cs index 51a0cfe5d808d..5a71653ae852c 100644 --- a/src/EditorFeatures/CSharpTest/CodeLens/CSharpCodeLensTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeLens/CSharpCodeLensTests.cs @@ -402,4 +402,54 @@ internal partial class Program """; await RunMethodReferenceTest(input); } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/64592")] + public async Task TestFileScopedTypes() + { + const string input = """ + + + + + + + + + """; + await RunReferenceTest(input); + } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Helpers.cs b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Helpers.cs index 36956b2068f5b..bc0bb9e36dc7f 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Helpers.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Helpers.cs @@ -37,12 +37,6 @@ internal static bool OriginalSymbolsMatch( if (searchSymbol == null || symbolToMatch == null) return false; - // Avoid the expensive checks if we can fast path when the compiler just says these are equal. Also, for the - // purposes of symbol finding nullability of symbols doesn't affect things, so just use the default - // comparison. - if (searchSymbol.Equals(symbolToMatch)) - return true; - if (OriginalSymbolsMatchCore(solution, searchSymbol, symbolToMatch)) return true; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Extensions/Symbols/SymbolEquivalenceComparer.EquivalenceVisitor.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Extensions/Symbols/SymbolEquivalenceComparer.EquivalenceVisitor.cs index 84dcfc7efb7a2..95aa5fbf0ff83 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Extensions/Symbols/SymbolEquivalenceComparer.EquivalenceVisitor.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Extensions/Symbols/SymbolEquivalenceComparer.EquivalenceVisitor.cs @@ -10,7 +10,6 @@ using System.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis.Shared.Extensions; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Shared.Utilities; @@ -153,7 +152,7 @@ private bool AssembliesAreEquivalent(IAssemblySymbol x, IAssemblySymbol y) private bool FieldsAreEquivalent(IFieldSymbol x, IFieldSymbol y, Dictionary? equivalentTypesWithDifferingAssemblies) { return - x.Name == y.Name && + x.MetadataName == y.MetadataName && AreEquivalent(x.CustomModifiers, y.CustomModifiers, equivalentTypesWithDifferingAssemblies) && AreEquivalent(x.ContainingSymbol, y.ContainingSymbol, equivalentTypesWithDifferingAssemblies); } @@ -161,7 +160,7 @@ private bool FieldsAreEquivalent(IFieldSymbol x, IFieldSymbol y, Dictionary AssembliesAreEquivalent(x.ContainingAssembly, y.ContainingAssembly) && x.Name == y.Name; + => AssembliesAreEquivalent(x.ContainingAssembly, y.ContainingAssembly) && x.MetadataName == y.MetadataName; private bool NamedTypesAreEquivalent(INamedTypeSymbol x, INamedTypeSymbol y, Dictionary? equivalentTypesWithDifferingAssemblies) { @@ -357,8 +356,7 @@ private bool HandleNamedTypesWorker(INamedTypeSymbol x, INamedTypeSymbol y, Dict return true; if (IsConstructedFromSelf(x) != IsConstructedFromSelf(y) || - x.Arity != y.Arity || - x.Name != y.Name || + x.MetadataName != y.MetadataName || x.IsAnonymousType != y.IsAnonymousType || x.IsUnboundGenericType != y.IsUnboundGenericType || !NullableAnnotationsEquivalent(x, y)) @@ -375,12 +373,12 @@ x.ContainingSymbol is INamespaceSymbol xNamespace && // For error types, we just ensure that the containing namespaces are equivalent up to the root. while (true) { - if (xNamespace.Name != yNamespace.Name) + if (xNamespace.MetadataName != yNamespace.MetadataName) return false; // Error namespaces don't set the IsGlobalNamespace bit unfortunately. So we just do the // nominal check to see if we've actually hit the root. - if (xNamespace.Name == "") + if (xNamespace.MetadataName == "") break; xNamespace = xNamespace.ContainingNamespace; @@ -398,7 +396,7 @@ x.ContainingSymbol is INamespaceSymbol xNamespace && if (equivalentTypesWithDifferingAssemblies != null && x.ContainingType == null && x.ContainingAssembly != null && - !AssemblyIdentityComparer.SimpleNameComparer.Equals(x.ContainingAssembly.Name, y.ContainingAssembly.Name) && + !AssemblyIdentityComparer.SimpleNameComparer.Equals(x.ContainingAssembly.MetadataName, y.ContainingAssembly.MetadataName) && !equivalentTypesWithDifferingAssemblies.ContainsKey(x)) { equivalentTypesWithDifferingAssemblies.Add(x, y); @@ -434,7 +432,7 @@ private bool HandleTupleTypes(INamedTypeSymbol x, INamedTypeSymbol y, Dictionary { var xElement = xElements[i]; var yElement = yElements[i]; - if (xElement.Name != yElement.Name) + if (xElement.MetadataName != yElement.MetadataName) return false; } } @@ -534,7 +532,7 @@ private bool HandleAnonymousTypes(INamedTypeSymbol x, INamedTypeSymbol y, Dictio var p1 = xMembersEnumerator.Current; var p2 = yMembersEnumerator.Current; - if (p1.Name != p2.Name || + if (p1.MetadataName != p2.MetadataName || p1.IsReadOnly != p2.IsReadOnly || !AreEquivalent(p1.Type, p2.Type, equivalentTypesWithDifferingAssemblies)) { @@ -549,7 +547,7 @@ private bool HandleAnonymousTypes(INamedTypeSymbol x, INamedTypeSymbol y, Dictio private bool NamespacesAreEquivalent(INamespaceSymbol x, INamespaceSymbol y, Dictionary? equivalentTypesWithDifferingAssemblies) { if (x.IsGlobalNamespace != y.IsGlobalNamespace || - x.Name != y.Name) + x.MetadataName != y.MetadataName) { return false; } @@ -567,7 +565,7 @@ private bool ParametersAreEquivalent(IParameterSymbol x, IParameterSymbol y, Dic { return x.IsRefOrOut() == y.IsRefOrOut() && - x.Name == y.Name && + x.MetadataName == y.MetadataName && AreEquivalent(x.CustomModifiers, y.CustomModifiers, equivalentTypesWithDifferingAssemblies) && AreEquivalent(x.Type, y.Type, equivalentTypesWithDifferingAssemblies) && AreEquivalent(x.ContainingSymbol, y.ContainingSymbol, equivalentTypesWithDifferingAssemblies); @@ -610,7 +608,7 @@ private bool PropertiesAreEquivalent(IPropertySymbol x, IPropertySymbol y, Dicti private bool EventsAreEquivalent(IEventSymbol x, IEventSymbol y, Dictionary? equivalentTypesWithDifferingAssemblies) { return - x.Name == y.Name && + x.MetadataName == y.MetadataName && IsPartialEventDefinitionPart(x) == IsPartialEventDefinitionPart(y) && IsPartialEventImplementationPart(x) == IsPartialEventImplementationPart(y) && AreEquivalent(x.ContainingSymbol, y.ContainingSymbol, equivalentTypesWithDifferingAssemblies); @@ -660,6 +658,6 @@ private static bool RangeVariablesAreEquivalent(IRangeVariableSymbol x, IRangeVa => HaveSameLocation(x, y); private static bool PreprocessingSymbolsAreEquivalent(IPreprocessingSymbol x, IPreprocessingSymbol y) - => x.Name == y.Name; + => x.MetadataName == y.MetadataName; } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Extensions/Symbols/SymbolEquivalenceComparer.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Extensions/Symbols/SymbolEquivalenceComparer.cs index f18211d02e775..91276b5f2f337 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Extensions/Symbols/SymbolEquivalenceComparer.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Extensions/Symbols/SymbolEquivalenceComparer.cs @@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.Shared.Utilities; /// equivalent. /// /// The kinds of the two symbols must match. -/// The names of the two symbols must match. +/// The metadata names of the two symbols must match. /// The arity of the two symbols must match. /// If the symbols are methods or parameterized properties, then the signatures of the two /// symbols must match.