Skip to content

Fix cross-assembly source generation accessibility - #11014

Open
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/source-generator-review
Open

Fix cross-assembly source generation accessibility#11014
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/source-generator-review

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

  • make reflection-free member accessibility checks account for the declaring assembly
  • prevent inaccessible nearer members from exposing hidden ancestor members during model construction
  • add two-assembly regression coverage for inherited methods and properties

Testing

  • build.cmd -test -projects test\UnitTests\MSTest.SourceGeneration.UnitTests\MSTest.SourceGeneration.UnitTests.csproj -bl

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0f79d9b9-3240-40e6-bc8e-ed8bfc4cfb2e
Copilot AI balanced review requested due to automatic review settings September 3, 2026 14:04
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

🧵 Parallel-safety audit — PR #11014

Nothing audited here touches process-global state, shared filesystem paths, or
[ResourceLock] / [DoNotParallelize] declarations. The changed test method
(Generator_ExcludesInaccessibleMembersFromBaseTypeInAnotherAssembly) only builds
in-memory CSharpCompilation/GeneratorDriver objects, writes to a local
MemoryStream, and asserts on generated source text — no env vars, CWD, console
state, statics, or shared paths are involved. The two other changed files
(TestClassModelBuilder.cs, TestMemberValidationHelper.cs) are pure analyzer/
source-generator logic with no test-time side effects. The [assembly: Parallelize(...)]
occurrences elsewhere in this file are inside raw source-code strings used as
generator input for other, unrelated tests — not real attributes on the test
assembly — so they do not change this project's parallelization state.

MSTest.SourceGeneration.UnitTests carries no [assembly: Parallelize] /
[assembly: DoNotParallelize], no .runsettings, and no testconfig.json, so
its effective scope is MSTest's default: off. Nothing to flag for
parallel-safety.

Audited MSTest.SourceGeneration.UnitTests at scope off, workers n/a.

Re-run with /parallel-audit.

🤖 Automated content by GitHub Copilot. Generated by the Parallel-safety audit on PR (on open / sync) workflow. · auto · 40.9 AIC · ⌖ 4.42 AIC · ⊞ 24.8K · [◷]( · )

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

🧪 Expert test review — PR #11014

GradeTestMutationNotesHow to improve
A (90–100) new MSTestReflectionMetadataGeneratorTests.
Generator_
ExcludesInaccessibleMembersFromBaseTypeInAnotherAssembly
4/4 killed Covers the derived-first dedup regression: an inaccessible derived-type member correctly shadows and excludes an otherwise-accessible grandparent member, plus verifies the inaccessible-getter diagnostic and absence of compile errors.

This advisory comment was generated automatically. Grades are heuristic
and informational — they do not block merging. Suggestions on the Files
changed tab can be applied with one click. Re-run with
/review-tests.

🤖 Automated content by GitHub Copilot. Generated by the Test Reviewer on PR (on open / sync) workflow. · auto · 43.1 AIC · ⌖ 2.47 AIC · ⊞ 16.9K · [◷]( · )

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

✅ 22/22 dimensions clean — no findings.

Review notes:

  • Algorithmic Correctness: Moving the dedup check (seenMethodKeys.Add) before the accessibility check is correct — derived-first iteration means the derived declaration wins for new-shadowed members. The hasUnsupportedTestMethod flag is still set on the first (derived) occurrence when applicable. For properties, the flag is set unconditionally before dedup/accessibility, so no regression there either.
  • The core fix (IsAccessibleFromConsumer now taking consumingAssembly) correctly addresses the bug where Internal and ProtectedOrInternal members from external assemblies were incorrectly treated as accessible. The delegation to SymbolReferenceabilityHelper.IsMemberAccessibleFrom is consistent with how DynamicDataSourceBuilder and AttributeMaterializationHelper already handle this.
  • HasGettableValue now uses the same assembly-aware check via IsMemberAccessibleFrom(getter.DeclaredAccessibility, getter.ContainingType, consumingAssembly), replacing the hardcoded accessibility enum check — consistent and correct.
  • Dictionary→HashSet refactor reduces memory by not storing values that were never read back, while preserving the same dedup semantics.
  • Test coverage: The new Generator_ExcludesInaccessibleMembersFromBaseTypeInAnotherAssembly test exercises the cross-assembly scenario with multi-level inheritance, new-shadowing, protected internal inaccessibility, and inaccessible getters — good coverage of the fix.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Two critical hiding defects remain, and cross-assembly internal coverage is incomplete.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 2 High severity · 1 Medium severity

New issues introduced by this change (3)
Severity Finding
High severity src/​Analyzers/​MSTest.SourceGeneration/​Generators/​TestClassModelBuilder.cs — These kind-specific sets still miss cross-kind hiding. C# member lookup hides base members by name…
High severity src/​Analyzers/​MSTest.SourceGeneration/​Generators/​TestClassModelBuilder.csBuildMethodSignatureKey distinguishes static and instance methods, but staticness is not part of…
Medium severity src/​Analyzers/​MSTest.SourceGeneration/​Generators/​TestMemberValidationHelper.cs — The assembly-sensitive predicate now covers both Internal and ProtectedOrInternal, but the…
What changed in this PR

Updates source generation to account for cross-assembly accessibility and inherited-member hiding.

Changes:

  • Adds assembly-aware accessibility checks.
  • Revises inherited-member filtering.
  • Adds two-assembly regression coverage.
File Review
test/​UnitTests/​MSTest.SourceGeneration.UnitTests/​MSTestReflectionMetadataGeneratorTests.cs Adds cross-assembly tests, but lacks direct internal member coverage.
src/​Analyzers/​MSTest.SourceGeneration/​Generators/​TestMemberValidationHelper.cs Adds assembly-sensitive checks. Moderate: add cross-assembly internal method, property, and getter regressions.
src/​Analyzers/​MSTest.SourceGeneration/​Generators/​TestClassModelBuilder.cs Critical: method hiding incorrectly distinguishes staticness and does not account for cross-kind hiding, potentially generating uncompilable code.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +47 to +48
var seenMethodKeys = new HashSet<string>(StringComparer.Ordinal);
var seenPropertyNames = new HashSet<string>(StringComparer.Ordinal);
Comment on lines +86 to +87
string key = TestMemberValidationHelper.BuildMethodSignatureKey(method);
if (!seenMethodKeys.Add(key))
Comment on lines +24 to +28
internal static bool IsAccessibleFromConsumer(ISymbol symbol, IAssemblySymbol consumingAssembly)
=> SymbolReferenceabilityHelper.IsMemberAccessibleFrom(
symbol.DeclaredAccessibility,
symbol.ContainingAssembly,
consumingAssembly);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants