Fix .cssig round-trips for records, generic constraints, and interface members - #33
Merged
Conversation
Roslyn models each `extension(Receiver) { ... }` block as a nested type
with an unspeakable, compiler-generated name. The writer emitted these as
nameless `public class { ... }` declarations, producing broken `.cssig`
files for projects that use extension members.
- Add ExtensionMembers helper isolating the Roslyn-version-sensitive logic
(numeric TypeKind.Extension, reflective ExtensionParameter) so the
analyzer keeps targeting the older Roslyn baseline.
- CsSigWriter now emits proper `extension<T>(receiver) { ... }` blocks
(deterministically ordered), rendering the receiver with ref-kind and
nullability.
- SignatureModel keys extension markers by the fixed `<extension>`
discriminator plus their receiver type, so distinct blocks with the same
receiver are not conflated.
- ApiSurface no longer double-counts the implicit implementation methods the
compiler synthesises on the host static class; the members are tracked
through the extension marker types instead.
- Bump the test harness to Roslyn 5.x (Microsoft.CodeAnalysis.Analyzer.Testing
1.1.4, CSharp.Workspaces 5.3.0) and add round-trip + soundness regression
tests for extension members.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Now that the analyzer requires C# 14 extension support anyway, bump the analyzer/code-fix projects from the Microsoft.CodeAnalysis 4.0 baseline to 5.0 and drop the version-compatibility workarounds: - ExtensionMembers uses INamedTypeSymbol.IsExtension / ExtensionParameter and TypeKind.Extension directly instead of numeric enum values and reflection. - SignatureModel uses RefKind.RefReadOnlyParameter directly instead of the numeric (RefKind)4 fallback. - Suppress RS1035/RS1037 (newly enforced by the updated analyzer-rules package) via a global config: RS1035 only fires on the third-party IndentingBuilder source, and RS1037 is an orthogonal optimisation hint. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Apply consistent multiline formatting across the CsSig projects and refine the analyzer, recognizer, writer, signature model, and code-fix provider. Switch the test harness from the obsolete XUnitVerifier-based Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.XUnit package to Microsoft.CodeAnalysis.CSharp.Analyzer.Testing 1.1.4. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
C# 14 extension-member support is a new feature. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e members Resolves several cases where the writer and analyzer disagreed about the API surface, surfaced by running the analyzer over the serde project: - Positional records: emit the primary constructor parameter list and the record base clause in the type header, and skip the synthesized primary constructor and positional properties (they are carried by the header). - Constructors: emit a `private` stub for records/classes whose only declared constructors are inaccessible (including an abstract record with an explicit private parameterless constructor), to suppress the public/protected parameterless constructor the compiler would otherwise synthesize. - Generic constraints: carry `where` clauses on types and methods. Constraints change member semantics (`where T : struct` makes `T?` a Nullable<T>) and distinguish overloads that differ only by constraint. - Default interface members and static interface members: normalize away virtual/abstract/override/sealed for interface members (a bodyless .cssig cannot express default-implementation-ness) and re-emit `static`, which SymbolDisplay strips on interface members. - Type-parameter nullability: collapse oblivious to not-annotated for bare type-parameter references, reconciling the lexical self-reference seen on the project side with the rebound reference the writer emits. Bumps the package version to 0.3.0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ivate members Drop the private-constructor stub. Implicit public/protected parameterless constructors are emitted explicitly as () primary-constructor syntax, and the analyzer ignores synthesized parameterless constructors on the .cssig side so a type with only an inaccessible ctor declares none. No private members appear in .cssig. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…SIGN.md The .cssig grammar now rejects private, bare internal, and private protected on any member, accessor, or type (CSSIG004); only public/protected/protected internal are expressible. Trim the analyzer README to usage essentials and move internals to DESIGN.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
# Conflicts: # src/CsSig/Analyzer/ApiSurface.cs # src/CsSig/Analyzer/CsSigWriter.cs # src/CsSig/Analyzer/IsExternalInit.cs # src/CsSig/Analyzer/SignatureModel.cs # src/CsSig/CodeFixes/StaticCs.CsSig.CodeFixes.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #32. Fixes several cases where the
.cssigwriter and the analyzer disagreed about the public API surface, found by running the analyzer over the realserdeproject (which now builds clean against the updated analyzer).Fixes
privatestub for records/classes whose only declared constructors are inaccessible (e.g. an abstract record with an explicitprivateparameterless ctor), suppressing the parameterless constructor the compiler would otherwise synthesize from the body-less form.whereclauses on types and methods. Constraints change member semantics (where T : structmakesT?aNullable<T>) and distinguish overloads differing only by constraint..cssigcannot express default-implementation-ness) and re-emitstatic, whichSymbolDisplaystrips on interface members.Bumps the package version to 0.3.0.
Tests
Adds round-trip tests:
RoundTripPositionalRecords,RoundTripPrivateConstructorClass,RoundTripDefaultInterfaceMethods,RoundTripGenericConstraints. Full suite: 98 passing, 1 skipped.