如何在Roslyn中将字符串变量替换为var
本文关键字:变量 替换 var 字符串 Roslyn | 更新日期: 2023-09-27 17:59:40
对于本地声明,如:string a=字符串。空的
如何编写诊断以将其更改为:var a=字符串。空的
你不能。var关键字告诉编译器执行类型推理,而只有var a;
时,编译器没有足够的信息来推理类型。
但是,您可以执行以下任意
var a = new String();
var b = String.Empty;
var c = "";
但这似乎付出了更多的努力。
编辑更新的请求:为什么要修改所有要用var声明的代码?无论如何,它编译成相同的IL(简单的例子):
// var a = String.Empty;
IL_0000: ldsfld string [mscorlib]System.String::Empty
IL_0005: pop
// string b = String.Empty;
IL_0006: ldsfld string [mscorlib]System.String::Empty
IL_000b: pop
我已经将代码修复与诊断结合在一起。以下是有趣的部分:
从ISyntaxNodeAnalyzer 实现AnalyzeNode
public void AnalyzeNode(SyntaxNode node, SemanticModel semanticModel, Action<Diagnostic> public void AnalyzeNode(SyntaxNode node, SemanticModel semanticModel, Action<Diagnostic> addDiagnostic, CancellationToken cancellationToken)
{
var localDeclaration = (LocalDeclarationStatementSyntax)node;
if (localDeclaration.Declaration.Type.IsVar) return;
var variable = localDeclaration.Declaration.Variables.First();
var initialiser = variable.Initializer;
if (initialiser == null) return;
var variableTypeName = localDeclaration.Declaration.Type;
var variableType = semanticModel.GetTypeInfo(variableTypeName).ConvertedType;
var initialiserInfo = semanticModel.GetTypeInfo(variable.Initializer.Value);
var typeOfRightHandSideOfDeclaration = initialiserInfo.Type;
if (Equals(variableType, typeOfRightHandSideOfDeclaration))
{
addDiagnostic(Diagnostic.Create(Rule, node.GetLocation(), localDeclaration.Declaration.Variables.First().Identifier.Value));
}
}
这主要着眼于声明两侧的类型,如果它们相同(并且RHS还不是var),则添加一个诊断。
这是代码修复的代码:
public async Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, TextSpan span, IEnumerable<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var diagnosticSpan = diagnostics.First().Location.SourceSpan;
var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<LocalDeclarationStatementSyntax>().First();
return new[] { CodeAction.Create("Use var", c => ChangeDeclarationToVar(document, declaration, c)) };
}
private async Task<Document> ChangeDeclarationToVar(Document document, LocalDeclarationStatementSyntax localDeclaration, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken);
var variableTypeName = localDeclaration.Declaration.Type;
var varTypeName = SyntaxFactory.IdentifierName("var").WithAdditionalAnnotations(Formatter.Annotation);
var newDeclaration = localDeclaration.ReplaceNode(variableTypeName, varTypeName);
var newRoot = root.ReplaceNode(localDeclaration, newDeclaration);
return document.WithSyntaxRoot(newRoot);
}
这一点很好也很简单,只需从语法工厂获取var并将其切换出去。请注意,var在SyntaxFactory中没有自己的静态方法,所以它是按名称引用的。
编译器无法从中推断类型。
您需要使用:
var a = ""; // compiler can see that is type `string`:
或者你可以做:
string a;