Skip to content

Why does UnnecessaryWithoutSuggestionDescriptor still show the smart tag, contrary to docs? #41849

@jnm2

Description

@jnm2

Version Used: VS 16.5-p3

When we implemented 'Simplify interpolation' in #40070, I specifically wanted to fade out multiple text segments. There is a nice API for that, but even though we used it, each segment gets its own smart tag.

Is this a Roslyn bug, or did we miss something? What confuses me the most, besides the fact that the nice API doesn't seem to do what it says, is what the difference actually is between UnnecessaryWithSuggestionDescriptor and UnnecessaryWithoutSuggestionDescriptor. They are identical except that the former gets the diagnostic ID IDE0071 and the latter gets the diagnostic ID IDE0071WithoutSuggestion.

That already seems odd, but I also searched all files in the repo for the string WithoutSuggestion and I don't see code that looks like it is doing an EndsWith("WithoutSuggestion") check. Could it have been removed at some point?

image

Here's the nice API:

/// <summary>
/// Diagnostic descriptor for code you want to fade out *and* want to have a smart-tag
/// appear for. This is the common descriptor for code that is being faded out
/// </summary>
protected readonly DiagnosticDescriptor UnnecessaryWithSuggestionDescriptor;
/// <summary>
/// Diagnostic descriptor for code you want to fade out and do *not* want to have a smart-tag
/// appear for. This is uncommon but useful in some cases. For example, if you are fading
/// out pieces of code before/after another piece of code *on the same line*, then you will
/// only want one usage of <see cref="UnnecessaryWithSuggestionDescriptor"/> and multiple
/// usages of <see cref="UnnecessaryWithoutSuggestionDescriptor"/>.
///
/// That's because if you use <see cref="UnnecessaryWithSuggestionDescriptor"/> for all the
/// faded out code then that will mean the user will see multiple code actions to fix the
/// same issue when they bring up the code action on that line. Using these two descriptors
/// helps ensure that there will not be useless code-action overload.
/// </summary>
protected readonly DiagnosticDescriptor UnnecessaryWithoutSuggestionDescriptor;

Here's our implementation:

for (var i = 0; i < unnecessaryLocations.Length; i++)
{
context.ReportDiagnostic(DiagnosticHelper.Create(
i == 0 ? UnnecessaryWithSuggestionDescriptor : UnnecessaryWithoutSuggestionDescriptor,
unnecessaryLocations[i],
severity,
additionalLocations: locations,
properties: null));
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions