提交 6bd87dfd 编写于 作者: K Kevin Halverson

Revert "Revert "Merge pull request #7510 from CyrusNajmabadi/analysisSpeedup""

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