Gopls:贡献
欢迎贡献!但是,开发进展迅速,我们的评审能力有限。因此,在提交 CL 之前,请务必:
-
如果尚不存在,请先为 bug 或功能请求**提交一个 issue**。这使我们能够识别重复的请求,或将特定问题合并到更普遍的问题中,并评估问题的优先级。
-
请通过在 issue 下评论,或者如果您能够,请将 issue 分配给自己,**认领它**。这有助于我们避免两个人处理同一个问题。
-
对于任何复杂度的 CL,请在 issue 跟踪器中**提出一个实现计划**。在陷入代码评审细节之前,先进行高层次的计划讨论会更有效率。
当您提交 CL 时,应包含:
- 一个**CL 描述**,总结更改,说明其必要性,从高层次进行解释,对比更明显或更简单的实现方式,并链接到相关的 issue。
- **测试**(集成测试或标记测试);
- 针对新功能或修改的功能的**文档**;以及
- 新功能或重要更改的**发布说明**。
在代码评审期间,请解决所有评审员的评论。有些评论会导致直接的代码更改;另一些则需要更复杂的响应。当评审员提问时,最好的回应通常不是直接回答,而是修改代码以避免提出问题,例如通过使代码自解释。如果您不同意某个评论,指出评审员的错误,或者提议在后续更改中解决某个评论(并在当前 CL 中留下 TODO 评论),都是可以的。但请不要在未采取行动的情况下忽略评论,这可能会导致评审员重复自己,或者导致严重问题被忽视。
更多详情,请参阅 Go 项目的贡献指南。
查找 issue
所有 gopls
issue 都贴有相应的标签(请参阅gopls
标签)。适合贡献者处理的 issue 会额外标记 help-wanted
标签。
在开始处理某个 issue 之前,请留下一条评论表示您认领了它。
入门
gopls
的大部分逻辑位于 golang.org/x/tools/gopls/internal
目录下。有关代码组织的概述,请参阅 design/implementation.md。
构建
要构建一个包含您更改的 gopls
版本
cd /path/to/tools/gopls
go install
为了确认您正在使用正确的 gopls
版本进行测试,请检查您的 gopls
版本是否如下所示:
$ gopls version
golang.org/x/tools/gopls master
golang.org/x/tools/gopls@(devel)
获取帮助
直接联系 gopls 团队的最佳方式是通过 gophers slack 上的 #gopls-dev 频道。请随时就您的贡献或一般的贡献问题提问。
错误处理
为了用户体验,只要可行,重要的逻辑错误就不会导致服务器崩溃,这一点很重要。
Go 程序的表示形式非常复杂。包元数据的导入图、已解析文件的语法树及其相关的类型信息共同构成了庞大的 API 表面积。即使输入有效,也有许多边缘情况需要考虑,当您考虑缺少导入、解析错误和类型错误时,这种情况会呈指数级增长。
当您的逻辑必须处理您认为“不可能发生”的错误时,您应该怎么做?
-
如果可能返回错误,请使用
bug.Errorf
函数将错误返回给用户,同时还将该 bug 记录在 gopls 的缓存中,以降低被忽略的可能性。 -
如果继续操作是安全的,您可以调用
bug.Reportf
来记录错误并照常继续。 -
如果无法继续,请调用
bug.Fatalf
来记录错误,然后使用log.Fatalf
停止程序。如果存在recover
处理程序可能挽救局面的情况,您也可以使用bug.Panicf
。 -
只有当您可以在本地证明错误是不可能的,才应该调用
log.Fatal
。如果错误可能因某些输入而发生,无论可能性多么小,您都应使用上述方法之一。此外,如果安全性的证明依赖于代码库中广泛分布的不变式,那么您应该改用bug.Panicf
。
另请注意,恐慌(panicking)比 log.Fatal
更可取,因为它允许 VS Code 的崩溃报告能够识别和捕获堆栈。
通过 bug.Errorf
及其类似函数报告的 bug 可以通过 gopls bug
命令检索,该命令会打开一个 GitHub Issue 模板,并填充每个 bug 的摘要及其频率。bug 的文本会被仔细地打印到 stdout,以避免与 GitHub 共享用户名和错误消息字符串(可能包含项目标识符)。用户被邀请在愿意的情况下分享。
测试
更改后运行测试的常用命令是:
gopls$ go test -short ./...
(-short
标志会跳过一些运行缓慢的测试。TryBot 生成器会在多种平台上运行完整的测试集。)
Gopls 测试混合了两种类型。
-
标记测试将每个测试场景表达在一个独立的文本文件中,该文件包含目标 .go、go.mod 和 go.work 文件,其中注释中的特殊注解驱动测试。这些测试通常易于编写和快速迭代,但表达能力有限。
-
集成测试是常规的 Go
func Test(*testing.T)
函数,它们对一个假的 LSP 启用客户端编辑器 API 进行一系列调用。该 API 允许您打开和编辑文件、导航到定义、调用其他 LSP 操作以及断言状态属性。由于 LSP 的异步性质,集成测试会断言编辑器最终必须达到的状态,即使程序很快出错,也可能需要一段时间才能将错误报告为在几分钟内未能达到期望状态。我们建议您设置
GOPLS_INTEGRATION_TEST_TIMEOUT=10s
来减少调试时的集成测试超时时间。当集成测试失败时,它们会打印客户端和服务器之间 LSP 会话的日志。虽然冗长,但一旦您学会阅读它们,它们对调试非常有帮助。
如果您需要帮助,请随时联系 gopls 团队。
CI
当您邮寄 CL 并您或另一位贡献者在 Gerrit 中分配 Run-TryBot=1
标签时,TryBots 将在 golang.org/x/tools
和 golang.org/x/tools/gopls
模块中运行测试,如上所述。
此外,一个名为“gopls-CI”的附加通道将由 Kokoro 运行,这是一个类似 Jenkins 的 Google 基础设施,用于运行 Dockerized 测试。这使我们能够在 TryBots 中难以添加的各种环境中运行 gopls 测试。特别是,Kokoro 会在旧版 Go 版本上运行测试,这些版本已不再受 TryBots 支持。按照该政策,对这些旧版 Go 版本的支持是尽力而为的,测试失败可能会被跳过而不是修复。
与 TryBots 一样,Kokoro 运行由 Run-TryBot=1
标签触发,但与 TryBots 不同的是,如果“gopls-CI”结果在 Gerrit 中被移除,它们不会自动重新运行。要强制对包含 Run-TryBot=1
标签的 CL 重新运行 Kokoro CI,您可以在 Gerrit 中回复“kokoro rerun”进行评论。
调试
调试更改的最简单方法是使用调试器运行单个 gopls
测试。
另请参阅故障排除。
文档
除测试新行为的测试外,每个添加或更改功能的 CL 都应包含:
- 一个**发布说明**,简要说明更改;以及
- 在功能索引中**全面的文档**。
发布说明应放在以即将发布的版本命名的文件中,例如 release/v0.16.0.md。(如果您的功能是发布后添加的第一个功能,请创建该文件。)
设计文档
本文档的源代码可以在 golang.org/x/tools/gopls/doc 下找到。