提交 04b666c6 编写于 作者: D David Kean

Merge pull request #8921 from dotnet/revert-8911-Revert7510

Revert "Revert "Merge pull request #7510 from CyrusNajmabadi/analysisSpeedup""
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
...@@ -15,8 +16,8 @@ internal static class Constants ...@@ -15,8 +16,8 @@ internal static class Constants
public const string SingleIfStatementForm = nameof(SingleIfStatementForm); public const string SingleIfStatementForm = nameof(SingleIfStatementForm);
} }
//[DiagnosticAnalyzer(LanguageNames.CSharp)] [DiagnosticAnalyzer(LanguageNames.CSharp)]
internal class InvokeDelegateWithConditionalAccessAnalyzer : DiagnosticAnalyzer internal class InvokeDelegateWithConditionalAccessAnalyzer : DiagnosticAnalyzer, IBuiltInAnalyzer
{ {
private static readonly DiagnosticDescriptor s_descriptor = new DiagnosticDescriptor( private static readonly DiagnosticDescriptor s_descriptor = new DiagnosticDescriptor(
IDEDiagnosticIds.InvokeDelegateWithConditionalAccessId, IDEDiagnosticIds.InvokeDelegateWithConditionalAccessId,
...@@ -91,6 +92,8 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) ...@@ -91,6 +92,8 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
ExpressionStatementSyntax expressionStatement, ExpressionStatementSyntax expressionStatement,
InvocationExpressionSyntax invocationExpression) InvocationExpressionSyntax invocationExpression)
{ {
var cancellationToken = syntaxContext.CancellationToken;
// Look for the form: "if (someExpr != null) someExpr()" // Look for the form: "if (someExpr != null) someExpr()"
if (condition.Left.IsKind(SyntaxKind.NullLiteralExpression) || if (condition.Left.IsKind(SyntaxKind.NullLiteralExpression) ||
condition.Right.IsKind(SyntaxKind.NullLiteralExpression)) condition.Right.IsKind(SyntaxKind.NullLiteralExpression))
...@@ -99,8 +102,11 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) ...@@ -99,8 +102,11 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
? condition.Right ? condition.Right
: condition.Left; : condition.Left;
cancellationToken.ThrowIfCancellationRequested();
if (SyntaxFactory.AreEquivalent(expr, invocationExpression.Expression, topLevel: false)) if (SyntaxFactory.AreEquivalent(expr, invocationExpression.Expression, topLevel: false))
{ {
cancellationToken.ThrowIfCancellationRequested();
// Looks good! // Looks good!
var tree = syntaxContext.SemanticModel.SyntaxTree; var tree = syntaxContext.SemanticModel.SyntaxTree;
var additionalLocations = new List<Location> var additionalLocations = new List<Location>
...@@ -136,6 +142,9 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) ...@@ -136,6 +142,9 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
ExpressionStatementSyntax expressionStatement, ExpressionStatementSyntax expressionStatement,
InvocationExpressionSyntax invocationExpression) InvocationExpressionSyntax invocationExpression)
{ {
var cancellationToken = syntaxContext.CancellationToken;
cancellationToken.ThrowIfCancellationRequested();
// look for the form "if (a != null)" or "if (null != a)" // look for the form "if (a != null)" or "if (null != a)"
if (!ifStatement.Parent.IsKind(SyntaxKind.Block)) if (!ifStatement.Parent.IsKind(SyntaxKind.Block))
{ {
...@@ -192,6 +201,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) ...@@ -192,6 +201,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
return false; return false;
} }
cancellationToken.ThrowIfCancellationRequested();
if (!Equals(declarator.Identifier.ValueText, conditionName.Identifier.ValueText)) if (!Equals(declarator.Identifier.ValueText, conditionName.Identifier.ValueText))
{ {
return false; return false;
...@@ -199,7 +209,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) ...@@ -199,7 +209,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
// Syntactically this looks good. Now make sure that the local is a delegate type. // Syntactically this looks good. Now make sure that the local is a delegate type.
var semanticModel = syntaxContext.SemanticModel; var semanticModel = syntaxContext.SemanticModel;
var localSymbol = (ILocalSymbol)semanticModel.GetDeclaredSymbol(declarator); var localSymbol = (ILocalSymbol)semanticModel.GetDeclaredSymbol(declarator, cancellationToken);
// Ok, we made a local just to check it for null and invoke it. Looks like something // Ok, we made a local just to check it for null and invoke it. Looks like something
// we can suggest an improvement for! // we can suggest an improvement for!
...@@ -237,5 +247,10 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) ...@@ -237,5 +247,10 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
private bool IsNullCheckExpression(ExpressionSyntax left, ExpressionSyntax right) => private bool IsNullCheckExpression(ExpressionSyntax left, ExpressionSyntax right) =>
left.IsKind(SyntaxKind.IdentifierName) && right.IsKind(SyntaxKind.NullLiteralExpression); left.IsKind(SyntaxKind.IdentifierName) && right.IsKind(SyntaxKind.NullLiteralExpression);
public DiagnosticAnalyzerCategory GetAnalyzerCategory()
{
return DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
}
} }
} }
\ No newline at end of file
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
namespace Microsoft.CodeAnalysis.CSharp.InvokeDelegateWithConditionalAccess namespace Microsoft.CodeAnalysis.CSharp.InvokeDelegateWithConditionalAccess
{ {
//[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(InvokeDelegateWithConditionalAccessCodeFixProvider)), Shared] [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(InvokeDelegateWithConditionalAccessCodeFixProvider)), Shared]
internal class InvokeDelegateWithConditionalAccessCodeFixProvider : CodeFixProvider internal class InvokeDelegateWithConditionalAccessCodeFixProvider : CodeFixProvider
{ {
public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(IDEDiagnosticIds.InvokeDelegateWithConditionalAccessId); public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(IDEDiagnosticIds.InvokeDelegateWithConditionalAccessId);
...@@ -45,23 +45,32 @@ private async Task<Document> UpdateDocumentAsync(CodeFixContext context) ...@@ -45,23 +45,32 @@ private async Task<Document> UpdateDocumentAsync(CodeFixContext context)
if (diagnostic.Properties[Constants.Kind] == Constants.VariableAndIfStatementForm) if (diagnostic.Properties[Constants.Kind] == Constants.VariableAndIfStatementForm)
{ {
return HandVariableAndIfStatementFormAsync(document, root, diagnostic); return HandVariableAndIfStatementFormAsync(document, root, diagnostic, cancellationToken);
} }
else else
{ {
Debug.Assert(diagnostic.Properties[Constants.Kind] == Constants.SingleIfStatementForm); Debug.Assert(diagnostic.Properties[Constants.Kind] == Constants.SingleIfStatementForm);
return HandleSingleIfStatementForm(document, root, diagnostic); return HandleSingleIfStatementForm(document, root, diagnostic, cancellationToken);
} }
} }
private Document HandleSingleIfStatementForm(Document document, SyntaxNode root, Diagnostic diagnostic) private Document HandleSingleIfStatementForm(
Document document,
SyntaxNode root,
Diagnostic diagnostic,
CancellationToken cancellationToken)
{ {
var ifStatementLocation = diagnostic.AdditionalLocations[0]; var ifStatementLocation = diagnostic.AdditionalLocations[0];
var expressionStatementLocation = diagnostic.AdditionalLocations[1]; var expressionStatementLocation = diagnostic.AdditionalLocations[1];
var ifStatement = (IfStatementSyntax)root.FindNode(ifStatementLocation.SourceSpan); var ifStatement = (IfStatementSyntax)root.FindNode(ifStatementLocation.SourceSpan);
cancellationToken.ThrowIfCancellationRequested();
var expressionStatement = (ExpressionStatementSyntax)root.FindNode(expressionStatementLocation.SourceSpan); var expressionStatement = (ExpressionStatementSyntax)root.FindNode(expressionStatementLocation.SourceSpan);
cancellationToken.ThrowIfCancellationRequested();
var invocationExpression = (InvocationExpressionSyntax)expressionStatement.Expression; var invocationExpression = (InvocationExpressionSyntax)expressionStatement.Expression;
cancellationToken.ThrowIfCancellationRequested();
StatementSyntax newStatement = expressionStatement.WithExpression( StatementSyntax newStatement = expressionStatement.WithExpression(
SyntaxFactory.ConditionalAccessExpression( SyntaxFactory.ConditionalAccessExpression(
...@@ -76,20 +85,27 @@ private Document HandleSingleIfStatementForm(Document document, SyntaxNode root, ...@@ -76,20 +85,27 @@ private Document HandleSingleIfStatementForm(Document document, SyntaxNode root,
} }
newStatement = newStatement.WithAdditionalAnnotations(Formatter.Annotation); newStatement = newStatement.WithAdditionalAnnotations(Formatter.Annotation);
cancellationToken.ThrowIfCancellationRequested();
var newRoot = root.ReplaceNode(ifStatement, newStatement); var newRoot = root.ReplaceNode(ifStatement, newStatement);
return document.WithSyntaxRoot(newRoot); return document.WithSyntaxRoot(newRoot);
} }
private static Document HandVariableAndIfStatementFormAsync(Document document, SyntaxNode root, Diagnostic diagnostic) private static Document HandVariableAndIfStatementFormAsync(
Document document, SyntaxNode root, Diagnostic diagnostic, CancellationToken cancellationToken)
{ {
var localDeclarationLocation = diagnostic.AdditionalLocations[0]; var localDeclarationLocation = diagnostic.AdditionalLocations[0];
var ifStatementLocation = diagnostic.AdditionalLocations[1]; var ifStatementLocation = diagnostic.AdditionalLocations[1];
var expressionStatementLocation = diagnostic.AdditionalLocations[2]; var expressionStatementLocation = diagnostic.AdditionalLocations[2];
var localDeclarationStatement = (LocalDeclarationStatementSyntax)root.FindNode(localDeclarationLocation.SourceSpan); var localDeclarationStatement = (LocalDeclarationStatementSyntax)root.FindNode(localDeclarationLocation.SourceSpan);
cancellationToken.ThrowIfCancellationRequested();
var ifStatement = (IfStatementSyntax)root.FindNode(ifStatementLocation.SourceSpan); var ifStatement = (IfStatementSyntax)root.FindNode(ifStatementLocation.SourceSpan);
cancellationToken.ThrowIfCancellationRequested();
var expressionStatement = (ExpressionStatementSyntax)root.FindNode(expressionStatementLocation.SourceSpan); var expressionStatement = (ExpressionStatementSyntax)root.FindNode(expressionStatementLocation.SourceSpan);
cancellationToken.ThrowIfCancellationRequested();
var invocationExpression = (InvocationExpressionSyntax)expressionStatement.Expression; var invocationExpression = (InvocationExpressionSyntax)expressionStatement.Expression;
var parentBlock = (BlockSyntax)localDeclarationStatement.Parent; var parentBlock = (BlockSyntax)localDeclarationStatement.Parent;
...@@ -105,6 +121,7 @@ private static Document HandVariableAndIfStatementFormAsync(Document document, S ...@@ -105,6 +121,7 @@ private static Document HandVariableAndIfStatementFormAsync(Document document, S
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace); var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
editor.ReplaceNode(ifStatement, newStatement); editor.ReplaceNode(ifStatement, newStatement);
editor.RemoveNode(localDeclarationStatement, SyntaxRemoveOptions.KeepLeadingTrivia | SyntaxRemoveOptions.AddElasticMarker); editor.RemoveNode(localDeclarationStatement, SyntaxRemoveOptions.KeepLeadingTrivia | SyntaxRemoveOptions.AddElasticMarker);
cancellationToken.ThrowIfCancellationRequested();
var newRoot = editor.GetChangedRoot(); var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(newRoot); return document.WithSyntaxRoot(newRoot);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册