Skip to content

feat(generator): 添加对 [GetAll] 特性的静态和只读字段跳过支持#151

Merged
GeWuYou merged 4 commits into
mainfrom
feat/generator-skip-static-readonly-fields
Mar 30, 2026
Merged

feat(generator): 添加对 [GetAll] 特性的静态和只读字段跳过支持#151
GeWuYou merged 4 commits into
mainfrom
feat/generator-skip-static-readonly-fields

Conversation

@GeWuYou
Copy link
Copy Markdown
Owner

@GeWuYou GeWuYou commented Mar 30, 2026

  • 添加了新的诊断规则 GF_ContextGet_007 和 GF_ContextGet_08
  • 实现了对静态字段和只读字段的跳过逻辑
  • 为 [GetAll] 特性添加了跳过字段的警告提示
  • 更新了测试用例验证跳过逻辑的正确性
  • 修改了代码生成顺序以确保正确的绑定推断
  • 在 README 中添加了关于字段跳过的文档说明

由 Sourcery 提供的摘要

为 [GetAll] 上下文注入添加对跳过不可赋值字段的支持,并提供相应的诊断信息和文档。

新功能:

  • 引入诊断信息,用于在 [GetAll] 在上下文注入期间跳过静态或 readonly 推断字段时发出警告。

改进:

  • 调整推断绑定逻辑,使 [GetAll] 只对本来会被绑定的字段发出警告。
  • 通过共享的 SourceGeneratorsPath 常量集中管理源生成器诊断类别,并更新全局 using。

文档:

  • 记录 [GetAll] 会跳过 const、static 和 readonly 字段,并在跳过推断绑定时可能发出警告。

测试:

  • 为 [GetAll] 类中被跳过的 const、static 和 readonly 字段添加生成器测试,并为显式 static/readonly 的 GetModel 字段添加诊断测试。
Original summary in English

Summary by Sourcery

Add support for skipping non-assignable fields in [GetAll] context injection and surface corresponding diagnostics and documentation.

New Features:

  • Introduce diagnostics to warn when [GetAll] skips static or readonly inferred fields during context injection.

Enhancements:

  • Adjust inferred binding logic so [GetAll] only warns for fields that would otherwise be bound.
  • Centralize the source generator diagnostics category using a shared SourceGeneratorsPath constant and update global usings.

Documentation:

  • Document that [GetAll] skips const, static and readonly fields and may warn when inferred bindings are skipped.

Tests:

  • Add generator tests covering skipped const, static and readonly fields for [GetAll] classes and diagnostics for explicit static/readonly GetModel fields.

GeWuYou added 2 commits March 30, 2026 08:40
- 添加了新的诊断规则 GF_ContextGet_007 和 GF_ContextGet_08
- 实现了对静态字段和只读字段的跳过逻辑
- 为 [GetAll] 特性添加了跳过字段的警告提示
- 更新了测试用例验证跳过逻辑的正确性
- 修改了代码生成顺序以确保正确的绑定推断
- 在 README 中添加了关于字段跳过的文档说明
- 将GFramework源代码生成器抽象层命名空间注释更正为GFramework源代码生成器根命名空间
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Mar 30, 2026

Reviewer's Guide

在 ContextGet 源生成器中实现了 [GetAll] 支持,用于跳过 static 和 readonly 字段;为这些跳过场景引入了专门的诊断信息;通过共享常量统一诊断类别命名,并扩展了测试和文档以覆盖新行为。

更新后的 ContextGet 诊断与生成器绑定逻辑类图

