Generate diagnostic when null conditional expressions are used but rewrite is not configured

This commit is contained in:
Koen Bekkenutte
2021-10-18 23:08:36 +08:00
parent 58770723dd
commit 8ccb73d424
5 changed files with 40 additions and 2 deletions
@@ -2,3 +2,4 @@
Rule ID | Category | Severity | Notes
--------|----------|----------|--------------------
EFP0002 | Design | Error |
@@ -17,5 +17,13 @@ namespace EntityFrameworkCore.Projectables.Generator
DiagnosticSeverity.Error,
isEnabledByDefault: true);
public static readonly DiagnosticDescriptor NullConditionalRewriteUnsupported = new(
id: "EFP0002",
title: "Method or property is not configured to support null-conditional expressions.",
messageFormat: "'{0}' has a null-conditional expression exposed but is not configured to rewrite this. Consider configuring a strategy using the NullConditionalRewriteSupport property on the Projectable attribute",
category: "Design",
DiagnosticSeverity.Error,
isEnabledByDefault: true);
}
}
@@ -15,13 +15,15 @@ namespace EntityFrameworkCore.Projectables.Generator
readonly INamedTypeSymbol _targetTypeSymbol;
readonly SemanticModel _semanticModel;
readonly NullConditionalRewriteSupport _nullConditionalRewriteSupport;
readonly GeneratorExecutionContext _context;
readonly Stack<ExpressionSyntax> _conditionalAccessExpressionsStack = new();
public ExpressionSyntaxRewriter(INamedTypeSymbol targetTypeSymbol, SemanticModel semanticModel, NullConditionalRewriteSupport nullConditionalRewriteSupport)
public ExpressionSyntaxRewriter(INamedTypeSymbol targetTypeSymbol, SemanticModel semanticModel, NullConditionalRewriteSupport nullConditionalRewriteSupport, GeneratorExecutionContext context)
{
_targetTypeSymbol = targetTypeSymbol;
_semanticModel = semanticModel;
_nullConditionalRewriteSupport = nullConditionalRewriteSupport;
_context = context;
}
public override SyntaxNode? VisitConditionalAccessExpression(ConditionalAccessExpressionSyntax node)
@@ -30,6 +32,12 @@ namespace EntityFrameworkCore.Projectables.Generator
_conditionalAccessExpressionsStack.Push(targetExpression);
if (_nullConditionalRewriteSupport == NullConditionalRewriteSupport.None)
{
var diagnostic = Diagnostic.Create(Diagnostics.NullConditionalRewriteUnsupported, node.GetLocation(), node);
_context.ReportDiagnostic(diagnostic);
}
return _nullConditionalRewriteSupport switch {
NullConditionalRewriteSupport.Ignore => Visit(node.WhenNotNull),
NullConditionalRewriteSupport.Rewrite =>
@@ -51,7 +51,7 @@ namespace EntityFrameworkCore.Projectables.Generator
.Cast<NullConditionalRewriteSupport>()
.FirstOrDefault();
var expressionSyntaxRewriter = new ExpressionSyntaxRewriter(memberSymbol.ContainingType, semanticModel, nullConditionalRewriteSupport);
var expressionSyntaxRewriter = new ExpressionSyntaxRewriter(memberSymbol.ContainingType, semanticModel, nullConditionalRewriteSupport, context);
var parameterSyntaxRewriter = new ParameterSyntaxRewriter(semanticModel);
var returnTypeSyntaxRewriter = new ReturnTypeSyntaxRewriter(semanticModel);
@@ -487,6 +487,27 @@ namespace Foo {
return Verifier.Verify(result.GeneratedTrees[0].ToString());
}
[Fact]
public void NullableMemberBinding_WithoutSupport_IsBeingReported()
{
var compilation = CreateCompilation(@"
using System;
using System.Linq;
using EntityFrameworkCore.Projectables;
namespace Foo {
static class C {
[Projectable(NullConditionalRewriteSupport = NullConditionalRewriteSupport.None)]
public static int? GetLength(this string input) => input?.Length;
}
}
");
var result = RunGenerator(compilation);
var diagnostic = Assert.Single(result.Diagnostics);
Assert.Equal("EFP0002", diagnostic.Id);
}
[Fact]
public Task NullableMemberBinding_WithIgnoreSupport_IsBeingRewritten()
{