Skip to content
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

Classify method group assignments as methods #57410

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,9 @@ await TestAsync(
class C
{
dynamic<int> d;
}", testHost);
}",
testHost,
Class("dynamic"));
}

[Theory]
Expand Down Expand Up @@ -1461,7 +1463,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 @@ -1974,12 +1977,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 @@ -1997,6 +2000,8 @@ class ObsoleteAttribute : Attribute
Namespace("System"),
Class("Serializable"),
Class("SerializableAttribute"),
Class("NonSerialized"),
Class("NonSerializedAttribute"),
Class("Obsolete"),
Class("Attribute"),
Class("ObsoleteAttribute"),
Expand Down Expand Up @@ -2589,7 +2594,8 @@ void goo()
}
}",
testHost,
Keyword("var"));
Keyword("var"),
Method("nameof"));
}

[WpfFact]
Expand Down Expand Up @@ -4451,5 +4457,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