如何用 ArgumentSyntax 替换 ExpressionSyntax
How to replace a ExpressionSyntax by an ArgumentSyntax
我想知道我有哪些选择?
我有这样的情况:
public event EventHandler<EventArgs> Changed;
FooBase()
{
Changed += new EventHandler<EventArgs>(HandleChanged);
}
void HandleChanged(object sender, EventArgs e)
{
}
必须修复并更改为以下代码:
public class FooBase
{
public event EventHandler<EventArgs> Changed;
FooBase()
{
Changed += HandleChanged;
}
void HandleChanged(object sender, EventArgs e)
{
}
}
在这种情况下,委托的创建变得多余。我面临一个 ObjectCreationExpression,我需要用它的参数 (ArgumentSyntax) 替换它。
在下面的代码中,除了我要说的,我什么都有。赋值表达式由左右两部分组成。这两个都是表达式语法。目前让我烦恼的是,我需要从参数语法中创建一个表达式语法,这对我来说目前是不可能的,我正在寻找一种方法来实现它!
代码修复:
public async override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var document = context.Document;
var cancellationToken = context.CancellationToken;
var span = context.Span;
var diagnostics = context.Diagnostics;
var root = await document.GetSyntaxRootAsync(cancellationToken);
var diagnostic = diagnostics.First();
var assignmentExpression = root.FindNode(context.Span) as AssignmentExpressionSyntax;
var objectCreation = assignmentExpression?.Right as ObjectCreationExpressionSyntax;
var argument = objectCreation?.ArgumentList.Arguments[0];
if (argument == null)
return;
var argumentAsExpressionStatement = SyntaxFactory.AssignmentExpression(assignmentExpression.Kind(),
assignmentExpression.Left, argument); //Does not compile
var newRoot = root.ReplaceNode(objectCreation,
argument
.WithoutLeadingTrivia()
.WithAdditionalAnnotations(Formatter.Annotation));
context.RegisterCodeFix(CodeActionFactory.Create(assignmentExpression.Span, diagnostic.Severity, "Remove redundant 'new'", document.WithSyntaxRoot(newRoot)), diagnostic);
}
对于那些可能想知道我如何弄清楚委托的创建何时多余的人,这是我使用的代码分析:
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;
using System.Linq;
namespace RefactoringEssentials.CSharp.Diagnostics
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class RedundantDelegateCreationAnalyzer : DiagnosticAnalyzer
{
private static readonly DiagnosticDescriptor descriptor = new DiagnosticDescriptor(
CSharpDiagnosticIDs.RedundantDelegateCreationAnalyzerID,
GettextCatalog.GetString("Explicit delegate creation expression is redundant"),
GettextCatalog.GetString("Redundant explicit delegate declaration"),
DiagnosticAnalyzerCategories.RedundanciesInCode,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
helpLinkUri: HelpLink.CreateFor(CSharpDiagnosticIDs.RedundantDelegateCreationAnalyzerID),
customTags: DiagnosticCustomTags.Unnecessary
);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(
(nodeContext) =>
{
Diagnostic diagnostic;
if (TryGetDiagnostic(nodeContext, out diagnostic))
{
nodeContext.ReportDiagnostic(diagnostic);
}
},
SyntaxKind.ExpressionStatement
);
}
private static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic)
{
diagnostic = default(Diagnostic);
if (nodeContext.IsFromGeneratedCode())
return false;
var semanticModel = nodeContext.SemanticModel;
var expressionStatement = nodeContext.Node as ExpressionStatementSyntax;
var addOrSubstractExpression = expressionStatement?.Expression as AssignmentExpressionSyntax;
var rightMember = addOrSubstractExpression?.Right as ObjectCreationExpressionSyntax;
if (rightMember == null || rightMember.ArgumentList.Arguments.Count != 1)
return false;
var leftTypeInfo = ModelExtensions.GetTypeInfo(semanticModel, addOrSubstractExpression.Left).ConvertedType;
if (leftTypeInfo == null || leftTypeInfo.Kind.Equals(SyntaxKind.EventDeclaration))
return false;
diagnostic = Diagnostic.Create(descriptor, addOrSubstractExpression.Right.GetLocation());
return true;
}
}
}
如果我很好地理解您的问题,您只需将 ObjectCreationExpressionSyntax 替换为 IdentifierNameSyntax (HandleChanged) 而不是 ArgumentSyntax。
这是编辑后的代码
public async override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var document = context.Document;
var cancellationToken = context.CancellationToken;
var span = context.Span;
var diagnostics = context.Diagnostics;
var root = await document.GetSyntaxRootAsync(cancellationToken);
var diagnostic = diagnostics.First();
var assignmentExpression = root.FindNode(context.Span) as AssignmentExpressionSyntax;
var objectCreation = assignmentExpression?.Right as ObjectCreationExpressionSyntax;
var argument = objectCreation?.ArgumentList.Arguments[0];
if (argument == null)
return;
var identifier = argument.DescendantNodes()
.OfType<IdentifierNameSyntax>).First();
var newRoot = root.ReplaceNode(objectCreation,
SyntaxFactory.IdentifierName(identifier.Identifier.Text));
context.RegisterCodeFix(CodeActionFactory.Create(assignmentExpression.Span, diagnostic.Severity, "Remove redundant 'new'", document.WithSyntaxRoot(newRoot)), diagnostic);
}
我发现在 ArgumentSyntax class 中,有一个 ExpressionSyntax 类型的 属性,它旧化了对委托将引用的方法的引用。
所以,代码变成了这样! :
var assignmentExpression = root.FindNode(context.Span) as AssignmentExpressionSyntax;
var objectCreation = assignmentExpression?.Right as ObjectCreationExpressionSyntax;
var argument = objectCreation?.ArgumentList.Arguments[0];
if (argument == null)
return;
var newRoot = root.ReplaceNode(objectCreation,
argument.Expression
.WithoutLeadingTrivia()
.WithAdditionalAnnotations(Formatter.Annotation));
context.RegisterCodeFix(CodeActionFactory.Create(assignmentExpression.Span, diagnostic.Severity, "Remove redundant 'new'", document.WithSyntaxRoot(newRoot)), diagnostic);
我想知道我有哪些选择? 我有这样的情况:
public event EventHandler<EventArgs> Changed;
FooBase()
{
Changed += new EventHandler<EventArgs>(HandleChanged);
}
void HandleChanged(object sender, EventArgs e)
{
}
必须修复并更改为以下代码:
public class FooBase
{
public event EventHandler<EventArgs> Changed;
FooBase()
{
Changed += HandleChanged;
}
void HandleChanged(object sender, EventArgs e)
{
}
}
在这种情况下,委托的创建变得多余。我面临一个 ObjectCreationExpression,我需要用它的参数 (ArgumentSyntax) 替换它。
在下面的代码中,除了我要说的,我什么都有。赋值表达式由左右两部分组成。这两个都是表达式语法。目前让我烦恼的是,我需要从参数语法中创建一个表达式语法,这对我来说目前是不可能的,我正在寻找一种方法来实现它!
代码修复:
public async override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var document = context.Document;
var cancellationToken = context.CancellationToken;
var span = context.Span;
var diagnostics = context.Diagnostics;
var root = await document.GetSyntaxRootAsync(cancellationToken);
var diagnostic = diagnostics.First();
var assignmentExpression = root.FindNode(context.Span) as AssignmentExpressionSyntax;
var objectCreation = assignmentExpression?.Right as ObjectCreationExpressionSyntax;
var argument = objectCreation?.ArgumentList.Arguments[0];
if (argument == null)
return;
var argumentAsExpressionStatement = SyntaxFactory.AssignmentExpression(assignmentExpression.Kind(),
assignmentExpression.Left, argument); //Does not compile
var newRoot = root.ReplaceNode(objectCreation,
argument
.WithoutLeadingTrivia()
.WithAdditionalAnnotations(Formatter.Annotation));
context.RegisterCodeFix(CodeActionFactory.Create(assignmentExpression.Span, diagnostic.Severity, "Remove redundant 'new'", document.WithSyntaxRoot(newRoot)), diagnostic);
}
对于那些可能想知道我如何弄清楚委托的创建何时多余的人,这是我使用的代码分析:
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;
using System.Linq;
namespace RefactoringEssentials.CSharp.Diagnostics
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class RedundantDelegateCreationAnalyzer : DiagnosticAnalyzer
{
private static readonly DiagnosticDescriptor descriptor = new DiagnosticDescriptor(
CSharpDiagnosticIDs.RedundantDelegateCreationAnalyzerID,
GettextCatalog.GetString("Explicit delegate creation expression is redundant"),
GettextCatalog.GetString("Redundant explicit delegate declaration"),
DiagnosticAnalyzerCategories.RedundanciesInCode,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
helpLinkUri: HelpLink.CreateFor(CSharpDiagnosticIDs.RedundantDelegateCreationAnalyzerID),
customTags: DiagnosticCustomTags.Unnecessary
);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(
(nodeContext) =>
{
Diagnostic diagnostic;
if (TryGetDiagnostic(nodeContext, out diagnostic))
{
nodeContext.ReportDiagnostic(diagnostic);
}
},
SyntaxKind.ExpressionStatement
);
}
private static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic)
{
diagnostic = default(Diagnostic);
if (nodeContext.IsFromGeneratedCode())
return false;
var semanticModel = nodeContext.SemanticModel;
var expressionStatement = nodeContext.Node as ExpressionStatementSyntax;
var addOrSubstractExpression = expressionStatement?.Expression as AssignmentExpressionSyntax;
var rightMember = addOrSubstractExpression?.Right as ObjectCreationExpressionSyntax;
if (rightMember == null || rightMember.ArgumentList.Arguments.Count != 1)
return false;
var leftTypeInfo = ModelExtensions.GetTypeInfo(semanticModel, addOrSubstractExpression.Left).ConvertedType;
if (leftTypeInfo == null || leftTypeInfo.Kind.Equals(SyntaxKind.EventDeclaration))
return false;
diagnostic = Diagnostic.Create(descriptor, addOrSubstractExpression.Right.GetLocation());
return true;
}
}
}
如果我很好地理解您的问题,您只需将 ObjectCreationExpressionSyntax 替换为 IdentifierNameSyntax (HandleChanged) 而不是 ArgumentSyntax。 这是编辑后的代码
public async override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var document = context.Document;
var cancellationToken = context.CancellationToken;
var span = context.Span;
var diagnostics = context.Diagnostics;
var root = await document.GetSyntaxRootAsync(cancellationToken);
var diagnostic = diagnostics.First();
var assignmentExpression = root.FindNode(context.Span) as AssignmentExpressionSyntax;
var objectCreation = assignmentExpression?.Right as ObjectCreationExpressionSyntax;
var argument = objectCreation?.ArgumentList.Arguments[0];
if (argument == null)
return;
var identifier = argument.DescendantNodes()
.OfType<IdentifierNameSyntax>).First();
var newRoot = root.ReplaceNode(objectCreation,
SyntaxFactory.IdentifierName(identifier.Identifier.Text));
context.RegisterCodeFix(CodeActionFactory.Create(assignmentExpression.Span, diagnostic.Severity, "Remove redundant 'new'", document.WithSyntaxRoot(newRoot)), diagnostic);
}
我发现在 ArgumentSyntax class 中,有一个 ExpressionSyntax 类型的 属性,它旧化了对委托将引用的方法的引用。
所以,代码变成了这样! :
var assignmentExpression = root.FindNode(context.Span) as AssignmentExpressionSyntax;
var objectCreation = assignmentExpression?.Right as ObjectCreationExpressionSyntax;
var argument = objectCreation?.ArgumentList.Arguments[0];
if (argument == null)
return;
var newRoot = root.ReplaceNode(objectCreation,
argument.Expression
.WithoutLeadingTrivia()
.WithAdditionalAnnotations(Formatter.Annotation));
context.RegisterCodeFix(CodeActionFactory.Create(assignmentExpression.Span, diagnostic.Severity, "Remove redundant 'new'", document.WithSyntaxRoot(newRoot)), diagnostic);