Skip to content
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 @@ -3286,71 +3286,6 @@ bool N(object x)
Parameter("x"),
Keyword("_"));

[Theory, CombinatorialData]
public Task UnusedUnderscoreParameterInLambda(TestHost testHost)
=> TestAsync("""
class X
{
void N()
{
System.Func<int, int> a = (int _) => 0;
}
}
""",
testHost,
Namespace("System"),
Delegate("Func"));

[Theory, CombinatorialData]
public Task UsedUnderscoreParameterInLambda(TestHost testHost)
=> TestAsync("""
class X
{
void N()
{
System.Func<int, int> a = (int _) => _;
}
}
""",
testHost,
Namespace("System"),
Delegate("Func"),
Parameter("_"));

[Theory, CombinatorialData]
public Task DiscardsInLambda(TestHost testHost)
=> TestAsync("""
class X
{
void N()
{
System.Func<int, int, int> a = (int _, int _) => 0;
}
}
""",
testHost,
Namespace("System"),
Delegate("Func"),
Keyword("_"),
Keyword("_"));

[Theory, CombinatorialData]
public Task DiscardsInLambdaWithInferredType(TestHost testHost)
=> TestAsync("""
class X
{
void N()
{
System.Func<int, int, int> a = (_, _) => 0;
}
}
""",
testHost,
Namespace("System"),
Delegate("Func"),
Keyword("_"),
Keyword("_"));

[Theory, CombinatorialData]
public Task NativeInteger(TestHost testHost)
=> TestInMethodAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1102,7 +1102,7 @@ public Task DiscardInLambda(TestHost testHost)
=> TestInMethodAsync(
code: @"x = (_, _) => 1;",
testHost: testHost,
expected: Classifications(Identifier("x"), Operators.Equals, Punctuation.OpenParen, Parameter("_"), Punctuation.Comma, Parameter("_"), Punctuation.CloseParen,
expected: Classifications(Identifier("x"), Operators.Equals, Punctuation.OpenParen, Keyword("_"), Punctuation.Comma, Keyword("_"), Punctuation.CloseParen,
Operators.EqualsGreaterThan, Number("1"), Punctuation.Semicolon));

[Theory, CombinatorialData]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2942,6 +2942,45 @@ void M()
], actualFormatted);
}

[WpfTheory]
[InlineData("System.Action<int, int> lambda = (_, p) => { };", false)]
[InlineData("System.Action<int, int> lambda = (int _, int p) => { };", false)]
[InlineData("System.Action<int, int, int> lambda = (_, _, p) => { };", true)]
[InlineData("System.Action<int, int, int> lambda = (int _, int _, int p) => { };", true)]
public async Task TestTotalClassifier_LambdaDiscards(string declaration, bool isDiscard)
{
using var workspace = EditorTestWorkspace.CreateCSharp($$"""
class C
{
void M()
{
{{declaration}}
}
}
""");
var document = workspace.Documents.First();
var provider = new TotalClassificationTaggerProvider(
workspace.GetService<TaggerHost>(),
workspace.GetService<ClassificationTypeMap>());

var buffer = document.GetTextBuffer();
using var tagger = provider.CreateTagger(document.GetTextView(), buffer);

var listenerProvider = workspace.ExportProvider.GetExportedValue<IAsynchronousOperationListenerProvider>();
await listenerProvider.GetWaiter(FeatureAttribute.Classification).ExpeditedWaitAsync();

var tags = tagger!.GetTags(new NormalizedSnapshotSpanCollection(buffer.CurrentSnapshot.GetFullSpan()));
var actual = tags.OrderBy(tag => tag.Span.Start.Position)
.Where(tag => tag.Span.GetText() is "_" or "p")
.Select(tag => new FormattedClassification(tag.Span.GetText(), tag.Tag.ClassificationType.Classification));

AssertEx.Equal<FormattedClassification>(
isDiscard
? [Keyword("_"), Keyword("_"), Parameter("p")]
: [Parameter("_"), Parameter("p")],
actual);
}

[WpfFact]
public void TestCopyPasteClassifier()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,17 @@ private static bool IsVerbatimStringToken(SyntaxToken token)
}
else if (token.Parent is ParameterSyntax parameterSyntax && parameterSyntax.Identifier == token)
{
if (token.Text == "_" && parameterSyntax.Parent is ParameterListSyntax { Parent: AnonymousFunctionExpressionSyntax } parameterList)
{
foreach (var otherParameter in parameterList.Parameters)
{
if (otherParameter != parameterSyntax && otherParameter.Identifier.Text == "_")
{
return ClassificationTypeNames.Keyword;
}
}
}

return ClassificationTypeNames.ParameterName;
}
else if (token.Parent is ForEachStatementSyntax forEachStatementSyntax && forEachStatementSyntax.Identifier == token)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Classification.Classifiers;

internal sealed class DiscardSyntaxClassifier : AbstractSyntaxClassifier
{
public override ImmutableArray<Type> SyntaxNodeTypes { get; } = [typeof(DiscardDesignationSyntax), typeof(DiscardPatternSyntax), typeof(ParameterSyntax), typeof(IdentifierNameSyntax)];
public override ImmutableArray<Type> SyntaxNodeTypes { get; } = [typeof(DiscardDesignationSyntax), typeof(DiscardPatternSyntax), typeof(IdentifierNameSyntax)];

public override void AddClassifications(
SyntaxNode syntax,
Expand All @@ -33,16 +33,6 @@ public override void AddClassifications(

switch (syntax)
{
case ParameterSyntax parameter when parameter.Identifier.Text == "_":
var symbol = semanticModel.GetDeclaredSymbol(parameter, cancellationToken);

if (symbol?.IsDiscard == true)
{
result.Add(new ClassifiedSpan(parameter.Identifier.Span, ClassificationTypeNames.Keyword));
}

break;

case IdentifierNameSyntax identifierName when identifierName.Identifier.Text == "_":
var symbolInfo = semanticModel.GetSymbolInfo(identifierName, cancellationToken);

Expand Down