使用Roslyn更改文件

时间:2016-03-09 16:10:53

标签: c# roslyn

我正在尝试编写一个使用Roslyn修改某些代码的命令行工具。一切似乎都顺利:打开解决方案,更改解决方案,Workspace.TryApplyChanges方法返回true。但是,磁盘上没有更改实际文件。这是怎么回事?下面是我正在使用的顶级代码。

static void Main(string[] args)
{
    var solutionPath = args[0];
    UpdateAnnotations(solutionPath).Wait();
}

static async Task<bool> UpdateAnnotations(string solutionPath)
{
    using (var workspace = MSBuildWorkspace.Create())
    {
        var solution = await workspace.OpenSolutionAsync(solutionPath);
        var newSolution = await SolutionAttributeUpdater.UpdateAttributes(solution);
        var result = workspace.TryApplyChanges(newSolution);
        Console.WriteLine(result);
        return result;
    }
}

1 个答案:

答案 0 :(得分:3)

我使用您的代码构建了一个简短的程序,并收到了我期望的结果 - 问题似乎存在于SolutionAttributeUpdater.UpdateAttributes方法中。我使用您的base main和UpdateAnnotations方法使用以下实现收到了这些结果:

public class SolutionAttributeUpdater
{
    public static async Task<Solution> UpdateAttributes(Solution solution)
    {
        foreach (var project in solution.Projects)
        {
            foreach (var document in project.Documents)
            {
                var syntaxTree = await document.GetSyntaxTreeAsync();
                var root = syntaxTree.GetRoot();

                var descentants = root.DescendantNodes().Where(curr => curr is AttributeListSyntax).ToList();
                if (descentants.Any())
                {
                    var attributeList = SyntaxFactory.AttributeList(
                        SyntaxFactory.SingletonSeparatedList(
                            SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("Cookies"), SyntaxFactory.AttributeArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.AttributeArgument(
                                    SyntaxFactory.LiteralExpression(
                                                                SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(@"Sample"))
                                    )})))));
                    root = root.ReplaceNodes(descentants, (node, n2) => attributeList);
                    solution = solution.WithDocumentSyntaxRoot(document.Id, root);
                }
            }
        }
        return solution;
    }
}

在样本溶液中使用以下类进行了测试:

public class SampleClass<T>
{
    [DataMember("Id")]
    public int Property { get; set; }
    [DataMember("Id")]
    public void DoStuff()
    {
        DoStuff();
    }
}

它产生了以下输出:

public class SampleClass<T>
{
[Cookies("Sample")]        public int Property { get; set; }
[Cookies("Sample")]        public void DoStuff()
    {
        DoStuff();
    }
}

如果您查看UpdateAttributes方法,我必须用ReplaceNodes替换节点,并通过调用WithDocumentSyntaxRoot更新解决方案。

我会假设这两个调用中的任何一个缺失或者根本没有任何更改 - 如果你调用workspace.TryApplyChanges(解决方案),你仍然会收到true作为输出。

请注意,使用root.ReplaceNode()而不是root.ReplaceNodes()的多次调用也可能导致错误,因为只有第一次更新实际用于修改后的文档 - 这可能会让您相信没有任何更改完全取决于实施。