Skip to content

Commit

Permalink
GH-170 - reporting separate diagnostic for subtitution of extension m…
Browse files Browse the repository at this point in the history
…ethods
  • Loading branch information
tpodolak committed Jul 30, 2023
1 parent e01eaa5 commit b3e3eb0
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ internal class AbstractDiagnosticDescriptorsProvider<T> : IDiagnosticDescriptors
{
public DiagnosticDescriptor NonVirtualSetupSpecification { get; } = DiagnosticDescriptors<T>.NonVirtualSetupSpecification;

public DiagnosticDescriptor ExtensionMethodSetupSpecification { get; } = DiagnosticDescriptors<T>.ExtensionMethodSetupSpecification;

public DiagnosticDescriptor NonVirtualReceivedInOrderSetupSpecification { get; } = DiagnosticDescriptors<T>.NonVirtualReceivedInOrderSetupSpecification;

public DiagnosticDescriptor InternalSetupSpecification { get; } = DiagnosticDescriptors<T>.InternalSetupSpecification;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ internal abstract class AbstractNonSubstitutableSetupAnalyzer : AbstractDiagnost

protected abstract DiagnosticDescriptor NonVirtualSetupDescriptor { get; }

private readonly DiagnosticDescriptor _extensionMethodSetupDescriptor;

private readonly DiagnosticDescriptor _internalSetupSpecificationDescriptor;

protected AbstractNonSubstitutableSetupAnalyzer(
Expand All @@ -18,6 +20,7 @@ protected AbstractNonSubstitutableSetupAnalyzer(
: base(diagnosticDescriptorsProvider)
{
_nonSubstitutableMemberAnalysis = nonSubstitutableMemberAnalysis;
_extensionMethodSetupDescriptor = diagnosticDescriptorsProvider.NonVirtualSetupSpecification;
_internalSetupSpecificationDescriptor = diagnosticDescriptorsProvider.InternalSetupSpecification;
}

Expand All @@ -36,10 +39,15 @@ private void ReportDiagnostics(
in NonSubstitutableMemberAnalysisResult analysisResult)
{
var location = analysisResult.Member.GetLocation();

if (analysisResult.NonVirtualMemberSubstitution)
{
var descriptor = analysisResult.Symbol is IMethodSymbol { IsExtensionMethod: true }
? this._extensionMethodSetupDescriptor
: NonVirtualSetupDescriptor;

var diagnostic = Diagnostic.Create(
NonVirtualSetupDescriptor,
descriptor,
location,
analysisResult.MemberName);
context.TryReportDiagnostic(diagnostic, analysisResult.Symbol);
Expand Down
8 changes: 8 additions & 0 deletions src/NSubstitute.Analyzers.Shared/DiagnosticDescriptors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ internal class DiagnosticDescriptors<T>
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public static DiagnosticDescriptor ExtensionMethodSetupSpecification { get; } =
CreateDiagnosticDescriptor(
name: nameof(ExtensionMethodSetupSpecification),
id: DiagnosticIdentifiers.ExtensionMethodSetupSpecification,
category: DiagnosticCategory.NonVirtualSubstitution.GetDisplayName(),
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public static DiagnosticDescriptor InternalSetupSpecification { get; } =
CreateDiagnosticDescriptor(
name: nameof(InternalSetupSpecification),
Expand Down
3 changes: 1 addition & 2 deletions src/NSubstitute.Analyzers.Shared/DiagnosticIdentifiers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ internal class DiagnosticIdentifiers
{
public const string NonVirtualSetupSpecification = "NS1000";
public const string NonVirtualReceivedSetupSpecification = "NS1001";

public const string NonVirtualWhenSetupSpecification = "NS1002";

public const string InternalSetupSpecification = "NS1003";
public const string NonSubstitutableMemberArgumentMatcherUsage = "NS1004";
public const string NonVirtualReceivedInOrderSetupSpecification = "NS1005";
public const string ExtensionMethodSetupSpecification = "NS1006";

public const string PartialSubstituteForUnsupportedType = "NS2000";
public const string SubstituteForWithoutAccessibleConstructor = "NS2001";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ internal interface IDiagnosticDescriptorsProvider
{
DiagnosticDescriptor NonVirtualSetupSpecification { get; }

DiagnosticDescriptor ExtensionMethodSetupSpecification { get; }

DiagnosticDescriptor NonVirtualReceivedSetupSpecification { get; }

DiagnosticDescriptor NonVirtualReceivedInOrderSetupSpecification { get; }
Expand Down
21 changes: 19 additions & 2 deletions src/NSubstitute.Analyzers.Shared/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions src/NSubstitute.Analyzers.Shared/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -431,4 +431,17 @@
<data name="SyncOverAsyncThrowsTitle" xml:space="preserve">
<value>Synchronous exception thrown from async method.</value>
</data>

<data name="ExtensionMethodSetupSpecificationDescription" xml:space="preserve">
<value>Extension methods TODO</value>
<comment>An optional longer localizable description of the diagnostic.</comment>
</data>
<data name="ExtensionMethodSetupSpecificationMessageFormat" xml:space="preserve">
<value>Extension methods {0} TODO</value>
<comment>The format-able message the diagnostic displays.</comment>
</data>
<data name="ExtensionMethodSetupSpecificationTitle" xml:space="preserve">
<value>Extension methods TODO</value>
<comment>The title of the diagnostic.</comment>
</data>
</root>

0 comments on commit b3e3eb0

Please sign in to comment.