classDiagram
    class PathContests {
        <<static>>
        +string BaseNamespace
        +string SourceGeneratorsPath
        +string GameNamespace
    }

    class ContextGetDiagnostics {
        <<static>>
        -string SourceGeneratorsRuleCategory
        +DiagnosticDescriptor NestedClassNotSupported
        +DiagnosticDescriptor StaticFieldNotSupported
        +DiagnosticDescriptor ReadOnlyFieldNotSupported
        +DiagnosticDescriptor GetAllStaticFieldSkipped
        +DiagnosticDescriptor GetAllReadOnlyFieldSkipped
        +DiagnosticDescriptor FieldTypeNotValid
        +DiagnosticDescriptor ContextAwareTypeRequired
        +DiagnosticDescriptor MultipleContextGetAttributesNotSupported
    }

    class ContextGetGenerator {
        <<static>>
        -void AddInferredBindings(SourceProductionContext context, InferredSymbols symbols, ImmutableArray~IFieldSymbol~ fields, ImmutableArray~IFieldSymbol~ explicitFields, List~ContextBinding~ bindings)
        -bool TryCreateInferredBinding(IFieldSymbol field, InferredSymbols symbols, out ContextBinding binding)
        -bool CanApplyInferredBinding(SourceProductionContext context, IFieldSymbol field)
        -void ReportFieldDiagnostic(SourceProductionContext context, DiagnosticDescriptor descriptor, IFieldSymbol field)
    }

    PathContests <.. ContextGetDiagnostics : uses
    ContextGetDiagnostics <.. ContextGetGenerator : uses
Loading

[GetAll] 推断绑定与跳过诊断的流程图

flowchart TD
    A[Start AddInferredBindings] --> B[Iterate each field]
    B --> C{Field in explicitFields?}
    C -- Yes --> B
    C -- No --> D[TryCreateInferredBinding]
    D --> E{TryCreateInferredBinding success?}
    E -- No --> B
    E -- Yes --> F[CanApplyInferredBinding]

    F --> G{field.IsStatic?}
    G -- Yes --> H[Report GF_ContextGet_007 via GetAllStaticFieldSkipped]
    H --> B
    G -- No --> I{field.IsReadOnly?}
    I -- Yes --> J[Report GF_ContextGet_008 via GetAllReadOnlyFieldSkipped]
    J --> B
    I -- No --> K[Add binding to bindings]
    K --> B

    B --> L{More fields?}
    L -- Yes --> B
    L -- No --> M[End AddInferredBindings]
Loading

File-Level Changes

Change Details Files
Add skip-and-warn behavior for static/readonly inferred fields when using [GetAll] in ContextGetGenerator.
  • 重构推断绑定流程,改为先创建推断绑定,再检查是否可以应用,这样只有在字段原本会被绑定时,才会在 [GetAll] 情况下发出警告。
  • 将辅助方法从 CanInferBinding 重命名并调整为 CanApplyInferredBinding,使其关注“可应用性”而非“类型推断”。
  • 当字段为 static 时,报告 GetAllStaticFieldSkipped (GF_ContextGet_007) 警告,而不是致命的 StaticFieldNotSupported 诊断,并跳过绑定生成。
  • 当字段为 readonly 时,报告 GetAllReadOnlyFieldSkipped (GF_ContextGet_008) 警告,而不是致命的 ReadOnlyFieldNotSupported 诊断,并跳过绑定生成。
GFramework.SourceGenerators/Rule/ContextGetGenerator.cs
Introduce new diagnostics and shared category constant for ContextGet rules.
  • 在 PathContests 中添加 SourceGeneratorsPath 常量,用于表示 GFramework.SourceGenerators 根命名空间。
  • 使用 SourceGeneratorsPath 定义 SourceGeneratorsRuleCategory,并用该常量替换 ContextGetDiagnostics 中硬编码的诊断类别。
  • 定义两个新的 DiagnosticDescriptor 实例:GetAllStaticFieldSkipped (GF_ContextGet_007) 和 GetAllReadOnlyFieldSkipped (GF_ContextGet_008),严重级别为警告,并使用消息解释在 [GetAll] 下的跳过行为。
GFramework.SourceGenerators.Common/Constants/PathContests.cs
GFramework.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs
Extend tests to validate new skip/warning behavior and keep explicit [GetModel] diagnostics unchanged.
  • 添加测试,确保在 [GetAll] 下,当 const 字段无法被推断为绑定时,会被忽略且不会产生诊断。
  • 添加测试,确保在 [GetAll] 下,readonly 和 static 推断字段会被跳过,生成的代码仅包含可赋值字段,并且 GF_ContextGet_007 / GF_ContextGet_008 警告会以正确的代码范围和参数被报告。
  • 添加测试,确认显式标注 [GetModel] 的 readonly 或 static 字段仍然会产生现有的错误诊断 GF_ContextGet_003 和 GF_ContextGet_002。
GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs
Update global usings and analyzer metadata to support new behavior.
  • 在源生成器项目中,将 System.Collections.Immutable、Microsoft.CodeAnalysis.CSharp.Syntax 和 Microsoft.CodeAnalysis.CSharp 提升为全局 using。
  • 在 AnalyzerReleases.Unshipped.md 中,以 ContextGetDiagnostics 分析器 ID 将新的诊断 GF_ContextGet_007 和 GF_ContextGet_008 注册为警告。
GFramework.SourceGenerators/GlobalUsings.cs
GFramework.SourceGenerators/AnalyzerReleases.Unshipped.md
Document [GetAll] skipping behavior for const/static/readonly fields.
  • 扩展 README,澄清 [GetAll] 会跳过 const、static 和 readonly 字段,并说明当某个字段原本会被推断为 Model/System/Utility 绑定,但因不可赋值而被跳过时,会发出警告。
GFramework.SourceGenerators/README.md

Tips and commands

Interacting with Sourcery

  • 触发新评审: 在 pull request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的评审评论。
  • 从评审评论生成 GitHub issue: 通过回复评审评论来让 Sourcery 基于该评论创建 issue。你也可以在评审评论下回复 @sourcery-ai issue 来从该评论创建 issue。
  • 生成 pull request 标题: 在 pull request 标题中任意位置写上 @sourcery-ai,即可随时生成标题。你也可以在 pull request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 pull request 摘要: 在 pull request 正文中任意位置写上 @sourcery-ai summary,即可在你想要的位置生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary 来(重新)生成摘要。
  • 生成评审者指南: 在 pull request 中评论 @sourcery-ai guide,即可随时(重新)生成评审者指南。
  • 一次性解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve,即可解决所有 Sourcery 评论。如果你已经处理了所有评论,又不想再看到它们,这非常有用。
  • 一次性关闭所有 Sourcery 评审: 在 pull request 中评论 @sourcery-ai dismiss,即可关闭所有现有的 Sourcery 评审。特别适合你希望从头开始新一轮评审的情况——别忘了再评论 @sourcery-ai review 触发新的评审!

Customizing Your Experience

打开你的 dashboard 以:

  • 启用或禁用评审功能,例如 Sourcery 自动生成的 pull request 摘要、评审者指南等。
  • 更改评审语言。
  • 添加、移除或编辑自定义评审指令。
  • 调整其他评审设置。

Getting Help

Original review guide in English

Reviewer's Guide

Implements [GetAll] support for skipping static and readonly fields in the ContextGet source generator, introduces dedicated diagnostics for these skip cases, aligns diagnostic category naming via a shared constant, and expands tests and documentation to cover the new behavior.

Class diagram for updated ContextGet diagnostics and generator binding logic

classDiagram
    class PathContests {
        <<static>>
        +string BaseNamespace
        +string SourceGeneratorsPath
        +string GameNamespace
    }

    class ContextGetDiagnostics {
        <<static>>
        -string SourceGeneratorsRuleCategory
        +DiagnosticDescriptor NestedClassNotSupported
        +DiagnosticDescriptor StaticFieldNotSupported
        +DiagnosticDescriptor ReadOnlyFieldNotSupported
        +DiagnosticDescriptor GetAllStaticFieldSkipped
        +DiagnosticDescriptor GetAllReadOnlyFieldSkipped
        +DiagnosticDescriptor FieldTypeNotValid
        +DiagnosticDescriptor ContextAwareTypeRequired
        +DiagnosticDescriptor MultipleContextGetAttributesNotSupported
    }

    class ContextGetGenerator {
        <<static>>
        -void AddInferredBindings(SourceProductionContext context, InferredSymbols symbols, ImmutableArray~IFieldSymbol~ fields, ImmutableArray~IFieldSymbol~ explicitFields, List~ContextBinding~ bindings)
        -bool TryCreateInferredBinding(IFieldSymbol field, InferredSymbols symbols, out ContextBinding binding)
        -bool CanApplyInferredBinding(SourceProductionContext context, IFieldSymbol field)
        -void ReportFieldDiagnostic(SourceProductionContext context, DiagnosticDescriptor descriptor, IFieldSymbol field)
    }

    PathContests <.. ContextGetDiagnostics : uses
    ContextGetDiagnostics <.. ContextGetGenerator : uses
