Conversation
…ce file, into a partial class
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
This PR refactors the PolyfillInterceptorGenerator to emit one generated interceptor file per input source file by generating into a shared static partial interceptor class, aiming to reduce incremental-generator overhead as call site counts grow.
Changes:
- Update generator pipeline to process/emit per
CompilationUnitSyntax, producing one.g.csper source file and using a partialPolyfillInterceptorsclass. - Change generated interceptor/method naming to include a file-derived tag + call-site line/column for uniqueness.
- Update benchmarks and snapshot-verified test outputs to match the new emission strategy and identifiers.
Reviewed changes
Copilot reviewed 93 out of 93 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/ExpressiveSharp.Generator/PolyfillInterceptorGenerator.cs | Refactors generator to emit one generated file per source file; updates naming, caching comparer, and emission logic. |
| benchmarks/ExpressiveSharp.Benchmarks/PolyfillGeneratorBenchmarks.cs | Expands/renames benchmarks to measure cold vs incremental edits and single-file vs multi-file scenarios. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/WhereTests.cs | Adds using System.Linq; (currently appears unused). |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SingleLambdaQueryableTests.cs | Adds using System.Linq; (currently appears unused). |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/OrderByTests.cs | Adds using System.Linq; (currently appears unused). |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ZipTests.Zip_WithResultSelector_GeneratesInterceptor.verified.txt | Updates snapshot to partial class + new method/variable identifiers. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/WhereTests.Where_SimpleCondition_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/WhereTests.Where_CapturedVariable_GeneratesClosureAccess.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/WhereTests.Where_CapturedInstanceField_GeneratesClosureAccess.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/WhereTests.ChainedWhereAndSelect_GeneratesTwoInterceptors.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SingleLambdaQueryableTests.ThenByDescending_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SingleLambdaQueryableTests.TakeWhile_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SingleLambdaQueryableTests.SkipWhile_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SingleLambdaQueryableTests.OrderByDescending_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SingleLambdaQueryableTests.DistinctBy_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SingleLambdaQueryableTests.CountBy_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SetOperationTests.UnionBy_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SetOperationTests.IntersectBy_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SetOperationTests.ExceptBy_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SelectTests.Select_NamedType_GeneratesConcreteInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SelectTests.Select_AnonymousType_GeneratesGenericInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SelectTests.Select_AnonymousType_WithComputedExpression_GeneratesCorrectly.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SelectManyTests.SelectMany_CollectionSelector_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/SelectManyTests.SelectMany_WithResultSelector_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Sum_NullableLongSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Sum_NullableIntSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Sum_NullableFloatSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Sum_NullableDoubleSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Sum_NullableDecimalSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Sum_LongSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Sum_IntSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Sum_FloatSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Sum_DoubleSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Sum_DecimalSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Single_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.SingleOrDefault_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Min_GenericSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.MinBy_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Max_GenericSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.MaxBy_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.LongCount_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Last_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.LastOrDefault_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.First_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.FirstOrDefault_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Count_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Average_NullableLongSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Average_NullableIntSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Average_NullableFloatSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Average_NullableDoubleSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Average_NullableDecimalSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Average_LongSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Average_IntSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Average_FloatSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Average_DoubleSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Average_DecimalSelector_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.Any_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ScalarMethodTests.All_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/PolyfillTests.Polyfill_SimpleLambda_GeneratesExpression.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/PolyfillTests.Polyfill_NullConditional_RewritesOperator.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/PolyfillTests.Polyfill_InferredTypeArgument_GeneratesExpression.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/PolyfillTests.Polyfill_CapturedVariable_GeneratesClosureAccess.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/PolyfillTargetTests.PolyfillTarget_WithoutAttribute_DefaultsToQueryable.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/PolyfillTargetTests.PolyfillTarget_RoutesToSpecifiedType.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/OrderByTests.ThenBy_CastsToIOrderedQueryable.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/OrderByTests.OrderBy_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/NullConditionalTests.NullConditionalRewrite_ExpandsInWhereBody.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/JoinTests.Join_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/JoinTests.Join_AnonymousResultSelector_GeneratesGenericInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/JoinTests.GroupJoin_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/JoinTests.GroupJoin_AnonymousResultSelector_GeneratesGenericInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/GroupByTests.GroupBy_WithResultSelector_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/GroupByTests.GroupBy_WithElementSelector_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/GroupByTests.GroupBy_WithElementAndResultSelector_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/GroupByTests.GroupBy_GeneratesGroupingReturnType.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/GlobalOptionsTests.Where_PerCallOverridesGlobal.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/GlobalOptionsTests.Where_GlobalNullConditionalRewrite_AppliesWithoutPerCallOverride.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/GlobalOptionsTests.Polyfill_GlobalNullConditionalIgnore_UsesIgnoreMode.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ExecuteUpdateTests.ExecuteUpdate_SetProperty_WithSwitchExpression.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ExecuteUpdateTests.ExecuteUpdate_SetProperty_WithNullConditional.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ExecuteUpdateTests.ExecuteUpdate_SetProperty_ConstantValue.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ExecuteUpdateTests.ExecuteUpdateAsync_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ComparerOverloadTests.OrderBy_WithComparer_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ComparerOverloadTests.GroupBy_WithComparer_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ComparerOverloadTests.DistinctBy_WithComparer_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/AnonymousElementTests.Where_AfterAnonymousSelect_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/AnonymousElementTests.Select_AfterAnonymousSelect_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/AnonymousElementTests.OrderByDescending_AfterAnonymousSelect_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/AnonymousElementTests.GroupBy_AfterAnonymousSelect_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/AnonymousElementTests.DistinctBy_AfterAnonymousSelect_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/AnonymousElementTests.Count_AfterAnonymousSelect_GeneratesScalarInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/AggregateByTests.AggregateBy_WithSeedSelector_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
| tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/AggregateByTests.AggregateBy_GeneratesInterceptor.verified.txt | Snapshot update for new naming/emission. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Combine with the compilation so ProcessFileAndEmit can build a SemanticModel. | ||
| // | ||
| // WithComparer uses REFERENCE equality on the CompilationUnitSyntax root node: | ||
| // • Roslyn syntax trees are immutable — editing a noise file creates a new | ||
| // Compilation but keeps every other file's syntax tree root as the EXACT | ||
| // SAME object reference across incremental runs. | ||
| // • All untouched source files compare as "equal" → RegisterSourceOutput | ||
| // skipped entirely → O(1) incremental cost for noise-file edits. | ||
| // • Only files that were actually edited get a new root reference → re-run. | ||
| var filesWithCompilation = candidateFiles | ||
| .Combine(context.CompilationProvider) | ||
| .WithComparer(CompilationUnitAndCompilationComparer.Instance); | ||
|
|
There was a problem hiding this comment.
The new .WithComparer(CompilationUnitAndCompilationComparer) ignores the Compilation entirely (reference-equality only on the CompilationUnitSyntax). This can cause stale generated interceptors when the compilation changes without this file’s syntax root changing (e.g., referenced assembly updates, symbol changes from other file edits that affect binding in this file). Consider incorporating relevant compilation identity into equality (at least ExternalReferences like MemberDeclarationSyntaxAndCompilationEqualityComparer does) so semantic-dependent output is recomputed when needed.
| @@ -181,26 +225,63 @@ public InterceptsLocationAttribute(int version, string data) { } | |||
| } | |||
| """; | |||
|
|
|||
| spc.AddSource("PolyfillInterceptors.g.cs", | |||
| spc.AddSource(ComputeOutputFileName(sourcePath), | |||
| SourceText.From(source, Encoding.UTF8)); | |||
| } | |||
|
|
|||
| /// <summary> | |||
| /// Computes a stable output file name for a given source file. | |||
| /// One interceptor file is generated per source file, keyed by the full 32-bit | |||
| /// FNV-1a hash of the source path. | |||
| /// </summary> | |||
| private static string ComputeOutputFileName(string sourcePath) | |||
| { | |||
| unchecked | |||
| { | |||
| var hash = 2166136261u; | |||
| for (var i = 0; i < sourcePath.Length; i++) | |||
| { | |||
| hash ^= (uint)sourcePath[i]; | |||
| hash *= 16777619u; | |||
| } | |||
| return "PolyfillInterceptors_" + hash.ToString("x8") + ".g.cs"; | |||
| } | |||
| } | |||
|
|
|||
| /// <summary> | |||
| /// Returns a short (4-char hex) tag derived from the source file path hash. | |||
| /// Used as a prefix in interceptor method names to prevent collisions between | |||
| /// files that have call sites at identical line/col positions. | |||
| /// </summary> | |||
| private static string GetFileTag(string sourcePath) | |||
| { | |||
| unchecked | |||
| { | |||
| var hash = 2166136261u; | |||
| for (var i = 0; i < sourcePath.Length; i++) | |||
| { | |||
| hash ^= (uint)sourcePath[i]; | |||
| hash *= 16777619u; | |||
| } | |||
| return (hash & 0xFFFFu).ToString("x4"); | |||
| } | |||
| } | |||
There was a problem hiding this comment.
ComputeOutputFileName/GetFileTag are derived from SyntaxTree.FilePath. In real builds FilePath is often an absolute path, so method names + hint names may vary across machines, undermining deterministic/reproducible builds. Also, if FilePath is empty (possible for in-memory trees), multiple trees will hash to the same value, causing AddSource hint-name collisions. Consider basing the hash on a stable project-relative path (via AnalyzerConfigOptions) and/or including a fallback unique key when FilePath is empty.
| /// <summary> | ||
| /// Returns a short (4-char hex) tag derived from the source file path hash. | ||
| /// Used as a prefix in interceptor method names to prevent collisions between | ||
| /// files that have call sites at identical line/col positions. | ||
| /// </summary> | ||
| private static string GetFileTag(string sourcePath) | ||
| { | ||
| unchecked | ||
| { | ||
| var hash = 2166136261u; | ||
| for (var i = 0; i < sourcePath.Length; i++) | ||
| { | ||
| hash ^= (uint)sourcePath[i]; | ||
| hash *= 16777619u; | ||
| } | ||
| return (hash & 0xFFFFu).ToString("x4"); | ||
| } |
There was a problem hiding this comment.
GetFileTag truncates the path hash to 16 bits. In solutions with a few hundred+ source files, collisions become plausible and would produce duplicate interceptor method names across files (same fileTag + line/col), causing compilation failures in the generated partial class. Use a larger tag (e.g., full 32-bit hash) or incorporate additional disambiguation.
| var lineSpan = inv.GetLocation().GetLineSpan(); | ||
| spc.ReportDiagnostic(Diagnostic.Create( | ||
| Diagnostics.InterceptorEmissionFailed, | ||
| inv.GetLocation(), | ||
| Location.Create( | ||
| lineSpan.Path, | ||
| new TextSpan(0, 0), | ||
| new LinePositionSpan( | ||
| new LinePosition(lineSpan.StartLinePosition.Line, lineSpan.StartLinePosition.Character), | ||
| new LinePosition(lineSpan.StartLinePosition.Line, lineSpan.StartLinePosition.Character))), | ||
| ex.GetType().Name + ": " + ex.Message)); |
There was a problem hiding this comment.
The diagnostic location built in the catch block uses TextSpan(0, 0), which can make the reported diagnostic point to the start of the file rather than the failing invocation span (affecting navigation/squiggles). Prefer reporting inv.GetLocation() (or Location.Create with inv.Span) so the diagnostic accurately highlights the call site.
| using System.Linq; | ||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
| using VerifyMSTest; |
There was a problem hiding this comment.
This new using System.Linq; appears unused in this test file (it only appears inside the source string). With TreatWarningsAsErrors enabled, an unused using directive will fail the build. Please remove it unless it’s actually needed.
| using System.Linq; | ||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
| using VerifyMSTest; |
There was a problem hiding this comment.
This new using System.Linq; appears unused in this test file (it only appears inside the source string). With TreatWarningsAsErrors enabled, an unused using directive will fail the build. Please remove it unless it’s actually needed.
| using System.Linq; | ||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
| using VerifyMSTest; |
There was a problem hiding this comment.
This new using System.Linq; appears unused in this test file (it only appears inside the source string). With TreatWarningsAsErrors enabled, an unused using directive will fail the build. Please remove it unless it’s actually needed.
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Thread SourceProductionContext through TryEmitPolyfill / TryEmit / EmitGenericLambda / EmitLambdaBody so ExpressionTreeEmitter can report EXP0007, EXP0008, EXP0009, EXP0011, and EXP0018 for lambdas in IExpressiveQueryable LINQ calls and ExpressionPolyfill.Create. Previously passing context: null silenced these warnings; users would get runtime default-value behavior with no compile-time signal. Also restore EXP0010 (InterceptorEmissionFailed) to use inv.GetLocation() instead of a zero-width span at the invocation's starting line/col, so IDEs highlight the full invocation again. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
I noticed a single file was emitted for every generated polyfill, which might become problematic, here are the benchmarks, for multiple files :