Skip to content

Commit

Permalink
Classify method group assignments as methods (#57410)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidwengier authored Nov 1, 2021
1 parent 78db81e commit db6587f
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,9 @@ await TestAsync(
class C
{
dynamic<int> d;
}", testHost);
}",
testHost,
Class("dynamic"));
}

[Theory]
Expand Down Expand Up @@ -1462,7 +1464,8 @@ public async Task NAQTypeNameMethodCall(TestHost testHost)
await TestInMethodAsync(@"global::System.String.Clone("");",
testHost,
Namespace("System"),
Class("String"));
Class("String"),
Method("Clone"));
}

[Theory]
Expand Down Expand Up @@ -1975,12 +1978,12 @@ class Serializable
{
}
[NonSerialized] // Binds to global::NonSerializedAttribute; not colorized
[NonSerialized] // Binds to global::NonSerializedAttribute; colorized
class NonSerializedAttribute
{
}
[NonSerializedAttribute] // Binds to global::NonSerializedAttribute; not colorized
[NonSerializedAttribute] // Binds to global::NonSerializedAttribute; colorized
class NonSerializedAttribute
{
}
Expand All @@ -1998,6 +2001,8 @@ class ObsoleteAttribute : Attribute
Namespace("System"),
Class("Serializable"),
Class("SerializableAttribute"),
Class("NonSerialized"),
Class("NonSerializedAttribute"),
Class("Obsolete"),
Class("Attribute"),
Class("ObsoleteAttribute"),
Expand Down Expand Up @@ -2590,7 +2595,8 @@ void goo()
}
}",
testHost,
Keyword("var"));
Keyword("var"),
Method("nameof"));
}

[WpfFact]
Expand Down Expand Up @@ -4454,5 +4460,30 @@ class C { }",
testHost,
Namespace("NS"));
}

[Theory]
[CombinatorialData]
[WorkItem(57184, "https://github.com/dotnet/roslyn/issues/57184")]
public async Task MethodGroupClassifications(TestHost testHost)
{
await TestAsync(
@"var f = m;
Delegate d = m;
MulticastDelegate md = m;
ICloneable c = m;
object obj = m;
m(m);
int m(Delegate d) { }",
testHost,
Keyword("var"),
Method("m"),
Method("m"),
Method("m"),
Method("m"),
Method("m"),
Method("m"),
Method("m"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ await TestAsync(
///<param name='_
}",
testHost,
Identifier("_"),
ParseOptions(Options.Regular),
Method("_"),
Method("_"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Expand Down Expand Up @@ -917,7 +918,7 @@ class Program : IReadOnlyCollection<int,string>
Keyword("class"),
Class("Program"),
Punctuation.Colon,
Identifier("IReadOnlyCollection"),
Interface("IReadOnlyCollection"),
Punctuation.OpenAngle,
Keyword("int"),
Punctuation.Comma,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,16 @@ private bool TryClassifySymbol(
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken)
{
if (symbolInfo.CandidateReason is CandidateReason.Ambiguous or
if (symbolInfo.CandidateReason is
CandidateReason.Ambiguous or
CandidateReason.MemberGroup)
{
return TryClassifyAmbiguousSymbol(name, symbolInfo, semanticModel, result, cancellationToken);
}

// Only classify if we get one good symbol back, or if it bound to a constructor symbol with
// overload resolution/accessibility errors, or bound to type/constructor and type wasn't creatable.
var symbol = TryGetSymbol(name, symbolInfo, semanticModel);
var symbol = TryGetSymbol(name, symbolInfo);
if (TryClassifySymbol(name, symbol, semanticModel, cancellationToken, out var classifiedSpan))
{
result.Add(classifiedSpan);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,61 +13,9 @@ internal abstract class AbstractNameSyntaxClassifier : AbstractSyntaxClassifier
protected abstract int? GetRightmostNameArity(SyntaxNode node);
protected abstract bool IsParentAnAttribute(SyntaxNode node);

protected ISymbol? TryGetSymbol(SyntaxNode node, SymbolInfo symbolInfo, SemanticModel semanticModel)
protected ISymbol? TryGetSymbol(SyntaxNode node, SymbolInfo symbolInfo)
{
var symbol = symbolInfo.Symbol;

if (symbol is null && symbolInfo.CandidateSymbols.Length > 0)
{
var firstSymbol = symbolInfo.CandidateSymbols[0];

switch (symbolInfo.CandidateReason)
{
case CandidateReason.NotAValue:
return firstSymbol;

case CandidateReason.NotCreatable:
// We want to color types even if they can't be constructed.
if (firstSymbol.IsConstructor() || firstSymbol is ITypeSymbol)
{
symbol = firstSymbol;
}

break;

case CandidateReason.OverloadResolutionFailure:
// If we couldn't bind to a constructor, still classify the type.
if (firstSymbol.IsConstructor())
{
symbol = firstSymbol;
}

break;

case CandidateReason.Inaccessible:
// If a constructor wasn't accessible, still classify the type if it's accessible.
if (firstSymbol.IsConstructor() && semanticModel.IsAccessible(node.SpanStart, firstSymbol.ContainingType))
{
symbol = firstSymbol;
}

break;

case CandidateReason.WrongArity:
var arity = GetRightmostNameArity(node);

if (arity.HasValue && arity.Value == 0)
{
// When the user writes something like "IList" we don't want to *not* classify
// just because the type bound to "IList<T>". This is also important for use
// cases like "Add-using" where it can be confusing when the using is added for
// "using System.Collection.Generic" but then the type name still does not classify.
symbol = firstSymbol;
}

break;
}
}
var symbol = symbolInfo.GetAnySymbol();

// Classify a reference to an attribute constructor in an attribute location
// as if we were classifying the attribute type itself.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers
Dim classifiedSpan As ClassifiedSpan

Dim symbolInfo = semanticModel.GetSymbolInfo(node, cancellationToken)
Dim symbol = TryGetSymbol(node, symbolInfo, semanticModel)
Dim symbol = TryGetSymbol(node, symbolInfo)

If symbol Is Nothing Then
If TryClassifyIdentifier(node, semanticModel, cancellationToken, classifiedSpan) Then
Expand Down

0 comments on commit db6587f

Please sign in to comment.