Skip to content

Commit f935ca8

Browse files
Fix issue where typeof/sizeof weren't classified properly in FindRefs (#79372)
2 parents 8cec0d0 + 881be8f commit f935ca8

File tree

6 files changed

+81
-37
lines changed

6 files changed

+81
-37
lines changed

src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,66 @@ class var<T> { }
254254
Await TestAPIAndFeature(input, kind, host)
255255
End Function
256256

257+
<WpfTheory, CombinatorialData>
258+
<WorkItem("https://github.com/dotnet/roslyn/issues/79100")>
259+
Public Async Function TestNamedType_TypeOfOperator_Name(kind As TestKind, host As TestHost) As Task
260+
Dim input =
261+
<Workspace>
262+
<Project Language="C#" CommonReferences="true">
263+
<Document>
264+
class {|Definition:Celsius|}
265+
{
266+
public {|Definition:Celsius|}()
267+
{
268+
System.Type t = typeof({|ValueUsageInfo.Name:[|$$Celsius|]|});
269+
}
270+
}
271+
</Document>
272+
</Project>
273+
</Workspace>
274+
Await TestAPIAndFeature(input, kind, host)
275+
End Function
276+
277+
<WpfTheory, CombinatorialData>
278+
<WorkItem("https://github.com/dotnet/roslyn/issues/79100")>
279+
Public Async Function TestNamedType_SizeOfOperator_Name(kind As TestKind, host As TestHost) As Task
280+
Dim input =
281+
<Workspace>
282+
<Project Language="C#" CommonReferences="true">
283+
<Document>
284+
class {|Definition:Celsius|}
285+
{
286+
public {|Definition:Celsius|}()
287+
{
288+
int t = sizeof({|ValueUsageInfo.Name:[|$$Celsius|]|});
289+
}
290+
}
291+
</Document>
292+
</Project>
293+
</Workspace>
294+
Await TestAPIAndFeature(input, kind, host)
295+
End Function
296+
297+
<WpfTheory, CombinatorialData>
298+
<WorkItem("https://github.com/dotnet/roslyn/issues/79100")>
299+
Public Async Function TestNamedType_NameOfOperator_Name(kind As TestKind, host As TestHost) As Task
300+
Dim input =
301+
<Workspace>
302+
<Project Language="C#" CommonReferences="true">
303+
<Document>
304+
class {|Definition:Celsius|}
305+
{
306+
public {|Definition:Celsius|}()
307+
{
308+
string t = nameof({|ValueUsageInfo.Name:[|$$Celsius|]|});
309+
}
310+
}
311+
</Document>
312+
</Project>
313+
</Workspace>
314+
Await TestAPIAndFeature(input, kind, host)
315+
End Function
316+
257317
<WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539799")>
258318
<WpfTheory, CombinatorialData>
259319
Public Async Function TestNamedType_InaccessibleType(kind As TestKind, host As TestHost) As Task

