简体   繁体   中英

Roslyn: Add using statements to Syntax tree

I have successfully created a codefix which generates factory methods if they're missing from a generic factory class. When I look at the fixed up file, I get a number of errors due to missing using statements.

I've been able to create a list of UsingDirectives that I want to add to my refactored file. How can I add these usings to the file?

    private async Task<Solution> FixUpFactory(Document document, TypeDeclarationSyntax typeDecl, CancellationToken cancellationToken)
        {
...
var factorySyntaxTree = factoryClass.DeclaringSyntaxReferences.Select(x => x.SyntaxTree);
var factoryDocument = document.Project.GetDocument(factorySyntaxTree.FirstOrDefault());
var usingDirectives = FindUsingDirectives(factorySyntaxTree.FirstOrDefault());
var methodUsingDirectives = FindMethodUsingDirectives(createMethods);
var usingDirectivesToAdd = new SyntaxList<UsingDirectiveSyntax>(methodUsingDirectives.Except(usingDirectives).Distinct());
...
//replace 
var factoryTree = await factoryDocument.GetSyntaxTreeAsync();
var compUnitSyntax = factoryTree.GetCompilationUnitRoot();
var newCompUnitSyntax = compUnitSyntax.WithUsings(usingDirectivesToAdd);

var documentRoot = await factoryDocument.GetSyntaxRootAsync().ConfigureAwait(false);
//newRoot comes out the same as the documentRoot
var newRoot= documentRoot.ReplaceNode(compUnitSyntax, newCompUnitSyntax);
var factorySolution = document.Project.Solution.WithDocumentSyntaxRoot(factoryDocument.Id, newRoot);
}

So, how can I get the newRoot to reflect the new using directives I'd like to add?

I ended up breaking up my code a little bit. Both of these worked:

private SyntaxTree UpdateUsingDirectives(SyntaxTree originalTree, UsingDirectiveSyntax[] newUsings)
{
    var rootNode = originalTree.GetRoot() as CompilationUnitSyntax;
    rootNode = rootNode.AddUsings(newUsings).NormalizeWhitespace();
    return rootNode.SyntaxTree;
}
private SyntaxTree UpdateUsingDirectives(SyntaxTree originalTree, SyntaxList<UsingDirectiveSyntax> newUsings)
{
    var rootNode = originalTree.GetRoot() as CompilationUnitSyntax;
    rootNode = rootNode.WithUsings(newUsings).NormalizeWhitespace();
    return rootNode.SyntaxTree;
}

Note the second one replaces the usings.

After that, you can do something like:

var newFactory = UpdateUsingDirectives(factoryTree, newUsings);
var newFactoryRoot = newFactory.GetRoot();

var documentRoot = await factoryDocument.GetSyntaxRootAsync().ConfigureAwait(false);

var newRoot= documentRoot.ReplaceNode(document.getRoot(), newFactoryRoot);
var factorySolution = document.Project.Solution.WithDocumentSyntaxRoot(factoryDocument.Id, newRoot);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM