I'm playing with Roslyn analyzers and Codefixes. In my scenario I wan't to have every domain class should have an according builder in another project.
The diagnostic part was no problem but now I struggle with the codefix. That is what I have so far:
The registration of the codefix (works)
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) {
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
var diagnostic = context.Diagnostics.First();
var diagnosticSpan = diagnostic.Location.SourceSpan;
// Find the type declaration identified by the diagnostic.
var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<TypeDeclarationSyntax>().First();
var equivalenceKey = "CreateTestDataBuilder";
var codeAction = CodeAction.Create(equivalenceKey, c => CreateTestDataBuilderAsync(context.Document, declaration, c), equivalenceKey: equivalenceKey);
context.RegisterCodeFix(codeAction, diagnostic);
}
The codeaction to create the document (crashes)
private async Task<Solution> CreateTestDataBuilderAsync(Document contextDocument, TypeDeclarationSyntax declaration, CancellationToken cancellationToken) {
Project contextDocumentProject = contextDocument.Project;
Solution solution = contextDocumentProject.Solution;
Project testProject = solution.Projects.FirstOrDefault(p => p.Name == contextDocument.Project.Name + ".Test");
if (testProject == null) {
return solution;
}
var semanticModel = await contextDocument.GetSemanticModelAsync(cancellationToken);
var typeSymbol = semanticModel.GetDeclaredSymbol(declaration, cancellationToken);
string[] folders = new[] { "src/Builders" };
Document testDataBuilderDocument = testProject.AddDocument(typeSymbol + "Builder.cs", SourceText.From(string.Format(TestDataBuilderTemplate, typeSymbol.Name)), folders);
bool result = solution.Workspace.TryApplyChanges(solution);
return solution;
}
I think I dont got the idea of how to manipulate the solution with codefixes. Any help?