src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,17 @@ protected static SymbolUsageInfo GetSymbolUsageInfo(
608608
while (syntaxFacts.IsQualifiedName(topNameNode.Parent))
609609
topNameNode = topNameNode.Parent;
610610

611-
var isInNamespaceNameContext = syntaxFacts.IsBaseNamespaceDeclaration(topNameNode.Parent);
611+
var parent = topNameNode?.Parent;
612+
613+
// typeof/sizeof are a special case where we don't want to return a TypeOrNamespaceUsageInfo, but rather a ValueUsageInfo.Name.
614+
// This brings it in line with nameof(...), making all those operators appear in a similar fashion.
615+
if (parent?.RawKind == syntaxFacts.SyntaxKinds.TypeOfExpression ||
616+
parent?.RawKind == syntaxFacts.SyntaxKinds.SizeOfExpression)
617+
{
618+
return new(ValueUsageInfo.Name, typeOrNamespaceUsageInfoOpt: null);
619+
}
620+
621+
var isInNamespaceNameContext = syntaxFacts.IsBaseNamespaceDeclaration(parent);
612622
return syntaxFacts.IsInNamespaceOrTypeContext(topNameNode)
613623
? SymbolUsageInfo.Create(GetTypeOrNamespaceUsageInfo())
614624
: GetSymbolUsageInfoCommon();
@@ -677,18 +687,12 @@ SymbolUsageInfo GetSymbolUsageInfoCommon()
677687
if (operation is IObjectCreationOperation)
678688
return SymbolUsageInfo.Create(TypeOrNamespaceUsageInfo.ObjectCreation);
679689

680-
switch (operation?.Parent)
681-
{
682-
case INameOfOperation:
683-
case ITypeOfOperation:
684-
case ISizeOfOperation:
685-
return SymbolUsageInfo.Create(ValueUsageInfo.Name);
686-
}
690+
// Note: sizeof/typeof also return 'name', but are handled above in GetSymbolUsageInfo.
691+
if (operation?.Parent is INameOfOperation)
692+
return SymbolUsageInfo.Create(ValueUsageInfo.Name);
687693

688694
if (node.IsPartOfStructuredTrivia())
689-
{
690695
return SymbolUsageInfo.Create(ValueUsageInfo.Name);
691-
}
692696

693697
var symbolInfo = semanticModel.GetSymbolInfo(node, cancellationToken);
694698
if (symbolInfo.Symbol != null)

src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,13 @@ public int Convert<TSyntaxKind>(TSyntaxKind kind) where TSyntaxKind : struct
118118
public int ReferenceNotEqualsExpression => (int)SyntaxKind.NotEqualsExpression;
119119
public int SimpleAssignmentExpression => (int)SyntaxKind.SimpleAssignmentExpression;
120120
public int SimpleMemberAccessExpression => (int)SyntaxKind.SimpleMemberAccessExpression;
121+
public int? SizeOfExpression => (int)SyntaxKind.SizeOfExpression;
121122
public int? SuppressNullableWarningExpression => (int)SyntaxKind.SuppressNullableWarningExpression;
122123
public int TernaryConditionalExpression => (int)SyntaxKind.ConditionalExpression;
123124
public int ThisExpression => (int)SyntaxKind.ThisExpression;
124125
public int? ThrowExpression => (int)SyntaxKind.ThrowExpression;
125126
public int TupleExpression => (int)SyntaxKind.TupleExpression;
127+
public int TypeOfExpression => (int)SyntaxKind.TypeOfExpression;
126128

127129
public int? AndPattern => (int)SyntaxKind.AndPattern;
128130
public int? ConstantPattern => (int)SyntaxKind.ConstantPattern;

src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/SymbolUsageInfo.cs

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
using System;
65
using System.Diagnostics;
76
using System.Runtime.Serialization;
8-
using Roslyn.Utilities;
97

108
namespace Microsoft.CodeAnalysis;
119

@@ -15,7 +13,7 @@ namespace Microsoft.CodeAnalysis;
1513
/// For methods, fields, properties, events, locals and parameters, this corresponds to values from <see cref="ValueUsageInfo"/>.
1614
/// </summary>
1715
[DataContract]
18-
internal readonly struct SymbolUsageInfo : IEquatable<SymbolUsageInfo>
16+
internal readonly record struct SymbolUsageInfo
1917
{
2018
public static readonly SymbolUsageInfo None = Create(ValueUsageInfo.None);
2119

@@ -45,28 +43,4 @@ public bool IsReadFrom()
4543

4644
public bool IsWrittenTo()
4745
=> ValueUsageInfoOpt.HasValue && ValueUsageInfoOpt.Value.IsWrittenTo();
48-
49-
public bool IsNameOnly()
50-
=> ValueUsageInfoOpt.HasValue && ValueUsageInfoOpt.Value.IsNameOnly();
51-
52-
public override bool Equals(object? obj)
53-
=> obj is SymbolUsageInfo && Equals((SymbolUsageInfo)obj);
54-
55-
public bool Equals(SymbolUsageInfo other)
56-
{
57-
if (ValueUsageInfoOpt.HasValue)
58-
{
59-
return other.ValueUsageInfoOpt.HasValue &&
60-
ValueUsageInfoOpt.Value == other.ValueUsageInfoOpt.Value;
61-
}
62-
else
63-
{
64-
RoslynDebug.Assert(TypeOrNamespaceUsageInfoOpt.HasValue);
65-
return other.TypeOrNamespaceUsageInfoOpt.HasValue &&
66-
TypeOrNamespaceUsageInfoOpt.Value == other.TypeOrNamespaceUsageInfoOpt.Value;
67-
}
68-
}
69-
70-
public override int GetHashCode()
71-
=> Hash.Combine(((int?)ValueUsageInfoOpt)?.GetHashCode() ?? 0, ((int?)TypeOrNamespaceUsageInfoOpt)?.GetHashCode() ?? 0);
7246
}

src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,13 @@ internal interface ISyntaxKinds
161161
int ReferenceNotEqualsExpression { get; }
162162
int SimpleAssignmentExpression { get; }
163163
int SimpleMemberAccessExpression { get; }
164+
int? SizeOfExpression { get; }
164165
int? SuppressNullableWarningExpression { get; }
165166
int TernaryConditionalExpression { get; }
166167
int ThisExpression { get; }
167168
int? ThrowExpression { get; }
168169
int TupleExpression { get; }
170+
int TypeOfExpression { get; }
169171

170172
#endregion
171173

src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageService
120120
Public ReadOnly Property ReferenceNotEqualsExpression As Integer = SyntaxKind.IsNotExpression Implements ISyntaxKinds.ReferenceNotEqualsExpression
121121
Public ReadOnly Property SimpleAssignmentExpression As Integer = SyntaxKind.SimpleAssignmentStatement Implements ISyntaxKinds.SimpleAssignmentExpression
122122
Public ReadOnly Property SimpleMemberAccessExpression As Integer = SyntaxKind.SimpleMemberAccessExpression Implements ISyntaxKinds.SimpleMemberAccessExpression
123+
Public ReadOnly Property SizeOfExpression As Integer? Implements ISyntaxKinds.SizeOfExpression
123124
Public ReadOnly Property SuppressNullableWarningExpression As Integer? Implements ISyntaxKinds.SuppressNullableWarningExpression
124125
Public ReadOnly Property TernaryConditionalExpression As Integer = SyntaxKind.TernaryConditionalExpression Implements ISyntaxKinds.TernaryConditionalExpression
125126
Public ReadOnly Property ThisExpression As Integer = SyntaxKind.MeExpression Implements ISyntaxKinds.ThisExpression
126127
Public ReadOnly Property ThrowExpression As Integer? Implements ISyntaxKinds.ThrowExpression
127128
Public ReadOnly Property TupleExpression As Integer = SyntaxKind.TupleExpression Implements ISyntaxKinds.TupleExpression
129+
Public ReadOnly Property TypeOfExpression As Integer = SyntaxKind.GetTypeExpression Implements ISyntaxKinds.TypeOfExpression
128130

129131
Public ReadOnly Property AndPattern As Integer? Implements ISyntaxKinds.AndPattern
130132
Public ReadOnly Property ConstantPattern As Integer? Implements ISyntaxKinds.ConstantPattern

0 commit comments

Comments
 (0)