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.