Skip to content

Commit

Permalink
[GH-11] - code fix provider for adding suppressions to nsubstitute.json
Browse files Browse the repository at this point in the history
  • Loading branch information
tpodolak committed Jun 22, 2018
1 parent e1c34f6 commit 0888ddd
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 96 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using NSubstitute.Analyzers.Shared.CodeFixProviders;

namespace NSubstitute.Analyzers.CSharp.CodeFixProviders
{
[ExportCodeFixProvider(LanguageNames.CSharp)]
public class DefaultSuppressDiagnosticsCodeFixProvider : AbstractSuppressDiagnosticsCodeFixProvider
{
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</PropertyGroup>
<PropertyGroup>
<PackageId>NSubstitute.Analyzers.CSharp</PackageId>
<PackageVersion>7.0.0</PackageVersion>
<PackageVersion>8.0.0</PackageVersion>
<Authors>Tomasz Podolak, NSubstitute.Analyzers contributors</Authors>
<PackageLicenseUrl>https://github.com/nsubstitute/NSubstitute.Analyzers/blob/master/LICENSE.md</PackageLicenseUrl>
<PackageProjectUrl>https://github.com/nsubstitute/NSubstitute.Analyzers</PackageProjectUrl>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Newtonsoft.Json;
using NSubstitute.Analyzers.Shared.Extensions;
using NSubstitute.Analyzers.Shared.Settings;
using NSubstitute.Analyzers.Shared.Threading;

namespace NSubstitute.Analyzers.Shared.CodeFixProviders
{
public class AbstractSuppressDiagnosticsCodeFixProvider : CodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(DiagnosticIdentifiers.NonVirtualSetupSpecification);

public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var project = context.Document.Project;
var workspace = project.Solution.Workspace;

// check if we are allowed to add it
if (!workspace.CanApplyChange(ApplyChangesKind.AddAdditionalDocument))
{
return SpecializedTasks.CompletedTask;
}

foreach (var diagnostic in context.Diagnostics.Where(diagnostic => FixableDiagnosticIds.Contains(diagnostic.Id)))
{
context.RegisterCodeFix(
CodeAction.Create(
"Suppress in nsubstitute.json",
cancellationToken => GetTransformedSolutionAsync(context, diagnostic),
nameof(AbstractSuppressDiagnosticsCodeFixProvider)),
diagnostic);
}

return SpecializedTasks.CompletedTask;
}

private async Task<Solution> GetTransformedSolutionAsync(CodeFixContext context, Diagnostic diagnostic)
{
var project = context.Document.Project;
var solution = project.Solution;

var settingsFile = GetSettingsFile(project);

// creating additional document from Roslyn is broken (https://github.com/dotnet/roslyn/issues/4655) the nsubstitute.json file have to be created by users manually
// if there is no settings file do not provide refactorings
if (settingsFile == null)
{
return solution;
}

var root = await context.Document.GetSyntaxRootAsync();
var model = await context.Document.GetSemanticModelAsync();

var syntaxNode = root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true);
var symbol = model.GetSymbolInfo(syntaxNode);

var options = GetUpdatedAnalyzersOptions(context, diagnostic, symbol);

project = project.RemoveAdditionalDocument(settingsFile.Id);
solution = project.Solution;

var newDocumentId = settingsFile.Id ?? DocumentId.CreateNewId(project.Id);

return solution.AddAdditionalDocument(
newDocumentId,
AnalyzersSettings.AnalyzerFileName,
JsonConvert.SerializeObject(options, Formatting.Indented));
}

private static AnalyzersSettings GetUpdatedAnalyzersOptions(CodeFixContext context, Diagnostic diagnostic, SymbolInfo symbol)
{
var options = context.Document.Project.AnalyzerOptions.GetSettings(default(CancellationToken));
var target = DocumentationCommentId.CreateDeclarationId(symbol.Symbol);
options.Suppressions = options.Suppressions ?? new List<Suppression>();

var existingSuppression = options.Suppressions.FirstOrDefault(suppression => suppression.Target == target);

if (existingSuppression != null)
{
existingSuppression.Rules = existingSuppression.Rules ?? new List<string>();
existingSuppression.Rules.Add(diagnostic.Id);
}
else
{
options.Suppressions.Add(new Suppression
{
Target = DocumentationCommentId.CreateDeclarationId(symbol.Symbol),
Rules = new List<string>
{
diagnostic.Id
}
});
}

return options;
}

private static TextDocument GetSettingsFile(Project project)
{
return project.AdditionalDocuments.SingleOrDefault(document =>
document.Name.Equals(AnalyzersSettings.AnalyzerFileName, StringComparison.CurrentCultureIgnoreCase));
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Newtonsoft.Json;
using NSubstitute.Analyzers.Shared.Settings;

namespace NSubstitute.Analyzers.Shared.Extensions
Expand All @@ -22,9 +23,7 @@ public static AnalyzersSettings GetSettings(this AnalyzerOptions options, Cancel
{
var sourceText = settingsText.GetText(cancellationToken);

return AnalyzersSettings.Default;

// return JsonConvert.DeserializeObject<AnalyzersSettings>(sourceText.ToString());
return JsonConvert.DeserializeObject<AnalyzersSettings>(sourceText.ToString());
}
catch (Exception)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using NSubstitute.Analyzers.CSharp.CodeFixProviders;
using NSubstitute.Analyzers.CSharp.DiagnosticAnalyzers;
using NSubstitute.Analyzers.Shared.CodeFixProviders;
using NSubstitute.Analyzers.Tests.CSharp.DiagnosticAnalyzerTests.NonVirtualSetupAnalyzerTests;
using NSubstitute.Analyzers.Tests.Shared.CodeFixProviders;
using Xunit;
Expand Down Expand Up @@ -46,7 +47,7 @@ protected override DiagnosticAnalyzer GetDiagnosticAnalyzer()

protected override CodeFixProvider GetCodeFixProvider()
{
return new SupressDiagnosticCodeFixProvider();
return new AbstractSuppressDiagnosticsCodeFixProvider();
}
}
}

0 comments on commit 0888ddd

Please sign in to comment.