简体   繁体   中英

Roslyn SyntaxTree changes injection

I wrote my class MonitorSyntaxRewriter, which inherits from CSharpSyntaxRewriter. With this class I change my SyntaxTree. But, how can I "inject" this modified synaxtree somewhere? I mean, I have some random project in Visual Studio, and on Build, I would like all the syntax trees go through this MonitorSyntaxRewriter. Is there some option for that?

Or is there some other possible workaround? (creating new solution...). I just don't want my *.cs files being changed in the project.

As far as I know you can't plug into the build process and rewrite the syntax trees before they're compiled and emitted to disk.

This means achieving what you'd like is not going to be easy. However, your project isn't impossible and you could conceivably create your own Visual Studio extension that added a menu option to Visual Studio and kicked off your own build and emit process.

In order to rewrite syntax trees and apply them to a solution, you need to apply them to their parent document. When writing Visual Studio extensions, you'll want to get access to the VisualStudioWorkspace . This contains the solution, project and documents within the currently opened solution. I've written some background info on workspaces you might be interested in.

You can MEF import the Visual Studio Workspace within a MEF exported class via:

[Import(typeof(Microsoft.VisualStudio.LanguageServices.VisualStudioWorkspace))]

Once you have access to the VisualStudioWorkspace , you could rewrite each document one-by-one. The following sample code should get you started:

Workspace ws = null; //Normally you'd get access to the VisualStudioWorkspace here.
var currentSolution = ws.CurrentSolution;

foreach (var projectId in currentSolution.ProjectIds)
{
    var project = currentSolution.GetProject(projectId);
    foreach (var documentId in project.DocumentIds)
    {
        Document doc = project.GetDocument(documentId);
        var root = await doc.GetSyntaxRootAsync();

        //Rewrite your root here
        var rewrittenRoot = RewriteSyntaxRoot(root);

        //Save the changes to the current document
        doc = doc.WithSyntaxRoot(root);
        //Persist your changes to the current project
        project = doc.Project;
    }
    //Persist the project changes to the current solution
    currentSolution = project.Solution;
}

//Now you have your rewritten solution. You can emit the projects to disk one by one if you'd like.

This won't modify the user's code, but will allow you to emit your custom projects to disk or to a MemoryStream which you could load into an AppDomain or run directly depending on what you're trying to do.

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