Skip to content

Implement SA1119#363

Merged
sharwell merged 1 commit intoDotNetAnalyzers:masterfrom
pdelvo:SA1119
Jan 15, 2015
Merged

Implement SA1119#363
sharwell merged 1 commit intoDotNetAnalyzers:masterfrom
pdelvo:SA1119

Conversation

@pdelvo
Copy link
Member

@pdelvo pdelvo commented Jan 14, 2015

Fixes #88.
This is a very tricky one. I tried it on Json.Net. It found a lot of violations but they all seem correct. The Code Fix was able to fix them all at once.
I am mostly compatible with StyleCop I think except for the one thing mentioned in #88. because of readability I don't report diagnostics for parenthised expressions in BinaryExpresions.

@pdelvo
Copy link
Member Author

pdelvo commented Jan 14, 2015

I rebased a few improvements ans bug fixes

@sharwell
Copy link
Member

I'm not merging this for now because I'd like to see this issue resolved. I'll post some additional comments in the code regarding less important "tweaks" that I would have just done myself during the merge, in case you want to fix them.

❗ This diagnostic uses WellKnownDiagnosticTags.Unnecessary, which results in the diagnostic span getting grayed out in the editor. In the current implementation, the "location" for this diagnostic is the complete expression, where the actual unnecessary region is just the parentheses. During my experimentation, I attempted to use the additionalLocations parameter to Diagnostic.Create in order to specify two regions which are both unnecessary but belong to the same diagnostic instance:

private Diagnostic CreateDiagnostic(ParenthesizedExpressionSyntax syntax)
{
    Location primaryLocation = syntax.OpenParenToken.GetLocation();
    Location[] secondaryLocations = { syntax.CloseParenToken.GetLocation() };

    return Diagnostic.Create(Descriptor, primaryLocation, additionalLocations: secondaryLocations);
}

Unfortunately this did not have the expected result. Instead, I believe you will need to do the following:

  1. Report SA1119 for only the open parenthesis.

  2. Define a new diagnostic in the same analyzer:

    • Use DiagnosticSeverity.Hidden
    • Use the tags WellKnownDiagnosticTags.NotConfigurable and WellKnownDiagnosticTags.Unnecessary
    • Do not include the diagnostic in the array returned by SupportedDiagnostics. Hopefully this will cause Roslyn to not call the code at all when SA1119 is disabled. Since a NotConfigurable diagnostic is always enabled, it would override the setting for SA1119 and run this code anyway, even if the SA1119 portion was not shown in the editor UI.
  3. Report the new hidden diagnostic for the closing parenthesis.

  4. Update the code fix provider to trigger on just the SA1119 open parenthesis. The updated code might look like this (replacing the current call to FindNode through the declaration of syntax):

    SyntaxToken openParenToken = root.FindToken(diagnostic.Location.SourceSpan.Start, findInsideTrivia: true);
    if (openParenToken.IsMissing || !openParenToken.IsKind(SyntaxKind.OpenParenToken))
        continue;
    
    ParenthesizedExpressionSyntax syntax = openParenToken.Parent as ParenthesizedExpressionSyntax;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These blank lines are getting inserted due to a bug in the Remove and Sort Usings feature in Visual Studio 2015 preview. After running this command, you should look at the result and see if it added the extra lines.

@pdelvo
Copy link
Member Author

pdelvo commented Jan 14, 2015

This is what it looks like with your changes:
sa1119
You can barely see that the closing parenthesis is faded out. Im not sure if I like that better.
The code fix actually works without changing anything.

@sharwell
Copy link
Member

I believe that is a more accurate representation. However, if you want to do even more (shouldn't be much more than you just did), you could do the following:

  1. Leave the hidden diagnostic you defined as it is.
  2. Remove the WellKnownDiagnosticTags.Unnecessary tag from the main SA1119.
  3. Report 3 diagnostics:
    1. SA1119 is reported for the entire expression. Nothing is grayed out, and the green squiggle goes under the entire expression.
    2. Report the hidden diagnostic for the close parenthesis, like you do now.
    3. Report an additional instance of the same hidden diagnostic for the open parenthesis.

I believe you will like the UI of this much more, and the only work is step 3.i. You also have to handle steps 2 and 3.iii above, but those are trivial.

@pdelvo
Copy link
Member Author

pdelvo commented Jan 14, 2015

I will do that. Actually it is not as trivial because I have to change a lot of unit tests too

@sharwell
Copy link
Member

❓ I thought you shouldn't need to change the tests, because the first character of the location where the SA1119 diagnostic is reported stays the same.

@pdelvo
Copy link
Member Author

pdelvo commented Jan 14, 2015

But the diagnostic now reports 3 diagnostics. 2 start at the same position but they are different and one is at the closing parenthesis

@sharwell
Copy link
Member

😦 Sorry about that.

Do you agree this is the right approach for the user experience?

@pdelvo
Copy link
Member Author

pdelvo commented Jan 14, 2015

Done.

@sharwell
Copy link
Member

Unfortunately I'm out of time today 😞 , but it shouldn't take me too long to review this again when I have more time. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SA1119: StatementMustNotUseUnnecessaryParenthesis

2 participants