From c87509e07fd355b8930b2d92f6ca83ea4275c707 Mon Sep 17 00:00:00 2001 From: Koen Bekkenutte <2912652+kbekkenutte@users.noreply.github.com> Date: Mon, 31 May 2021 02:05:57 +0800 Subject: [PATCH] Raise diagnostics when not exposing expression bodies members --- .../AnalyzerReleases.Shipped.md | 3 ++ .../AnalyzerReleases.Unshipped.md | 5 +++ .../Diagnostics.cs | 21 +++++++++ .../ProjectableInterpreter.cs | 14 ++++++ .../ProjectionExpressionGeneratorTests.cs | 43 +++++++++++++++++++ 5 files changed, 86 insertions(+) create mode 100644 src/EntityFrameworkCore.Projections.Generator/AnalyzerReleases.Shipped.md create mode 100644 src/EntityFrameworkCore.Projections.Generator/AnalyzerReleases.Unshipped.md create mode 100644 src/EntityFrameworkCore.Projections.Generator/Diagnostics.cs diff --git a/src/EntityFrameworkCore.Projections.Generator/AnalyzerReleases.Shipped.md b/src/EntityFrameworkCore.Projections.Generator/AnalyzerReleases.Shipped.md new file mode 100644 index 0000000..d567f14 --- /dev/null +++ b/src/EntityFrameworkCore.Projections.Generator/AnalyzerReleases.Shipped.md @@ -0,0 +1,3 @@ +; Shipped analyzer releases +; https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md + diff --git a/src/EntityFrameworkCore.Projections.Generator/AnalyzerReleases.Unshipped.md b/src/EntityFrameworkCore.Projections.Generator/AnalyzerReleases.Unshipped.md new file mode 100644 index 0000000..f69adf0 --- /dev/null +++ b/src/EntityFrameworkCore.Projections.Generator/AnalyzerReleases.Unshipped.md @@ -0,0 +1,5 @@ +### New Rules + +Rule ID | Category | Severity | Notes +--------|----------|----------|-------------------- +EFP0001 | Design | Error | ST0001_AnalyzerName diff --git a/src/EntityFrameworkCore.Projections.Generator/Diagnostics.cs b/src/EntityFrameworkCore.Projections.Generator/Diagnostics.cs new file mode 100644 index 0000000..36f833e --- /dev/null +++ b/src/EntityFrameworkCore.Projections.Generator/Diagnostics.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; + +namespace EntityFrameworkCore.Projections.Generator +{ + public static class Diagnostics + { + public static readonly DiagnosticDescriptor RequiresExpressionBodyDefinition = new( + id: "EFP0001", + title: "Method or property should expose an expression body definition", + messageFormat: "Method or property '{0}' should expose an expression body definition.", + category: "Design", + DiagnosticSeverity.Error, + isEnabledByDefault: true); + + } +} diff --git a/src/EntityFrameworkCore.Projections.Generator/ProjectableInterpreter.cs b/src/EntityFrameworkCore.Projections.Generator/ProjectableInterpreter.cs index 4a34bb6..211bb40 100644 --- a/src/EntityFrameworkCore.Projections.Generator/ProjectableInterpreter.cs +++ b/src/EntityFrameworkCore.Projections.Generator/ProjectableInterpreter.cs @@ -84,6 +84,13 @@ namespace EntityFrameworkCore.Projections.Generator if (memberDeclarationSyntax is MethodDeclarationSyntax methodDeclarationSyntax) { + if (methodDeclarationSyntax.ExpressionBody is null) + { + var diagnostic = Diagnostic.Create(Diagnostics.RequiresExpressionBodyDefinition, methodDeclarationSyntax.GetLocation(), memberSymbol.Name); + context.ReportDiagnostic(diagnostic); + return null; + } + descriptor.ReturnTypeName = methodDeclarationSyntax.ReturnType.ToString(); descriptor.Body = expressionSyntaxRewriter.Visit(methodDeclarationSyntax.ExpressionBody.Expression); foreach (var additionalParameter in ((ParameterListSyntax)parameterSyntaxRewriter.Visit(methodDeclarationSyntax.ParameterList)).Parameters) @@ -93,6 +100,13 @@ namespace EntityFrameworkCore.Projections.Generator } else if (memberDeclarationSyntax is PropertyDeclarationSyntax propertyDeclarationSyntax) { + if (propertyDeclarationSyntax.ExpressionBody is null) + { + var diagnostic = Diagnostic.Create(Diagnostics.RequiresExpressionBodyDefinition, propertyDeclarationSyntax.GetLocation(), memberSymbol.Name); + context.ReportDiagnostic(diagnostic); + return null; + } + descriptor.ReturnTypeName = propertyDeclarationSyntax.Type.ToString(); descriptor.Body = expressionSyntaxRewriter.Visit(propertyDeclarationSyntax.ExpressionBody.Expression); } diff --git a/tests/EntityFrameworkCore.Projections.Generator.Tests/ProjectionExpressionGeneratorTests.cs b/tests/EntityFrameworkCore.Projections.Generator.Tests/ProjectionExpressionGeneratorTests.cs index cc746fe..3ead468 100644 --- a/tests/EntityFrameworkCore.Projections.Generator.Tests/ProjectionExpressionGeneratorTests.cs +++ b/tests/EntityFrameworkCore.Projections.Generator.Tests/ProjectionExpressionGeneratorTests.cs @@ -340,6 +340,49 @@ namespace Foo { return Verifier.Verify(result.GeneratedTrees[0].ToString()); } + [Fact] + public void BlockBodiedMember_RaisesDiagnostics() + { + var compilation = CreateCompilation(@" +using System; +using EntityFrameworkCore.Projections; +namespace Foo { + class C { + [Projectable] + public int Foo + { + get => 1; + } + } +} +"); + + var result = RunGenerator(compilation); + + Assert.Single(result.Diagnostics); + } + + [Fact] + public void BlockBodiedMethod_RaisesDiagnostics() + { + var compilation = CreateCompilation(@" +using System; +using EntityFrameworkCore.Projections; +namespace Foo { + class C { + [Projectable] + public int Foo() + { + return 1; + } + } +} +"); + + var result = RunGenerator(compilation); + + Assert.Single(result.Diagnostics); + } #region Helpers