source: misc/tools/PersistenceCodeFix/PersistenceCodeFix/PersistenceCodeFix/Analyzers/ObsoleteStorableClass/ObsoleteStorableClassFix.cs @ 16576

Last change on this file since 16576 was 16576, checked in by gkronber, 2 years ago

#2520: changed Fossil -> Attic in VS Code Fix

File size: 4.0 KB
Line 
1using System;
2using System.Collections.Immutable;
3using System.Composition;
4using System.Linq;
5using System.Threading;
6using System.Threading.Tasks;
7using Microsoft.CodeAnalysis;
8using Microsoft.CodeAnalysis.CodeActions;
9using Microsoft.CodeAnalysis.CodeFixes;
10using Microsoft.CodeAnalysis.CSharp;
11using Microsoft.CodeAnalysis.CSharp.Syntax;
12using Microsoft.CodeAnalysis.Formatting;
13
14namespace PersistenceCodeFix {
15  [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(ObsoleteStorableClassFix)), Shared]
16  public sealed class ObsoleteStorableClassFix : CodeFixProvider, IDocumentCodeFixProvider {
17    private const string title = "Change to StorableType attribute";
18
19    public sealed override ImmutableArray<string> FixableDiagnosticIds {
20      get { return ImmutableArray.Create(ObsoleteStorableClassAnalyzer.DiagnosticId); }
21    }
22
23    public sealed override FixAllProvider GetFixAllProvider() {
24      return SequentialFixAllProvider.Instance;
25    }
26
27    public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) {
28      var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
29
30      var diagnostic = context.Diagnostics.First();
31      var diagnosticSpan = diagnostic.Location.SourceSpan;
32      var attributeSyntax = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<AttributeSyntax>().First();
33
34      context.RegisterCodeFix(
35        CodeAction.Create(
36          title: title,
37          createChangedDocument: c => ChangeToStorableTypeAttribute(context.Document, attributeSyntax, c),
38          equivalenceKey: title),
39        diagnostic);
40    }
41
42    private static async Task<Document> ChangeToStorableTypeAttribute(Document document, AttributeSyntax attrDecl, CancellationToken cancellationToken) {
43      var oldAttrArgs = attrDecl.ArgumentList;
44
45      // create new identifier
46      var name = SyntaxFactory.IdentifierName("StorableType")
47        .WithLeadingTrivia(attrDecl.Name.GetLeadingTrivia());
48
49      // create guid arg
50      var guid = Guid.NewGuid();
51      var guidArg = SyntaxFactory.AttributeArgument(
52        SyntaxFactory.LiteralExpression(
53          SyntaxKind.StringLiteralExpression,
54          SyntaxFactory.Literal(guid.ToString().ToUpperInvariant())
55        ));
56
57      var newAttrArgs = SyntaxFactory.AttributeArgumentList();
58      if (oldAttrArgs != null) {
59        // preserve old trivia
60        newAttrArgs = oldAttrArgs.WithArguments(newAttrArgs.Arguments);
61
62        // add old args
63        foreach (var arg in oldAttrArgs.Arguments)
64          newAttrArgs = newAttrArgs.AddArguments(arg);
65
66        // add trailing trivia to name only if there is an old argument list
67        // otherwise add it after the new argument list ...
68        name = name.WithTrailingTrivia(attrDecl.Name.GetTrailingTrivia());
69      } else {
70        // ... here
71        newAttrArgs = newAttrArgs.WithTrailingTrivia(attrDecl.Name.GetTrailingTrivia());
72      }
73      newAttrArgs = newAttrArgs.AddArguments(guidArg);
74
75      // rename attr, add old trivia and format
76      var newAttrDecl = attrDecl
77        .WithName(name)
78        .WithArgumentList(newAttrArgs)
79        .WithAdditionalAnnotations(Formatter.Annotation);
80
81      var root = await document.GetSyntaxRootAsync(cancellationToken) as CompilationUnitSyntax;
82      var newRoot = root.ReplaceNode(attrDecl, newAttrDecl);
83
84      // add using of HEAL.Attic if the document does not already have it
85      var oldUsings = root.Usings;
86      if (oldUsings.All(x => x.Name.WithoutTrivia().ToString() != "HEAL.Attic")) {
87        var persistenceUsing = SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName("HEAL.Attic"));
88        newRoot = newRoot.WithUsings(oldUsings.Add(persistenceUsing));
89      }
90
91      return document.WithSyntaxRoot(newRoot);
92    }
93
94    public Task<Document> FixDocumentAsync(Document document, SyntaxNode node, CancellationToken cancellationToken) {
95      return ChangeToStorableTypeAttribute(document, (AttributeSyntax)node, cancellationToken);
96    }
97  }
98}
Note: See TracBrowser for help on using the repository browser.