From 11d92abadcec44ec9c76f6579b1997bcb1fc07e1 Mon Sep 17 00:00:00 2001 From: ancplua Date: Mon, 4 May 2026 14:59:05 +0200 Subject: [PATCH 1/2] chore: add Copilot PR-review instructions Add .github/copilot-instructions.md scoping Copilot Code Review to the five-package shape: netstandard2.0 surface constraints (no System.Text.Json or modern BCL in main lib / Sources), Sources visibility-rewrite invariant (#if ANCPLUA_ROSLYN_PUBLIC), generator hot-path patterns (ref structs, EquatableArray, closure-free dict ops), Guard.cs as the sole RS1035 allow-list site. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/copilot-instructions.md | 68 +++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..c8d09e8 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,68 @@ +# Copilot PR-review instructions for ANcpLua.Roslyn.Utilities + +Utility library for Roslyn incremental generators, analyzers, and code-fix +providers. Ships five NuGet packages: a binary library, a `Sources` source-only +package (rewritten to `internal` at pack via `Transform-Sources.ps1`), `Polyfills`, +`Testing` (analyzer/generator/codefix harness), and `Testing.Aot`. Main library + +`Sources` target `netstandard2.0` so Roslyn-hosted consumers can absorb them; +`Testing` targets `net10.0`. `TreatWarningsAsErrors=true` repo-wide; all analyzer +diagnostics elevated to error in `.editorconfig`. This file scopes to PR review only. + +## Flag + +- New API in the main library (or `Sources`) that pulls in dependencies not + available on `netstandard2.0` — `System.Text.Json`, modern BCL methods, anything + ns2.1+. Such code can land in `Testing` or downstream consumers, but not in + the analyzer-hosted surface. +- New `public` type or member added to the `Sources` project without a + `#if ANCPLUA_ROSLYN_PUBLIC public #else internal #endif` guard — the Sources + package rewrites visibility on pack, so adding bare `public` breaks the + internal-on-pack contract. +- Storing `ISymbol`, `SyntaxNode`, `SyntaxTree`, or any Roslyn reference type as + a `HashSet` / `Dictionary` key — reference equality, cache misses + on rebuild, breaks generator incrementality. +- New allocations in generator hot paths: `.ToArray()` / `.ToList()` on a `Span` + inside `Append` loops, capturing closures in `Dict.GetOrAdd`/`GetOrInsert`, + boxing of value types via `object`. The `closure-free` `GetOrInsert` + + `static` lambda + `ValueStringBuilder` patterns are the established shape. +- Public types intended for generator payloads added without value equality — + use `readonly record struct` (or `EquatableArray` for collections), never + classes or non-record structs. +- File-I/O via `System.IO.File` / `System.IO.Directory` outside `Guard.cs` — + `Guard.cs` is the single allow-listed call site (suppressed `RS1035`). + +## utilities-specific + +- The `Sources` package is for source generators that can't take a binary + reference. Any new helper meant for that consumer set goes in + `src/ANcpLua.Roslyn.Utilities/` (the shared tree) and gets exposed via the + `Sources` package on pack. +- `Polyfills` package supplies `init`, `required`, `Index`/`Range`, nullable + + trim attributes for `netstandard2.0` consumers. Don't duplicate polyfills in + the main library. +- `Testing` ships a fluent generator/analyzer/codefix harness. New test helpers + belong there, not in individual consumer test projects. +- `EquatableArray` is `ref`-struct-like (value-equality wrapper); use it for + collection fields in generator records, not `ImmutableArray` (no equality) + or `T[]` (reference equality). + +## Do not flag + +- Allow-listed suppressions in `Guard.cs`: `#pragma warning disable RS1035` + (file I/O legal here, non-analyzer call sites only). +- Polyfills suppressions: `CA1019`, `RCS1251`, `IDE0300`, `CA1064`, `CA1812`, + `SA1623`, `RCS1157` — all on shim types. +- Testing-csproj suppressions: `NU1903`, `RS1036`, `RS1038`, `RS1041`, `CA1019`, + `NU5104`, `CA1859`, `RS0030`, `CA1307`, `IDE1006`, `CA1002`, `CA1000`, + `CS1574`, `CS1591` — test-infra concessions. +- `[ExcludeFromCodeCoverage]` only appears on polyfills, not on mainline types + — that's intentional, mainline gets coverage. +- `Testing` package's use of `System.Text.Json` and modern BCL — it's `net10.0`, + not the constrained surface. + +## Project context + +Solo-dev repo. The Sources package is consumed by `ANcpLua.Analyzers` and +`ANcpLua.Agents.Testing` (and downstream generators); regressions ripple. Breaking +changes are allowed in the same session — bump major, fix consumers, ship. +Don't suggest backwards-compat shims or feature flags within a single PR. From eaa8194c867845622ccc11c5fb90c5de27127d41 Mon Sep 17 00:00:00 2001 From: ancplua Date: Mon, 4 May 2026 15:00:04 +0200 Subject: [PATCH 2/2] ci(publish): grep -qFx for tag exact-match + parenthesize multi-condition if MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two zero-risk readability/robustness tweaks on the auto-bump workflow: - grep -qFx (literal-string match) instead of grep -qx — avoids regex metachar surprises if a tag ever contains a literal . or * - (push && main) || dispatch — parens make the precedence explicit (no behavior change; YAML expression already evaluated in this order) Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/nuget-publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index dfe1c8e..343e0ca 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -49,7 +49,7 @@ jobs: MAJOR=${BASH_REMATCH[1]} MINOR=${BASH_REMATCH[2]} PATCH=${BASH_REMATCH[3]} - if git tag --points-at HEAD | grep -qx "$LATEST_TAG"; then + if git tag --points-at HEAD | grep -qFx "$LATEST_TAG"; then VERSION="$MAJOR.$MINOR.$PATCH" echo "HEAD is tagged $LATEST_TAG — reusing version: $VERSION" else @@ -116,7 +116,7 @@ jobs: # 3. No NUGET_API_KEY secret required — OIDC handles auth. publish: needs: [version, build] - if: github.event_name == 'push' && github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch' + if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest environment: nuget permissions: