generated from VeyronSakai/RoslynAnalyzerTemplate
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #132 from VeyronSakai/feature/comment-code-fix-pro…
…vider comment CodeFixProvider
- Loading branch information
Showing
3 changed files
with
143 additions
and
143 deletions.
There are no files selected for viewing
90 changes: 45 additions & 45 deletions
90
VContainerAnalyzer.Test/InjectAttributeCodeFixProviderTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,45 @@ | ||
// Copyright (c) 2020-2024 VeyronSakai. | ||
// This software is released under the MIT License. | ||
|
||
using System.Threading.Tasks; | ||
using NUnit.Framework; | ||
using VerifyField = | ||
Microsoft.CodeAnalysis.CSharp.Testing.NUnit.CodeFixVerifier<VContainerAnalyzer.Analyzers.FieldAnalyzer, | ||
VContainerAnalyzer.CodeFixProviders.InjectAttributeCodeFixProvider>; | ||
using VerifyProperty = | ||
Microsoft.CodeAnalysis.CSharp.Testing.NUnit.CodeFixVerifier<VContainerAnalyzer.Analyzers.PropertyAnalyzer, | ||
VContainerAnalyzer.CodeFixProviders.InjectAttributeCodeFixProvider>; | ||
|
||
namespace VContainerAnalyzer.Test; | ||
|
||
[TestFixture] | ||
public class InjectAttributeCodeFixProviderTest | ||
{ | ||
[Test] | ||
public async Task RemoveInjectAttribute_FieldHasInjectAttribute_CodeFixed() | ||
{ | ||
var (source, _) = Helper.GetJoinedFilesContentText("FieldInjectionClass.cs", "EmptyClassStub.cs"); | ||
var (fixedSource, offset) = | ||
Helper.GetJoinedFilesContentText("FieldInjectionClassFixed.txt", "EmptyClassStub.cs"); | ||
|
||
var expected = VerifyField.Diagnostic() | ||
.WithSpan(6 + offset, 10, 6 + offset, 16) | ||
.WithArguments("_field1"); | ||
|
||
await VerifyField.VerifyCodeFixAsync(source, expected, fixedSource); | ||
} | ||
|
||
[Test] | ||
public async Task RemoveInjectAttribute_PropertyHasInjectAttribute_CodeFixed() | ||
{ | ||
var (source, _) = Helper.GetJoinedFilesContentText("PropertyInjectionClass.cs", "EmptyClassStub.cs"); | ||
var (fixedSource, offset) = | ||
Helper.GetJoinedFilesContentText("PropertyInjectionClassFixed.txt", "EmptyClassStub.cs"); | ||
|
||
var expected = VerifyProperty.Diagnostic() | ||
.WithSpan(6 + offset, 10, 6 + offset, 16) | ||
.WithArguments("Property1"); | ||
|
||
await VerifyProperty.VerifyCodeFixAsync(source, expected, fixedSource); | ||
} | ||
} | ||
// // Copyright (c) 2020-2024 VeyronSakai. | ||
// // This software is released under the MIT License. | ||
// | ||
// using System.Threading.Tasks; | ||
// using NUnit.Framework; | ||
// using VerifyField = | ||
// Microsoft.CodeAnalysis.CSharp.Testing.NUnit.CodeFixVerifier<VContainerAnalyzer.Analyzers.FieldAnalyzer, | ||
// VContainerAnalyzer.CodeFixProviders.InjectAttributeCodeFixProvider>; | ||
// using VerifyProperty = | ||
// Microsoft.CodeAnalysis.CSharp.Testing.NUnit.CodeFixVerifier<VContainerAnalyzer.Analyzers.PropertyAnalyzer, | ||
// VContainerAnalyzer.CodeFixProviders.InjectAttributeCodeFixProvider>; | ||
// | ||
// namespace VContainerAnalyzer.Test; | ||
// | ||
// [TestFixture] | ||
// public class InjectAttributeCodeFixProviderTest | ||
// { | ||
// [Test] | ||
// public async Task RemoveInjectAttribute_FieldHasInjectAttribute_CodeFixed() | ||
// { | ||
// var (source, _) = Helper.GetJoinedFilesContentText("FieldInjectionClass.cs", "EmptyClassStub.cs"); | ||
// var (fixedSource, offset) = | ||
// Helper.GetJoinedFilesContentText("FieldInjectionClassFixed.txt", "EmptyClassStub.cs"); | ||
// | ||
// var expected = VerifyField.Diagnostic() | ||
// .WithSpan(6 + offset, 10, 6 + offset, 16) | ||
// .WithArguments("_field1"); | ||
// | ||
// await VerifyField.VerifyCodeFixAsync(source, expected, fixedSource); | ||
// } | ||
// | ||
// [Test] | ||
// public async Task RemoveInjectAttribute_PropertyHasInjectAttribute_CodeFixed() | ||
// { | ||
// var (source, _) = Helper.GetJoinedFilesContentText("PropertyInjectionClass.cs", "EmptyClassStub.cs"); | ||
// var (fixedSource, offset) = | ||
// Helper.GetJoinedFilesContentText("PropertyInjectionClassFixed.txt", "EmptyClassStub.cs"); | ||
// | ||
// var expected = VerifyProperty.Diagnostic() | ||
// .WithSpan(6 + offset, 10, 6 + offset, 16) | ||
// .WithArguments("Property1"); | ||
// | ||
// await VerifyProperty.VerifyCodeFixAsync(source, expected, fixedSource); | ||
// } | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
194 changes: 97 additions & 97 deletions
194
VContainerAnalyzer/CodeFixProviders/InjectAttributeCodeFixProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,97 +1,97 @@ | ||
// Copyright (c) 2020-2024 VeyronSakai. | ||
// This software is released under the MIT License. | ||
|
||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Composition; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CodeActions; | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory; | ||
|
||
namespace VContainerAnalyzer.CodeFixProviders; | ||
|
||
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(InjectAttributeCodeFixProvider)), Shared] | ||
public sealed class InjectAttributeCodeFixProvider : CodeFixProvider | ||
{ | ||
public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(Rules.Rule0002.Id); | ||
|
||
public override FixAllProvider GetFixAllProvider() | ||
{ | ||
return WellKnownFixAllProviders.BatchFixer; | ||
} | ||
|
||
public 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; | ||
var declaration = root? | ||
.FindToken(diagnosticSpan.Start) | ||
.Parent? | ||
.AncestorsAndSelf() | ||
.OfType<MemberDeclarationSyntax>() | ||
.FirstOrDefault(); | ||
|
||
if (declaration == null) | ||
{ | ||
return; | ||
} | ||
|
||
if (declaration is not FieldDeclarationSyntax && declaration is not PropertyDeclarationSyntax) | ||
{ | ||
return; | ||
} | ||
|
||
context.RegisterCodeFix( | ||
CodeAction.Create( | ||
"Remove InjectAttribute", | ||
cancellationToken => | ||
RemoveInjectAttribute(context.Document, declaration, cancellationToken), | ||
FixableDiagnosticIds.Single()), | ||
context.Diagnostics); | ||
} | ||
|
||
private static async Task<Document> RemoveInjectAttribute(Document document, MemberDeclarationSyntax declaration, | ||
CancellationToken cancellationToken) | ||
{ | ||
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); | ||
var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); | ||
var newAttributeLists = new List<AttributeListSyntax>(); | ||
|
||
foreach (var attributeList in declaration.AttributeLists) | ||
{ | ||
var nodesToRemove = new List<AttributeSyntax>(); | ||
|
||
foreach (var attribute in attributeList.Attributes) | ||
{ | ||
var attributeType = model?.GetTypeInfo(attribute).Type; | ||
if (attributeType != null && attributeType.IsVContainerInjectAttribute()) | ||
{ | ||
nodesToRemove.Add(attribute); | ||
} | ||
} | ||
|
||
var newAttributes = attributeList.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia); | ||
if (newAttributes.Attributes.Any()) | ||
{ | ||
newAttributeLists.Add(newAttributes); | ||
} | ||
} | ||
|
||
var newDeclaration = declaration | ||
.WithAttributeLists(SyntaxFactory.List(newAttributeLists)) | ||
.WithLeadingTrivia(declaration.GetLeadingTrivia()); | ||
|
||
var newRoot = root?.ReplaceNode(declaration, newDeclaration); | ||
return newRoot == null ? document : document.WithSyntaxRoot(newRoot); | ||
} | ||
} | ||
// // Copyright (c) 2020-2024 VeyronSakai. | ||
// // This software is released under the MIT License. | ||
// | ||
// using System.Collections.Generic; | ||
// using System.Collections.Immutable; | ||
// using System.Composition; | ||
// using System.Linq; | ||
// using System.Threading; | ||
// using System.Threading.Tasks; | ||
// using Microsoft.CodeAnalysis; | ||
// using Microsoft.CodeAnalysis.CodeActions; | ||
// using Microsoft.CodeAnalysis.CodeFixes; | ||
// using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
// using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory; | ||
// | ||
// namespace VContainerAnalyzer.CodeFixProviders; | ||
// | ||
// [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(InjectAttributeCodeFixProvider)), Shared] | ||
// public sealed class InjectAttributeCodeFixProvider : CodeFixProvider | ||
// { | ||
// public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(Rules.Rule0002.Id); | ||
// | ||
// public override FixAllProvider GetFixAllProvider() | ||
// { | ||
// return WellKnownFixAllProviders.BatchFixer; | ||
// } | ||
// | ||
// public 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; | ||
// var declaration = root? | ||
// .FindToken(diagnosticSpan.Start) | ||
// .Parent? | ||
// .AncestorsAndSelf() | ||
// .OfType<MemberDeclarationSyntax>() | ||
// .FirstOrDefault(); | ||
// | ||
// if (declaration == null) | ||
// { | ||
// return; | ||
// } | ||
// | ||
// if (declaration is not FieldDeclarationSyntax && declaration is not PropertyDeclarationSyntax) | ||
// { | ||
// return; | ||
// } | ||
// | ||
// context.RegisterCodeFix( | ||
// CodeAction.Create( | ||
// "Remove InjectAttribute", | ||
// cancellationToken => | ||
// RemoveInjectAttribute(context.Document, declaration, cancellationToken), | ||
// FixableDiagnosticIds.Single()), | ||
// context.Diagnostics); | ||
// } | ||
// | ||
// private static async Task<Document> RemoveInjectAttribute(Document document, MemberDeclarationSyntax declaration, | ||
// CancellationToken cancellationToken) | ||
// { | ||
// var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); | ||
// var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); | ||
// var newAttributeLists = new List<AttributeListSyntax>(); | ||
// | ||
// foreach (var attributeList in declaration.AttributeLists) | ||
// { | ||
// var nodesToRemove = new List<AttributeSyntax>(); | ||
// | ||
// foreach (var attribute in attributeList.Attributes) | ||
// { | ||
// var attributeType = model?.GetTypeInfo(attribute).Type; | ||
// if (attributeType != null && attributeType.IsVContainerInjectAttribute()) | ||
// { | ||
// nodesToRemove.Add(attribute); | ||
// } | ||
// } | ||
// | ||
// var newAttributes = attributeList.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia); | ||
// if (newAttributes.Attributes.Any()) | ||
// { | ||
// newAttributeLists.Add(newAttributes); | ||
// } | ||
// } | ||
// | ||
// var newDeclaration = declaration | ||
// .WithAttributeLists(SyntaxFactory.List(newAttributeLists)) | ||
// .WithLeadingTrivia(declaration.GetLeadingTrivia()); | ||
// | ||
// var newRoot = root?.ReplaceNode(declaration, newDeclaration); | ||
// return newRoot == null ? document : document.WithSyntaxRoot(newRoot); | ||
// } | ||
// } |