Change files using Roslyn

吃可爱长大的小学妹 提交于 2020-01-14 03:45:08

问题


I'm trying to write a command line tool that modifies some code using Roslyn. Everything seems to go well: the solution is opened, the solution is changed, the Workspace.TryApplyChanges method returns true. However no actual files are changed on disk. What's up? Below is the top level code I'm using.

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:


I constructed a short program using your code and received the results I expected - the problem appears to reside within the SolutionAttributeUpdater.UpdateAttributes method. I received these results using the following implementation with your base main and UpdateAnnotations-methods:

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;
    }
}

It was tested using the following class in the sample solution:

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

And it resulted in the following Output:

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

If you take a look at the UpdateAttributes method I had to replace the nodes with ReplaceNodes and updated the solution by calling WithDocumentSyntaxRoot.

I would assume that either one of those two calls is missing or that nothing was changed at all - if you call workspace.TryApplyChanges(solution) you would still receive true as an Output.

Note that using multiple calls of root.ReplaceNode() instead of root.ReplaceNodes() can also result in an error since only the first update is actually used for the modified document - which might lead you to believe that nothing has changed at all, depending on the implementation.



来源:https://stackoverflow.com/questions/35896780/change-files-using-roslyn

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!