代码分析器-删除节点失败,无一例外



正如您可能已经猜到的,我正在学习有关roslyn的所有知识,尤其是作为一名代码分析器。

语法高亮显示非常有效。然而,以下是我的代码操作,在删除节点时会无声地失败:

    private async Task<Document> RemoveNode(Document document, LocalDeclarationStatementSyntax typeDecl, CancellationToken cancellationToken)
    {
        IEnumerable<SyntaxNode> oldNode = typeDecl.DescendantNodes().OfType<VariableDeclarationSyntax>();
        SyntaxNode oldRoot = await document.GetSyntaxRootAsync(cancellationToken);
        SyntaxNode newRoot = oldRoot.RemoveNode(oldNode.Single(), SyntaxRemoveOptions.KeepNoTrivia); //Analyzer fails here
        return document.WithSyntaxRoot(newRoot);
    }

主题:

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            FruitMix fm = new FruitMix(); //This is the matched node
        }
    }
}

我觉得我错过了如何与Roslyn合作的"大局",所以尽管这里的帮助会很神奇,但我也很喜欢一些能帮助我的链接/资源。

我在这里上传了这个项目,虽然不是一个"最小"的例子,但它很容易重现这个问题。上面的代码在CodeFixProvider.cs中。

感谢

当我在启用break-on-all exceptions thrown的情况下运行代码时,我可以看到它将ArgumentNullException深入到RemoveNode()内部的调用堆栈中,特别是在SyntaxFactory.LocalDeclarationStatement()中。

该异常令人困惑(GitHub上已经报道过),但实际上是您的错误:您正试图从其父级LocalDeclarationStatementSyntax中删除VariableDeclarationSyntax(其语法类似于LocalDeclarationStatement:constVariableDeclaration;)。由于没有VariableDeclarationSyntaxLocalDeclarationStatementSyntax是无效的,因此会得到异常。

最简单的修复方法是只删除父LocalDeclarationStatementSyntax:

SyntaxNode newRoot = oldRoot.RemoveNode(oldNode.Single().Parent, SyntaxRemoveOptions.KeepNoTrivia);