GFramework/docs/zh-CN/contributing.md
GeWuYou 3130a3bab2 feat(docs): 添加开发环境能力清单及相关工具脚本
- 在贡献指南中添加开发环境能力清单链接和说明
- 创建详细的开发环境能力清单文档,记录项目所需的运行时和工具
- 添加 .ai/environment/tools.ai.yaml 文件,为 AI 提供精简的环境能力信息
- 添加 .ai/environment/tools.raw.yaml 文件,存储完整的环境检测数据
- 创建 collect-dev-environment.sh 脚本,用于收集和输出环境信息
- 创建 generate-ai-environment.py 脚本,从原始数据生成 AI 友好的环境清单
- 在 .gitignore 中添加 .venv/ 工具目录忽略规则
2026-03-21 12:37:56 +08:00

844 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 贡献指南
欢迎为 GFramework 贡献代码!本指南将帮助你了解如何参与项目开发。
## 概述
GFramework 是一个开源的游戏开发框架,我们欢迎所有形式的贡献:
- 报告 Bug 和提出功能建议
- 提交代码修复和新功能
- 改进文档和示例
- 参与讨论和代码审查
## 行为准则
### 社区规范
我们致力于为所有贡献者提供友好、安全和包容的环境。参与本项目时,请遵守以下准则:
- **尊重他人**:尊重不同的观点和经验
- **建设性沟通**:提供有建设性的反馈,避免人身攻击
- **协作精神**:帮助新贡献者融入社区
- **专业态度**:保持专业和礼貌的交流方式
### 不可接受的行为
- 使用性别化语言或图像
- 人身攻击或侮辱性评论
- 骚扰行为(公开或私下)
- 未经许可发布他人的私人信息
- 其他不道德或不专业的行为
## 如何贡献
### 报告问题
发现 Bug 或有功能建议时,请通过 GitHub Issues 提交:
1. **搜索现有 Issue**:避免重复提交
2. **使用清晰的标题**:简洁描述问题
3. **提供详细信息**
- Bug 报告:复现步骤、预期行为、实际行为、环境信息
- 功能建议:使用场景、预期效果、可能的实现方案
**Bug 报告模板**
```markdown
**描述**
简要描述 Bug
**复现步骤**
1. 执行操作 A
2. 执行操作 B
3. 观察到错误
**预期行为**
应该发生什么
**实际行为**
实际发生了什么
**环境信息**
- GFramework 版本:
- .NET 版本:
- 操作系统:
- Godot 版本(如适用):
**附加信息**
日志、截图等
```
### 提交 Pull Request
#### 基本流程
1. **Fork 仓库**:在 GitHub 上 Fork 本项目
2. **克隆到本地**
```bash
git clone https://github.com/your-username/GFramework.git
cd GFramework
```
3. **创建特性分支**
```bash
git checkout -b feature/your-feature-name
# 或
git checkout -b fix/your-bug-fix
```
4. **进行开发**:编写代码、添加测试、更新文档
5. **提交更改**:遵循提交规范(见下文)
6. **推送分支**
```bash
git push origin feature/your-feature-name
```
7. **创建 PR**:在 GitHub 上创建 Pull Request
#### PR 要求
- **清晰的标题**:简洁描述变更内容
- **详细的描述**
- 变更的背景和动机
- 实现方案说明
- 测试验证结果
- 相关 Issue 链接(如有)
- **代码质量**:通过所有 CI 检查
- **测试覆盖**:为新功能添加测试
- **文档更新**:更新相关文档
### 改进文档
文档改进同样重要:
- **修正错误**:拼写、语法、技术错误
- **补充示例**:添加代码示例和使用场景
- **完善说明**:改进不清晰的描述
- **翻译工作**:帮助翻译文档(如需要)
文档位于 `docs/` 目录,使用 Markdown 格式编写。
## 开发环境设置
当前推荐的项目相关环境、CLI 与 AI 可用工具清单请查看:
- [开发环境能力清单](./contributor/development-environment.md)
### 前置要求
- **.NET SDK**8.0、9.0 或 10.0
- **Git**:版本控制工具
- **IDE**(推荐):
- Visual Studio 2022+
- JetBrains Rider
- Visual Studio Code + C# Dev Kit
### 克隆仓库
```bash
# 克隆你 Fork 的仓库
git clone https://github.com/your-username/GFramework.git
cd GFramework
# 添加上游仓库
git remote add upstream https://github.com/GeWuYou/GFramework.git
```
### 安装依赖
```bash
# 恢复 NuGet 包
dotnet restore
# 恢复 .NET 本地工具
dotnet tool restore
```
### 构建项目
```bash
# 构建所有项目
dotnet build
# 构建特定配置
dotnet build -c Release
```
### 运行测试
```bash
# 运行所有测试
dotnet test
# 运行特定测试项目
dotnet test GFramework.Core.Tests
dotnet test GFramework.SourceGenerators.Tests
# 生成测试覆盖率报告
dotnet test --collect:"XPlat Code Coverage"
```
### 验证代码质量
项目使用 MegaLinter 进行代码质量检查:
```bash
# 本地运行 MegaLinter需要 Docker
docker run --rm -v $(pwd):/tmp/lint oxsecurity/megalinter:v9
# 或使用 CI 流程验证
git push origin your-branch
```
## 代码规范
### 命名规范
遵循 C# 标准命名约定:
- **类、接口、方法**PascalCase
```csharp
public class PlayerController { }
public interface IEventBus { }
public void ProcessInput() { }
```
- **私有字段**_camelCase下划线前缀
```csharp
private int _health;
private readonly ILogger _logger;
```
- **参数、局部变量**camelCase
```csharp
public void SetHealth(int newHealth)
{
var oldHealth = _health;
_health = newHealth;
}
```
- **常量**PascalCase
```csharp
public const int MaxPlayers = 4;
private const string DefaultName = "Player";
```
- **接口**I 前缀
```csharp
public interface IArchitecture { }
public interface ICommand<TInput> { }
```
### 代码风格
- **缩进**4 个空格(不使用 Tab
- **大括号**Allman 风格(独占一行)
```csharp
if (condition)
{
DoSomething();
}
```
- **using 指令**:文件顶部,按字母顺序排列
```csharp
using System;
using System.Collections.Generic;
using GFramework.Core.Abstractions;
```
- **空行**
- 命名空间后空一行
- 类成员之间空一行
- 逻辑块之间适当空行
- **行长度**:建议不超过 120 字符
### 注释规范
#### XML 文档注释
所有公共 API 必须包含 XML 文档注释:
```csharp
/// <summary>
/// 架构基类,提供系统、模型、工具等组件的注册与管理功能。
/// </summary>
/// <typeparam name="TModel">模型类型</typeparam>
/// <param name="configuration">架构配置</param>
/// <returns>注册的模型实例</returns>
/// <exception cref="ArgumentNullException">当 model 为 null 时抛出</exception>
public TModel RegisterModel<TModel>(TModel model) where TModel : IModel
{
// 实现代码
}
```
#### 代码注释
- **何时添加注释**
- 复杂的算法逻辑
- 非显而易见的设计决策
- 临时解决方案(使用 TODO 或 HACK 标记)
- 性能关键代码的优化说明
- **注释风格**
```csharp
// 单行注释使用双斜杠
// 多行注释可以使用多个单行注释
// 每行都以双斜杠开始
/* 或使用块注释
* 适用于较长的说明
*/
```
- **避免无用注释**
```csharp
// 不好:注释重复代码内容
// 设置健康值为 100
health = 100;
// 好:解释为什么这样做
// 初始化时设置满血,避免首次战斗时的边界情况
health = MaxHealth;
```
### 设计原则
- **SOLID 原则**:遵循面向对象设计原则
- **依赖注入**:优先使用构造函数注入
- **接口隔离**:定义小而专注的接口
- **不可变性**:优先使用 `readonly` 和不可变类型
- **异步编程**I/O 操作使用 `async`/`await`
## 提交规范
### Commit 消息格式
使用 Conventional Commits 规范:
```
<type>(<scope>): <subject>
<body>
<footer>
```
#### Type类型
- **feat**:新功能
- **fix**Bug 修复
- **docs**:文档更新
- **style**:代码格式调整(不影响功能)
- **refactor**:重构(不是新功能也不是修复)
- **perf**:性能优化
- **test**:添加或修改测试
- **chore**:构建过程或辅助工具的变动
- **ci**CI 配置文件和脚本的变动
#### Scope范围
指明变更影响的模块:
- `core`GFramework.Core
- `game`GFramework.Game
- `godot`GFramework.Godot
- `generators`:源码生成器
- `docs`:文档
- `tests`:测试
#### Subject主题
- 使用祈使句,现在时态:"add" 而不是 "added" 或 "adds"
- 首字母小写
- 结尾不加句号
- 限制在 50 字符以内
#### Body正文
- 详细描述变更的动机和实现细节
- 与主题空一行
- 每行不超过 72 字符
#### Footer页脚
- 关联 Issue`Closes #123`
- 破坏性变更:`BREAKING CHANGE: 描述`
#### 示例
```bash
# 简单提交
git commit -m "feat(core): add event priority support"
# 详细提交
git commit -m "fix(godot): resolve scene loading race condition
修复了在快速切换场景时可能出现的资源加载竞态条件。
通过引入场景加载锁机制,确保同一时间只有一个场景在加载。
Closes #456"
# 破坏性变更
git commit -m "refactor(core): change IArchitecture interface
BREAKING CHANGE: IArchitecture.Init() 现在返回 Task 而不是 void。
所有继承 Architecture 的类需要更新为异步初始化。
Migration guide: 将 Init() 改为 async Task Init()
"
```
### 分支策略
- **main**:主分支,保持稳定
- **feature/***:新功能分支
- `feature/event-priority`
- `feature/godot-ui-system`
- **fix/***Bug 修复分支
- `fix/memory-leak`
- `fix/null-reference`
- **docs/***:文档更新分支
- `docs/api-reference`
- `docs/tutorial-update`
- **refactor/***:重构分支
- `refactor/logging-system`
#### 分支命名规范
- 使用小写字母和连字符
- 简洁描述分支目的
- 避免使用个人名称
## 测试要求
### 单元测试
所有新功能和 Bug 修复都应包含单元测试:
```csharp
using Xunit;
namespace GFramework.Core.Tests.Events;
public class EventBusTests
{
[Fact]
public void Subscribe_ShouldReceiveEvent()
{
// Arrange
var eventBus = new EventBus();
var received = false;
// Act
eventBus.Subscribe&lt;TestEvent&gt;(e =&gt; received = true);
eventBus.Publish(new TestEvent());
// Assert
Assert.True(received);
}
[Theory]
[InlineData(1)]
[InlineData(10)]
[InlineData(100)]
public void Subscribe_MultipleEvents_ShouldReceiveAll(int count)
{
// 测试实现
}
}
```
### 测试组织
- **测试项目**`*.Tests` 后缀
- **测试类**`*Tests` 后缀,与被测试类对应
- **测试方法**`MethodName_Scenario_ExpectedResult` 格式
- **测试数据**:使用 `[Theory]` 和 `[InlineData]` 进行参数化测试
### 测试覆盖率
- **目标**:新代码覆盖率 &gt; 80%
- **关键路径**:核心功能覆盖率 &gt; 90%
- **边界情况**:测试异常情况和边界值
### 集成测试
对于涉及多个组件交互的功能,添加集成测试:
```csharp
public class ArchitectureIntegrationTests
{
[Fact]
public async Task Architecture_FullLifecycle_ShouldWork()
{
// Arrange
var architecture = new TestArchitecture();
// Act
await architecture.InitAsync();
var result = architecture.GetModel&lt;TestModel&gt;();
await architecture.DestroyAsync();
// Assert
Assert.NotNull(result);
}
}
```
### 性能测试
对性能敏感的代码,添加基准测试:
```csharp
using BenchmarkDotNet.Attributes;
[MemoryDiagnoser]
public class EventBusBenchmarks
{
private EventBus _eventBus;
[GlobalSetup]
public void Setup()
{
_eventBus = new EventBus();
}
[Benchmark]
public void Publish_1000Events()
{
for (int i = 0; i &lt; 1000; i++)
{
_eventBus.Publish(new TestEvent());
}
}
}
```
## 文档要求
### XML 注释
所有公共 API 必须包含完整的 XML 文档注释:
```csharp
/// &lt;summary&gt;
/// 事件总线接口,提供事件的发布和订阅功能。
/// &lt;/summary&gt;
/// &lt;remarks&gt;
/// 事件总线使用观察者模式实现,支持类型安全的事件分发。
/// 所有订阅都是弱引用,避免内存泄漏。
/// &lt;/remarks&gt;
public interface IEventBus
{
/// &lt;summary&gt;
/// 订阅指定类型的事件。
/// &lt;/summary&gt;
/// &lt;typeparam name="TEvent"&gt;事件类型&lt;/typeparam&gt;
/// &lt;param name="handler"&gt;事件处理器&lt;/param&gt;
/// &lt;returns&gt;取消订阅的句柄&lt;/returns&gt;
/// &lt;exception cref="ArgumentNullException"&gt;当 handler 为 null 时抛出&lt;/exception&gt;
/// &lt;example&gt;
/// &lt;code&gt;
/// var unregister = eventBus.Subscribe&amp;lt;PlayerDiedEvent&amp;gt;(e =&amp;gt;
/// {
/// Console.WriteLine($"Player {e.PlayerId} died");
/// });
///
/// // 取消订阅
/// unregister.Dispose();
/// &lt;/code&gt;
/// &lt;/example&gt;
IUnRegister Subscribe&lt;TEvent&gt;(Action&lt;TEvent&gt; handler) where TEvent : IEvent;
}
```
### Markdown 文档
#### 文档结构
```markdown
# 标题
简要介绍模块功能和用途。
## 核心概念
解释关键概念和术语。
## 快速开始
提供最简单的使用示例。
## 详细用法
### 功能 A
详细说明和代码示例。
### 功能 B
详细说明和代码示例。
## 最佳实践
推荐的使用模式和注意事项。
## 常见问题
FAQ 列表。
## 相关资源
链接到相关文档和示例。
```
#### 代码示例
- **完整性**:示例代码应该可以直接运行
- **注释**:关键步骤添加注释说明
- **格式化**:使用正确的语法高亮
```csharp
// 创建架构实例
var architecture = new GameArchitecture();
// 初始化架构
await architecture.InitAsync();
// 注册模型
var playerModel = architecture.GetModel&lt;PlayerModel&gt;();
// 发送命令
await architecture.SendCommandAsync(new AttackCommand
{
TargetId = enemyId
});
```
#### 图表
使用 Mermaid 或 ASCII 图表说明复杂概念:
```markdown
```mermaid
graph TD
A[Controller] --&gt; B[Command]
B --&gt; C[System]
C --&gt; D[Model]
```
```
## PR 流程
### 创建 PR
1. **确保分支最新**
```bash
git fetch upstream
git rebase upstream/main
```
2. **推送到 Fork**
```bash
git push origin feature/your-feature
```
3. **创建 PR**
- 在 GitHub 上点击 "New Pull Request"
- 选择 base: `main` ← compare: `your-branch`
- 填写 PR 模板
### PR 模板
```markdown
## 变更说明
简要描述本 PR 的变更内容。
## 变更类型
- [ ] Bug 修复
- [ ] 新功能
- [ ] 破坏性变更
- [ ] 文档更新
- [ ] 性能优化
- [ ] 代码重构
## 相关 Issue
Closes #123
## 测试
描述如何测试这些变更:
- [ ] 添加了单元测试
- [ ] 添加了集成测试
- [ ] 手动测试通过
## 检查清单
- [ ] 代码遵循项目规范
- [ ] 添加了必要的注释
- [ ] 更新了相关文档
- [ ] 所有测试通过
- [ ] 没有引入新的警告
## 截图(如适用)
添加截图或 GIF 展示变更效果。
## 附加说明
其他需要说明的内容。
```
### 代码审查
PR 提交后,维护者会进行代码审查:
- **响应反馈**:及时回复审查意见
- **修改代码**:根据建议进行调整
- **讨论方案**:对有争议的地方进行讨论
- **保持耐心**:审查可能需要时间
#### 审查关注点
- **功能正确性**:代码是否实现了预期功能
- **代码质量**:是否遵循项目规范
- **测试覆盖**:是否有足够的测试
- **性能影响**:是否有性能问题
- **向后兼容**:是否破坏现有 API
### 合并流程
1. **通过 CI 检查**:所有自动化测试通过
2. **代码审查通过**:至少一位维护者批准
3. **解决冲突**:如有冲突需先解决
4. **合并方式**
- 功能分支Squash and merge
- 修复分支Merge commit
- 文档更新Squash and merge
## 常见问题
### 如何同步上游更新?
```bash
# 获取上游更新
git fetch upstream
# 合并到本地 main
git checkout main
git merge upstream/main
# 更新你的 Fork
git push origin main
# 更新特性分支
git checkout feature/your-feature
git rebase main
```
### 如何解决合并冲突?
```bash
# 拉取最新代码
git fetch upstream
git rebase upstream/main
# 如果有冲突,手动解决后
git add .
git rebase --continue
# 强制推送(因为 rebase 改变了历史)
git push origin feature/your-feature --force-with-lease
```
### 提交了错误的代码怎么办?
```bash
# 修改最后一次提交
git add .
git commit --amend
# 或者撤销最后一次提交
git reset --soft HEAD~1
# 修改后重新提交
git add .
git commit -m "fix: correct implementation"
```
### 如何运行特定的测试?
```bash
# 运行单个测试类
dotnet test --filter "FullyQualifiedName~EventBusTests"
# 运行单个测试方法
dotnet test --filter "FullyQualifiedName~EventBusTests.Subscribe_ShouldReceiveEvent"
# 运行特定类别的测试
dotnet test --filter "Category=Integration"
```
### 如何生成文档?
```bash
# 安装 VitePress如果还没安装
cd docs
npm install
# 本地预览文档
npm run docs:dev
# 构建文档
npm run docs:build
```
### 代码审查需要多长时间?
- **简单修复**:通常 1-3 天
- **新功能**:可能需要 1-2 周
- **大型重构**:可能需要更长时间
请耐心等待,维护者会尽快审查。
### 我的 PR 被拒绝了怎么办?
不要气馁!被拒绝的原因可能是:
- 不符合项目方向
- 需要更多讨论
- 实现方式需要调整
你可以:
- 在 Issue 中讨论方案
- 根据反馈调整实现
- 寻求维护者的建议
### 如何成为维护者?
持续贡献高质量的代码和文档,积极参与社区讨论,帮助其他贡献者。维护者会邀请活跃且负责任的贡献者加入维护团队。
## 获取帮助
如果你在贡献过程中遇到问题:
- **GitHub Issues**:提问或报告问题
- **GitHub Discussions**:参与讨论
- **代码注释**:查看现有代码的注释和文档
## 致谢
感谢所有为 GFramework 做出贡献的开发者!你们的努力让这个项目变得更好。
## 许可证
通过向本项目提交代码,你同意你的贡献将在 Apache License 2.0 下发布。