贡献

如果您计划投入大量精力进行一个大的拉取请求,其中涉及多个可能影响 Ruby LSP 长期维护的决策,请先开启一个讨论,以统一方向。

ruby-lsp 存储库包含三个子项目

  • 语言服务器 (ruby-lsp),位于存储库的顶层。大多数功能都在这里实现,因为服务器中实现的所有内容都可用于所有编辑器
  • VS Code 扩展,位于 vscode 目录下。任何自定义的 VS Code 功能都在这里实现
  • 文档网站,位于 jekyll 目录下。Ruby LSP 和 Rails 附加组件的所有面向用户的文档都包含在此处

本贡献指南按每个组件进行划分。

初始化设置

要开始为 Ruby LSP 做贡献,请确保已按如下方式安装所有依赖项

  • 顶层的 bundle install 将安装 Ruby 依赖项
  • jekyll 目录中的 bundle install 将安装文档依赖项
  • vscode 目录中的 yarn install 将为 VS Code 扩展安装 Node.js 依赖项

为服务器做贡献

这是 ruby-lsp gem 的结构

  • lib/ruby_indexer:代码索引器,用于从工作区提取声明
  • lib/ruby_lsp/*.rb:语言服务器的基础部分,例如工作线程、队列、处理请求等
  • lib/ruby_lsp/requests:请求实现。这些与 语言服务器规范 一一对应
  • lib/ruby_lsp/listeners:Prism 调度器监听器。服务器的大部分基础设施依赖于监听器模式,以在遍历 AST 时最大限度地提高性能。请注意,单个请求可能依赖于多个监听器

在添加或更改现有功能时,首先在规范中确定哪个请求负责该功能。然后确定服务器中哪个文件实现了该请求,并开始考虑实现。

使用 VS Code 时,打开 lsp.code-workspace 文件,而不是只打开常规文件夹。它包含用于有效并排使用子项目的配置

调试

实时调试服务器

在使用 VS Code 时,可以实时调试当前正在运行的语言服务器的开发实例

  1. CMD/CTRL + SHIFT + P 打开命令面板
  2. 搜索 调试 Ruby LSP 服务器。此命令将以调试模式重启服务器,允许您连接调试器。请注意,调试模式仅在编辑器关闭或 Ruby LSP 重启之前有效
  3. 服务器以调试模式启动后,通过转到 运行和调试,选择 附加到现有服务器 任务并单击运行来附加调试器
  4. 现在您应该能够在 UI 中设置断点,触发请求将在这些断点处停止

注意:由于您正在调试当前在您自己的编辑器中运行的语言服务器实例,如果执行当前在断点处暂停,则功能将不可用。

理解 Prism AST

Ruby LSP 使用 Prism 来解析和理解 Ruby 代码。在处理某个功能时,通常需要检查给定代码片段的 Prism AST 结构,以便您可以了解为什么以某种方式触发请求。

如果您正在使用 VS Code,则可以使用 显示语法树命令 来检查整个文档或选择的 AST 结构。

对于其他编辑器,使用我们的 IRB 配置是实现相同目的的最简单方法

  1. bundle exec irb 使用我们的配置启动 IRB。它将为您要求所有库
  2. 然后解析您想更好理解的 Ruby 代码并开始检查
source = <<~RUBY
  class Foo
    def bar
    end
  end
RUBY

ast = Prism.parse(source).value

查看 Prism 文档以获取更多相关信息。

追踪 LSP 请求和响应

在 VS Code 中,您可以通过启用追踪来验证服务器中发生的情况,这允许不同级别的日志记录。

{
  // Your JSON settings
  //
  // - `off`: no tracing
  // - `messages`: display requests and responses notifications
  // - `verbose`: display each request and response as JSON
  "ruby lsp.trace.server": "messages"
}

手动测试更改

在您进行更改或添加新功能后,您可以通过重启语言服务器在编辑器中进行验证。在 VS Code 中,可以通过运行命令 Ruby LSP: restart 来实现,这将重启服务器并拾取您的更改。

对于其他编辑器,您必须手动重启语言服务器才能拾取最新更改。

调试测试

在 VS Code 中,我们建议

  1. 在 UI 中设置断点
  2. 打开将命中该断点的测试
  3. 单击示例顶部的 debug 代码镜头按钮

或者(对于其他编辑器),在代码中添加 binding.b 语句并在终端中执行测试,这也允许您调试代码。

编写测试

Ruby LSP 中有两种类型的测试。第一种类型可能很熟悉:标准的 Minitest 文件,其中包含一堆使用方法声明语法的示例。

第二种类型的测试是我们的夹具/期望框架。在 test/fixtures 下添加新的夹具将自动使框架对该夹具运行所有请求。默认情况下,框架仅检查在对夹具运行时功能是否崩溃。这对于确保在使用不太常见的 Ruby 语法时,关键请求不会中断很有用。

要超越检查请求是否会因夹具而中断,您可以在 test/expectations/NAME_OF_THE_REQUEST 中添加一个期望,这允许您断言请求和夹具组合的预期响应。

例如,如果我们有一个 test/fixtures/foo.rb,那么添加一个 test/expectations/semantic_highlighting/foo.exp.json 将使框架验证在 foo.rb 夹具中运行语义高亮时,期望的响应是 foo.exp.json

查看现有夹具和期望组合的示例。

何时使用每种类型的测试

夹具/期望框架主要用于完整文档请求(每次都为整个文件计算的语言服务器功能)。

特定于位置或在不同机制下运行的请求和功能应仅使用常规 Minitest 测试。

运行测试套件

有多种可用的执行测试的方法。

# Run the entire test suite
bundle exec rake

# Run only indexing tests
bundle exec rake test:indexer

# Run only language server tests (excluding indexing)
bundle exec rake test

# Using the custom test framework to run a specific fixture example
# bin/test test/requests/the_request_you_want_to_run_test.rb name_of_fixture
bin/test test/requests/diagnostics_expectations_test.rb def_bad_formatting

此外,我们使用 RuboCop 进行 linting,并使用 Sorbet 进行类型检查。

# Run linting
bundle exec rubocop

# Run type checking
bundle exec srb tc

为 VS Code 扩展做贡献

在本节开始之前,请确保已安装依赖项

除了此处描述的内容之外,VS Code 扩展 API 文档也是一个很好的地方,可以收集有关扩展如何与编辑器交互的更多上下文。

VS Code 扩展当前具有以下主要部分

测试更改

打开 lsp.code-workspace 文件,而不是只打开常规文件夹。它包含使用如下所述的“运行和调试”所需的配置。

我们尽量确保尽可能彻底的测试。但是,有些测试很难编写,特别是那些与 VS Code 小部件交互的测试。

例如,如果运行测试显示一个对话框,则测试没有简单的方法来单击其上的按钮以继续执行。对于这些情况,我们使用 sinon 来存根预期的调用和响应。

注意:client.test.ts 是一个集成风格的测试,它启动 ruby-lsp gem 的开发版本并针对它运行请求。

运行测试

运行测试最简单的方法是在 运行和调试 中选择 扩展测试 任务,然后点击运行。这将运行所有测试,结果将显示在 VS Code 的调试控制台中。

或者,您也可以通过终端运行测试,这将在存储库内下载一个测试 VS Code 版本,并针对该版本运行测试。您可以通过运行启动任务来避免下载。

注意:无法运行单个测试文件或示例。

实时调试

可以对扩展的开发版本进行实时调试。详细信息可以在 VS Code 扩展文档 中找到,但本节包含一个简短的描述。

实时调试涉及两个 VS Code 窗口。第一个窗口是您将修改代码的地方,第二个窗口是扩展的开发版本将运行的地方。您需要在第一个窗口中更改代码,重新加载并在第二个窗口中验证更改。

  1. 首先,在 运行和调试 面板中使用 运行扩展 任务启动扩展调试。这将打开第二个 VS Code 窗口,其中运行着扩展的开发版本。
  2. 在第一个原始 VS Code 窗口中进行所需的更改
  3. 单击 调试工具栏 中的重新加载按钮,将您最近的更改加载到第二个 VS Code 窗口中
  4. 在第二个窗口中执行操作以验证您的更改

如果您希望执行单步调试,您只需在第一个窗口(您正在修改代码的窗口)的 UI 中添加断点,而不是在第二个窗口(扩展的开发版本正在运行的窗口)中添加断点。

贡献文档

Ruby LSP 使用 Jekyll 来生成文档,其源代码位于 /jekyll 文件夹下。在进行任何更改之前,请确保您已 执行了初始设置

之后,按照以下步骤进行并验证您的更改

  1. 进行所需的更改
  2. 在开发中启动 Jekyll
    bundle exec jekyll serve
    
  3. 通过访问 https://127.0.0.1:4000/ruby-lsp 在本地验证您的更改

贡献 Ruby LSP Rails 附加组件

请参阅 https://github.com/Shopify/ruby-lsp-rails/blob/main/CONTRIBUTING.md