Loading

Flow diagram for [GetAll] inferred binding and skip diagnostics

flowchart TD
    A[Start AddInferredBindings] --> B[Iterate each field]
    B --> C{Field in explicitFields?}
    C -- Yes --> B
    C -- No --> D[TryCreateInferredBinding]
    D --> E{TryCreateInferredBinding success?}
    E -- No --> B
    E -- Yes --> F[CanApplyInferredBinding]

    F --> G{field.IsStatic?}
    G -- Yes --> H[Report GF_ContextGet_007 via GetAllStaticFieldSkipped]
    H --> B
    G -- No --> I{field.IsReadOnly?}
    I -- Yes --> J[Report GF_ContextGet_008 via GetAllReadOnlyFieldSkipped]
    J --> B
    I -- No --> K[Add binding to bindings]
    K --> B

    B --> L{More fields?}
    L -- Yes --> B
    L -- No --> M[End AddInferredBindings]
Loading

File-Level Changes

Change Details Files
Add skip-and-warn behavior for static/readonly inferred fields when using [GetAll] in ContextGetGenerator.
  • Refactor inferred binding flow to first create the inferred binding and only then check whether it can be applied so that [GetAll] warnings are only emitted for fields that would otherwise be bound.
  • Rename and adjust the helper from CanInferBinding to CanApplyInferredBinding to focus on applicability rather than type inference.
  • When a field is static, report GetAllStaticFieldSkipped (GF_ContextGet_007) instead of the fatal StaticFieldNotSupported diagnostic and skip binding generation.
  • When a field is readonly, report GetAllReadOnlyFieldSkipped (GF_ContextGet_008) instead of the fatal ReadOnlyFieldNotSupported diagnostic and skip binding generation.
GFramework.SourceGenerators/Rule/ContextGetGenerator.cs
Introduce new diagnostics and shared category constant for ContextGet rules.
  • Add SourceGeneratorsPath constant to PathContests to represent the GFramework.SourceGenerators root namespace.
  • Use SourceGeneratorsPath to define SourceGeneratorsRuleCategory and replace hard-coded diagnostic categories in ContextGetDiagnostics with this constant.
  • Define two new DiagnosticDescriptor instances: GetAllStaticFieldSkipped (GF_ContextGet_007) and GetAllReadOnlyFieldSkipped (GF_ContextGet_008) with warning severity and messages explaining skip behavior under [GetAll].
GFramework.SourceGenerators.Common/Constants/PathContests.cs
GFramework.SourceGenerators/Diagnostics/ContextGetDiagnostics.cs
Extend tests to validate new skip/warning behavior and keep explicit [GetModel] diagnostics unchanged.
  • Add tests to ensure const fields under [GetAll] are ignored without diagnostics when they cannot be inferred as bindings.
  • Add tests to ensure readonly and static inferred fields under [GetAll] are skipped, that generated code only includes assignable fields, and that GF_ContextGet_007 / GF_ContextGet_008 warnings are reported with correct spans and arguments.
  • Add tests to confirm explicit [GetModel] fields that are readonly or static still produce existing error diagnostics GF_ContextGet_003 and GF_ContextGet_002 respectively.
GFramework.SourceGenerators.Tests/Rule/ContextGetGeneratorTests.cs
Update global usings and analyzer metadata to support new behavior.
  • Promote System.Collections.Immutable, Microsoft.CodeAnalysis.CSharp.Syntax, and Microsoft.CodeAnalysis.CSharp to global usings in the source generators project.
  • Register the new diagnostics GF_ContextGet_007 and GF_ContextGet_008 as warnings in AnalyzerReleases.Unshipped.md with the ContextGetDiagnostics analyzer ID.
