我这里有一些特定的内容,基本上,我正在加载一个临时工作区并在编译中得到与特定值有关的错误,因为我确切地知道我需要替换什么文本,而不是在哪里。下面的代码。
public static async Task<Solution> UpdateEntityReferences(Solution solution, ProjectId servicesId, string oldValue, string newValue)
{
var project = solution.GetProject(servicesId);
var compilation = await project.GetCompilationAsync();
var diagnostics = compilation.GetDiagnostics().Where(diag => diag.GetMessage().Contains($"'{oldValue}'"));
foreach (var diagnostic in diagnostics)
{
var errorLineSpan = diagnostic.Location.GetLineSpan();
var document = project.FindDocumentByName(Path.GetFileName(errorLineSpan.Path));
var syntaxRoot = await document.GetSyntaxRootAsync();
var errorSpan = errorLineSpan.Span;
}
return solution;
}
因此,到目前为止,我已经找到了错误的位置,并且基本上想返回该文档的新版本,但将“ errorSpan”替换为“ newValue”文本,但找不到解决方法,这可能吗?
编辑:借助Get the SyntaxNode given the linenumber in a SyntaxTree,我能够从SyntaxTree获取SyntaxNode,并且应该能够替换文本范围(for循环变为下面的内容),但这不起作用。
foreach (var diagnostic in diagnostics)
{
var errorLineSpan = diagnostic.Location.GetLineSpan();
var document = project.FindDocumentByName(Path.GetFileName(errorLineSpan.Path));
var syntaxTree = await document.GetSyntaxTreeAsync();
var errorSpan = errorLineSpan.Span;
var lineSpan = syntaxTree.GetText().Lines[errorSpan.Start.Line].Span;
var node = syntaxTree.GetRoot().DescendantNodes(lineSpan)
.First(n => lineSpan.Contains(n.FullSpan));
var errorTextSpan = TextSpan.FromBounds(errorSpan.Start.Character, errorSpan.End.Character);
var newNodeText = node.GetText().Replace(errorTextSpan, newValue);
}
替换文本(错误时间的一半),然后剩下一个SourceText对象,我无法弄清楚如何在文档中替换文本。有什么想法吗?
答案 0 :(得分:0)
最后到那里-因此,如果不使用document editor之类的东西,就不能替换textspan并取回文档,因为您需要替换SyntaxNode并且不能保证LineSpan的字符位置仍然正确的节点被抓住。
解决方案是简单地使用LineSpan中的行号来抓住该行上的节点,然后使用LINQ向下过滤到令牌。一旦获取了确切的节点,就可以在父节点中替换它,然后在syntaxRoot中替换,最后在文档中替换。下面的代码。
foreach (var diagnostic in diagnostics)
{
servicesProject = solution.GetProject(servicesId);
var errorLineSpan = diagnostic.Location.GetLineSpan();
var document = servicesProject.FindDocumentByName(Path.GetFileName(errorLineSpan.Path));
var syntaxTree = await document.GetSyntaxTreeAsync();
var errorSpan = errorLineSpan.Span;
var lineSpan = syntaxTree.GetText().Lines[errorSpan.Start.Line].Span;
var node = syntaxTree.GetRoot().DescendantNodes(lineSpan)
.First(n => lineSpan.Contains(n.FullSpan)).DescendantNodes()
.OfType<IdentifierNameSyntax>().FirstOrDefault(c => c.Identifier.Text == oldValue);
var newNode = node.ReplaceNode(node, SyntaxFactory.IdentifierName(newValue));
var newSyntaxRoot = syntaxTree.GetRoot().ReplaceNode(node, newNode);
document = document.WithSyntaxRoot(newSyntaxRoot);
solution = document.Project.Solution;
}