diff --git a/EasySourceGenerators.GeneratorTests/SimpleMethodWithParameter.cs b/EasySourceGenerators.GeneratorTests/SimpleMethodWithParameter.cs new file mode 100644 index 0000000..190889c --- /dev/null +++ b/EasySourceGenerators.GeneratorTests/SimpleMethodWithParameter.cs @@ -0,0 +1,41 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +namespace EasySourceGenerators.GeneratorTests; + +public class SimpleMethodWithParameterTests +{ + [Test] + public void SimpleMethodWithParameterTests_Test() + { + string source = """ + using EasySourceGenerators.Abstractions; + + namespace TestNamespace; + + public partial class SimpleMethodWithParameterClass + { + public partial int SimpleMethodWithParameter(int someIntParameter); + + [GeneratesMethod(sameClassMethodName: nameof(SimpleMethodWithParameter))] + private static int SimpleMethodWithParameter_Generator(int someIntParameter) + { + return 5; + } + } + """; + + ImmutableArray diagnostics = GeneratorTestHelper.GetGeneratorOnlyDiagnostics(source); + + Diagnostic? msgh007 = diagnostics.FirstOrDefault(diagnostic => diagnostic.Id == "MSGH007"); + Assert.That(msgh007, Is.Not.Null, "Expected MSGH007 for simple generator method with runtime parameter."); + Assert.That(msgh007!.Location.IsInSource, Is.True, "MSGH007 should point to generator source."); + + TextSpan span = msgh007.Location.SourceSpan; + string highlightedCode = source.Substring(span.Start, span.Length); + Assert.That(highlightedCode, Does.Contain("SimpleMethodWithParameter_Generator(int someIntParameter)")); + Assert.That(highlightedCode, Does.Not.Contain("return 5;"), + "MSGH007 should highlight the generator method signature, not the method body."); + } +} diff --git a/EasySourceGenerators.Generators/AnalyzerReleases.Unshipped.md b/EasySourceGenerators.Generators/AnalyzerReleases.Unshipped.md index 0db95df..8043d84 100644 --- a/EasySourceGenerators.Generators/AnalyzerReleases.Unshipped.md +++ b/EasySourceGenerators.Generators/AnalyzerReleases.Unshipped.md @@ -7,4 +7,5 @@ MSGH002 | GeneratesMethodGenerator | Error | GeneratesMethodGenerator MSGH003 | GeneratesMethodGenerator | Disabled | GeneratesMethodGenerator MSGH004 | GeneratesMethodGenerator | Error | GeneratesMethodGenerator MSGH005 | GeneratesMethodGenerator | Error | GeneratesMethodGenerator -MSGH006 | GeneratesMethodGenerator | Error | GeneratesMethodGenerator \ No newline at end of file +MSGH006 | GeneratesMethodGenerator | Error | GeneratesMethodGenerator +MSGH007 | GeneratesMethodGenerator | Error | GeneratesMethodGeneratorDiagnostics \ No newline at end of file diff --git a/EasySourceGenerators.Generators/GeneratesMethodGenerationPipeline.cs b/EasySourceGenerators.Generators/GeneratesMethodGenerationPipeline.cs index a52ab9d..22c8858 100644 --- a/EasySourceGenerators.Generators/GeneratesMethodGenerationPipeline.cs +++ b/EasySourceGenerators.Generators/GeneratesMethodGenerationPipeline.cs @@ -1,5 +1,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; using System.Collections.Immutable; using static EasySourceGenerators.Generators.Consts; @@ -71,6 +72,21 @@ private static string GenerateSourceForGroup( compilation); } + List methodsWithParameters = methods + .Where(method => method.Symbol.Parameters.Length > 0) + .ToList(); + if (methodsWithParameters.Count > 0) + { + foreach (GeneratesMethodGenerationTarget methodWithParameters in methodsWithParameters) + { + context.ReportDiagnostic(Diagnostic.Create( + GeneratesMethodGeneratorDiagnostics.CannotUseRuntimeParameterForCompileTimeGeneratorError, + GetMethodSignatureLocation(methodWithParameters.Syntax))); + } + + return string.Empty; + } + return GenerateFromSimplePattern(context, firstMethod, compilation); } @@ -105,4 +121,10 @@ private static bool HasAttribute(IMethodSymbol methodSymbol, string fullAttribut return methodSymbol.GetAttributes() .Any(attribute => attribute.AttributeClass?.ToDisplayString() == fullAttributeTypeName); } + + private static Location GetMethodSignatureLocation(MethodDeclarationSyntax methodSyntax) + { + TextSpan signatureSpan = TextSpan.FromBounds(methodSyntax.SpanStart, methodSyntax.ParameterList.Span.End); + return Location.Create(methodSyntax.SyntaxTree, signatureSpan); + } } diff --git a/EasySourceGenerators.Generators/GeneratesMethodGenerator.Diagnostics.cs b/EasySourceGenerators.Generators/GeneratesMethodGenerator.Diagnostics.cs index b24f756..d9a5dbf 100644 --- a/EasySourceGenerators.Generators/GeneratesMethodGenerator.Diagnostics.cs +++ b/EasySourceGenerators.Generators/GeneratesMethodGenerator.Diagnostics.cs @@ -53,4 +53,12 @@ internal static class GeneratesMethodGeneratorDiagnostics category: Category, defaultSeverity: DiagnosticSeverity.Error, isEnabledByDefault: true); + + internal static readonly DiagnosticDescriptor CannotUseRuntimeParameterForCompileTimeGeneratorError = new( + id: "MSGH007", + title: "Cannot use runtime parameter for compile-time generator", + messageFormat: "Method generators cannot have any parameters, as they will be run at compile time to generate the method output value. Use MethodTemplate if you want to emit method body instead of single value.", + category: Category, + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true); }