GFramework.SourceGenerators/GlobalUsings.cs
GFramework.SourceGenerators/AnalyzerReleases.Unshipped.md
Document [GetAll] skipping behavior for const/static/readonly fields.
  • Extend README to clarify that [GetAll] skips const, static, and readonly fields and that warnings are emitted when a field would otherwise be inferred as a Model/System/Utility binding but is skipped due to being non-assignable.
GFramework.SourceGenerators/README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepsource-io
Copy link
Copy Markdown

deepsource-io Bot commented Mar 30, 2026

DeepSource Code Review

We reviewed changes in 63cb6b5...9590bf1 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
C# Mar 30, 2026 1:23a.m. Review ↗
Secrets Mar 30, 2026 1:23a.m. Review ↗

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - 我在这里给出了一些高层次的反馈:

  • 分析器测试目前是通过硬编码的行/列范围来断言诊断结果(例如 .WithSpan(52, 42, 52, 48)),这种方式相当脆弱;建议改为在源字符串中使用标记(markup)来定位,这样当测试代码布局发生变化时,测试仍能保持稳定。
  • README 现在说明 [GetAll] 会跳过 const 字段,但生成器目前只对 static/readonly 字段做了显式处理和诊断;建议在生成器中也对 const 字段的行为进行显式处理,并添加一个专门的测试来覆盖本应可推断的 const 字段,以确保实际行为与文档描述相一致。
给 AI 代理的提示
Please address the comments from this code review:

## Overall Comments
- The analyzer tests that assert diagnostics via hard-coded line/column spans (e.g., `.WithSpan(52, 42, 52, 48)`) are quite brittle; consider switching to markup-based locations in the source strings so the tests remain stable if the test code layout changes.
- The README now documents that `[GetAll]` skips `const` fields, but the generator only has explicit handling and diagnostics for static/readonly fields; consider making the const-field behavior explicit in the generator and adding a focused test that covers a const field that would otherwise be inferable to ensure behavior matches the documentation.

Sourcery 对开源项目免费——如果你觉得我们的评审有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点击 👍 或 👎,我会根据你的反馈改进后续评审。
Original comment in English

Hey - I've left some high level feedback:

  • The analyzer tests that assert diagnostics via hard-coded line/column spans (e.g., .WithSpan(52, 42, 52, 48)) are quite brittle; consider switching to markup-based locations in the source strings so the tests remain stable if the test code layout changes.
  • The README now documents that [GetAll] skips const fields, but the generator only has explicit handling and diagnostics for static/readonly fields; consider making the const-field behavior explicit in the generator and adding a focused test that covers a const field that would otherwise be inferable to ensure behavior matches the documentation.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The analyzer tests that assert diagnostics via hard-coded line/column spans (e.g., `.WithSpan(52, 42, 52, 48)`) are quite brittle; consider switching to markup-based locations in the source strings so the tests remain stable if the test code layout changes.
- The README now documents that `[GetAll]` skips `const` fields, but the generator only has explicit handling and diagnostics for static/readonly fields; consider making the const-field behavior explicit in the generator and adding a focused test that covers a const field that would otherwise be inferable to ensure behavior matches the documentation.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

GeWuYou added 2 commits March 30, 2026 09:13
- 在 ContextGetGenerator 中添加对 const 字段的显式检查和跳过逻辑
- 更新文档说明 const、static 和 readonly 字段的处理方式
- 重构测试代码使用 MarkupTestSource 解析器进行更精确的诊断测试
- 添加新的 MarkupTestSource 类用于源码标记解析和诊断定位
- 在 ContextGetGenerator 中添加 System.Text 和 Extensions 引入
- 在测试文件中添加 Microsoft.CodeAnalysis.Text 引入
@GeWuYou GeWuYou merged commit a628ade into main Mar 30, 2026
9 checks passed
@GeWuYou GeWuYou deleted the feat/generator-skip-static-readonly-fields branch March 30, 2026 01:27
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.

1 participant