Skip to content

Commit

Permalink
raise a diagnostic if rpc context is marked [Dependency] (#737)
Browse files Browse the repository at this point in the history
Closes: #716
  • Loading branch information
omsmith authored Apr 5, 2021
1 parent 73ddc05 commit 01f9547
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 8 deletions.
33 changes: 25 additions & 8 deletions src/D2L.CodeStyle.Analyzers/ApiUsage/RpcAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
namespace D2L.CodeStyle.Analyzers.ApiUsage {
[DiagnosticAnalyzer( LanguageNames.CSharp )]
internal sealed class RpcAnalyzer : DiagnosticAnalyzer {
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
=> ImmutableArray.Create( Diagnostics.RpcContextFirstArgument, Diagnostics.RpcArgumentSortOrder );
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
Diagnostics.RpcContextFirstArgument,
Diagnostics.RpcArgumentSortOrder,
Diagnostics.RpcContextMarkedDependency
);

public override void Initialize( AnalysisContext context ) {
context.EnableConcurrentExecution();
Expand Down Expand Up @@ -83,7 +86,8 @@ INamedTypeSymbol dependencyAttributeType
method,
rpcContextType: rpcContextType,
rpcPostContextType: rpcPostContextType,
rpcPostContextBaseType: rpcPostContextBaseType
rpcPostContextBaseType: rpcPostContextBaseType,
dependencyAttributeType: dependencyAttributeType
);

// dependencyAttributeType may be null if that DLL isn't
Expand Down Expand Up @@ -118,7 +122,8 @@ private static void CheckThatFirstArgumentIsIRpcContext(
MethodDeclarationSyntax method,
INamedTypeSymbol rpcContextType,
INamedTypeSymbol rpcPostContextType,
INamedTypeSymbol rpcPostContextBaseType
INamedTypeSymbol rpcPostContextBaseType,
INamedTypeSymbol dependencyAttributeType
) {
var ps = method.ParameterList.Parameters;

Expand All @@ -141,6 +146,12 @@ INamedTypeSymbol rpcPostContextBaseType
context.ReportDiagnostic(
Diagnostic.Create( Diagnostics.RpcContextFirstArgument, firstParam.GetLocation() )
);
} else if( dependencyAttributeType != null
&& IsMarkedDependency( dependencyAttributeType, firstParam, context.SemanticModel )
) {
context.ReportDiagnostic(
Diagnostic.Create( Diagnostics.RpcContextMarkedDependency, firstParam.GetLocation() )
);
}
}

Expand All @@ -151,10 +162,7 @@ INamedTypeSymbol dependencyAttributeType
) {
bool doneDependencies = false;
foreach( var param in ps.Skip( 1 ) ) {
var isDep = param
.AttributeLists
.SelectMany( al => al.Attributes )
.Any( attr => IsAttribute( dependencyAttributeType, attr, context.SemanticModel ) );
var isDep = IsMarkedDependency( dependencyAttributeType, param, context.SemanticModel );

if( !isDep && !doneDependencies ) {
doneDependencies = true;
Expand All @@ -164,6 +172,15 @@ INamedTypeSymbol dependencyAttributeType
}
}

private static bool IsMarkedDependency(
INamedTypeSymbol dependencyAttributeType,
ParameterSyntax parameter,
SemanticModel model
) => parameter
.AttributeLists
.SelectMany( al => al.Attributes )
.Any( attr => IsAttribute( dependencyAttributeType, attr, model ) );

private static bool IsAttribute(
INamedTypeSymbol expectedType,
AttributeSyntax attr,
Expand Down
9 changes: 9 additions & 0 deletions src/D2L.CodeStyle.Analyzers/Diagnostics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -580,5 +580,14 @@ public static class Diagnostics {
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true
);

public static readonly DiagnosticDescriptor RpcContextMarkedDependency = new DiagnosticDescriptor(
id: "D2L0078",
title: "RPC context argument should not be marked [Dependency]",
messageFormat: "RPC context argument should not be marked [Dependency]",
category: "Correctness",
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true
);
}
}
15 changes: 15 additions & 0 deletions tests/D2L.CodeStyle.Analyzers.Test/Specs/RpcAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,20 @@ public static void IncorrectDependencySortOrderEvenWithRandomBadAttributeInTheMi
[UndefinedAttribute] int x,
/* RpcArgumentSortOrder */ [Dependency] FooDependency foo /**/
) { }

[Rpc]
public static void RpcContextMarkedDependency(
/* RpcContextMarkedDependency */ [Dependency] IRpcContext context /**/
) { }

[Rpc]
public static void RpcPostContextMarkedDependency(
/* RpcContextMarkedDependency */ [Dependency] IRpcPostContext context /**/
) { }

[Rpc]
public static void RpcPostContextBaseMarkedDependency(
/* RpcContextMarkedDependency */ [Dependency] IRpcPostContextBase context /**/
) { }
}
}

0 comments on commit 01f9547

Please sign in to comment.