Skip to content

Commit aba5ad8

Browse files
paulirwinclaude
andcommitted
Report LuceneDev4002 at the call site instead of the target method
Reporting on the target method declaration produced a non-local diagnostic — the analyzer was visiting an InvocationExpressionSyntax but raising the diagnostic on a syntax tree it had not visited. MSBuild ran a full compilation and surfaced the warning, but the IDE's per-file live analysis filtered it out, so the warning never appeared in the editor. Move the report to the DoesStackTraceContainMethod invocation. The diagnostic is now local, shows up in the IDE, and opens the door to a code fix at the call site. The message names the qualified target (e.g. 'Target.Merge') so it remains clear which method needs the attribute. Test span updated accordingly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0c6c007 commit aba5ad8

3 files changed

Lines changed: 15 additions & 5 deletions

File tree

src/Lucene.Net.CodeAnalysis.Dev/LuceneDev4xxx/LuceneDev4002_StackTraceHelperNoInliningAnalyzer.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ private static void AnalyzeInvocation(SyntaxNodeAnalysisContext ctx, INamedTypeS
9999
if (targetType is null)
100100
return;
101101

102+
// Report once per call site if any matching method declaration in source
103+
// is missing NoInlining. Locating the diagnostic on the invocation makes
104+
// it a "local" diagnostic relative to the syntax tree the analyzer is
105+
// visiting, which means the IDE surfaces it (compilation-wide non-local
106+
// diagnostics are filtered out of live IDE analysis) and a code fix can
107+
// be wired up in the future.
102108
foreach (var member in targetType.GetMembers(methodNameValue).OfType<IMethodSymbol>())
103109
{
104110
if (member.MethodKind != MethodKind.Ordinary)
@@ -120,8 +126,9 @@ private static void AnalyzeInvocation(SyntaxNodeAnalysisContext ctx, INamedTypeS
120126

121127
ctx.ReportDiagnostic(Diagnostic.Create(
122128
Descriptors.LuceneDev4002_MissingNoInlining,
123-
methodDecl.GetLocation(),
124-
methodDecl.Identifier.ValueText));
129+
invocation.GetLocation(),
130+
$"{targetType.Name}.{methodDecl.Identifier.ValueText}"));
131+
return;
125132
}
126133
}
127134
}

src/Lucene.Net.CodeAnalysis.Dev/Resources.resx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ under the License.
436436
<value>If a method is referenced by StackTraceHelper.DoesStackTraceContainMethod and the JIT inlines it, the method will not appear in the stack trace and the check will silently fail. Apply [MethodImpl(MethodImplOptions.NoInlining)] to the method.</value>
437437
</data>
438438
<data name="LuceneDev4002_AnalyzerMessageFormat" xml:space="preserve">
439-
<value>'{0}' is referenced by StackTraceHelper.DoesStackTraceContainMethod and should be marked with [MethodImpl(MethodImplOptions.NoInlining)] to prevent the JIT from inlining it out of the stack trace.</value>
439+
<value>'{0}' is referenced by this StackTraceHelper.DoesStackTraceContainMethod call and should be marked with [MethodImpl(MethodImplOptions.NoInlining)] to prevent the JIT from inlining it out of the stack trace.</value>
440440
</data>
441441

442442
</root>

tests/Lucene.Net.CodeAnalysis.Dev.Tests/LuceneDev4xxx/TestLuceneDev4002_StackTraceHelperNoInliningAnalyzer.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,13 @@ public void Check()
6464
}
6565
}" + StackTraceHelperStub;
6666

67+
// Diagnostic is now reported on the DoesStackTraceContainMethod invocation
68+
// (call site) so the IDE can surface it and a future code fix can be hooked
69+
// up. Argument is the qualified target method name.
6770
var expected = new DiagnosticResult(Descriptors.LuceneDev4002_MissingNoInlining)
6871
.WithSeverity(DiagnosticSeverity.Warning)
69-
.WithSpan(4, 5, 7, 6)
70-
.WithArguments("Merge");
72+
.WithSpan(14, 13, 14, 132)
73+
.WithArguments("Target.Merge");
7174

7275
var test = new InjectableCSharpAnalyzerTest(() => new LuceneDev4002_StackTraceHelperNoInliningAnalyzer())
7376
{

0 commit comments

Comments
 (0)