I want to walk over all the documents in every project in a given solution using Roslyn.
This is the code I have now:
var msWorkspace = MSBuildWorkspace.Create();
var solution = await msWorkspace.OpenSolutionAsync(solutionPath);
foreach (var project in solution.Projects)
{
foreach (var document in project.Documents)
{
if (document.SourceCodeKind != SourceCodeKind.Regular)
continue;
var doc = document;
foreach (var rewriter in rewriters)
{
doc = await rewriter.Rewrite(doc);
}
if (doc != document)
{
Console.WriteLine("changed {0}",doc.Name);
//save result
//the solution is now changed and the next document to be processed will belong to the old solution
msWorkspace.TryApplyChanges(doc.Project.Solution);
}
}
}
The problem here is that as Roslyn is largely immutable. After the first "msWorkspace.TryApplyChanges", the solution and the document are now replaced with new versions.
So the next iteration will still walk over the old versions.
Is there any way to do this in a Roslyn idiomatic way?
Or do I have to resort to some for(int projectIndex = 0;projectIndex < solution.Projects.count) {
kind of hackery?
You use the IdentifierName (String) method to create a NameSyntax node. Add the following code in your Main method in Program.cs: The preceding code creates an IdentifierNameSyntax object and assigns it to the variable name. Many of the Roslyn APIs return base classes to make it easier to work with related types.
One drawback of Roslyn’s immutability is that it can sometimes make it tricky to apply multiple changes to a Document or SyntaxTree. Immutability means that every time we apply changes to a syntax tree, we’re given an entirely new syntax tree.
A fundamental tenet within Roslyn is that most objects are immutable. This means we can’t hold on to a reference to a solution and expect it to be up-to-date forever. The moment a change is made, this solution will be out of date and a new, updated solution will have been created. Workspaces are our root node.
This solution posted in the Roslyn gitter chat does the trick and solves the problem.
var solution = await msWorkspace.OpenSolutionAsync(solutionPath);
foreach (var projectId in solution.ProjectIds)
{
var project = solution.GetProject(projectId);
foreach (var documentId in project.DocumentIds)
{
Document document = project.GetDocument(documentId);
if (document.SourceCodeKind != SourceCodeKind.Regular)
continue;
var doc = document;
foreach (var rewriter in rewriters)
{
doc = await rewriter.Rewrite(doc);
}
project = doc.Project;
}
solution = project.Solution;
}
msWorkspace.TryApplyChanges(solution);
in this case, changes are no longer discarded between iterations as everything builds on the result of the last iteration. (that is, documents and projects are fetched by ID rather than from an enumerator that walks over the original structure)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With