Gopls:被动特性

本页介绍了 gopls 的基本 LSP 特性,这些特性可以被描述为“被动的”,因为许多编辑器会持续使用它们来提供有关源代码文件的信息,而无需采取任何特殊操作。

另请参阅 代码提示,其中一些会用额外信息注解您的源代码,因此也可以被视为被动特性。

悬停 (Hover)

LSP 的 textDocument/hover 查询会返回光标下代码的描述,例如其名称、种类、类型、值(对于常量)、缩略声明(对于类型)、文档注释(如果存在),以及指向 pkg.go.dev 上符号文档的链接。客户端可以请求纯文本或 Markdown 格式。

根据选定内容,响应可能包含额外信息。例如,悬停在类型上会显示其声明的方法,以及从嵌入字段中提升的任何方法。

文档链接:文档注释可以使用方括号引用其他符号,例如 [fmt.Printf]。悬停在其中一个 文档链接 上会显示有关被引用符号的信息。

结构体大小/偏移量信息:对于结构体类型的声明,悬停在名称上会显示结构体的字节大小

悬停在每个字段名称上会显示该字段的大小和偏移量

这些信息在优化数据结构的布局、或在阅读引用每个字段的汇编文件或堆栈跟踪(其中按模糊的字节偏移量引用字段)时可能很有用。

此外,悬停还会报告

  • 结构体的 size class,即 Go 运行时为该类型单个对象实际分配的字节数;以及
  • 由于结构体字段排序不佳而浪费的空间百分比,如果该数值为 20% 或更高

在上面的结构体中,对齐规则要求两个布尔字段(1 字节)各自占用一个完整的字(8 字节),导致 (7 + 7) / (3 * 8) = 58% 的浪费。将两个布尔值放在一起可以节省一个字。(在大多数结构体中,清晰度比紧凑性更重要,因此您应该仅在性能分析显示分配非常频繁的数据结构中才重新排序字段以节省空间。)

嵌入指令:悬停在 //go:embed 指令中的文件名模式(例如 *.html)会显示通配符展开到的文件名列表。

Linkname 指令//go:linkname 指令为另一个符号创建链接器级别的别名。悬停在指令上会显示其他符号的信息。

对于 Go 1.0 之后添加到标准库的符号,悬停信息会显示添加该符号的 Go 版本。

设置 (Settings)

  • hoverKind 设置控制文档的详细程度。
  • linkTarget 设置指定 Go 包链接的基础 URI。

注意事项 (Caveats)

  • LSP 的一个不幸限制是,Hover 请求当前只包含一个位置,而不包含选定范围。这意味着无法请求有关较大表达式 f(x).yf(x) 部分的类型和方法的信息。如果您希望看到这个问题得到解决,请为您在 microsoft/language-server-protocol#1466 上点赞。

客户端支持 (Client support)

  • VS Code:默认启用。在光标附近显示渲染的 Markdown 面板。
  • Emacs + eglot:默认启用。在回显区显示单行摘要。
  • Vim + coc.nvim: ??
  • CLIgopls definition file.go:#start-#end 包含来自 Hover 查询的信息。

签名帮助 (Signature Help)

LSP 的 textDocument/signatureHelp 查询会返回包含光标或选定范围的最内层函数调用信息,包括函数的签名以及每个参数的名称、类型和文档。

客户端可以提供此信息,以帮助用户在阅读或编辑函数调用时记住每个参数的目的及其顺序。

如果光标位于表示函数或方法的标识符内,则不需要调用括号。例如,在 once.Do(initialize‸) 中进行签名帮助会描述 initialize,而不是 once.Do

客户端支持 (Client support)

  • VS Code:默认启用。在 IntelliSense 设置中也称为“参数提示”。与 Hover 信息一起显示签名和文档注释。
  • Emacs + eglot:默认启用。在回显区显示签名。
  • Vim + coc.nvim: ??
  • CLIgopls signature file.go:#start-#end

文档高亮 (Document Highlight)

LSP 的 textDocument/documentHighlight 查询会报告一组应根据当前光标位置或选定范围进行高亮的源范围,以强调它们之间的关系。

以下语法部分的每一部分都形成一个集合,因此如果您选择其中任何一个成员,gopls 都会高亮整个集合:

  • 引用同一符号的每个标识符(如下面的截图所示);
  • 一个命名结果变量及其所有对应的 return 语句的操作数;
  • 同一循环的 forbreakcontinue 关键字;
  • 同一 switch 语句的 switchbreak 关键字;
  • 函数的 func 关键字及其所有 return 语句。

一个选择可能激活以上多条规则,例如,通过一个既是标识符又是 return 操作数的标识符。

同一标识符的不同出现可能被着色,以区分对给定变量符号的“读取”和“写入”引用。

客户端支持 (Client support)

  • VS Code:默认启用。通过光标移动或单击触发。(注意:双击会激活简单的、不考虑语法的文本匹配。)
  • Emacs + eglot:默认启用。通过光标移动或选定范围触发。
  • Vim + coc.nvim: ??
  • CLIgopls signature file.go:#start-#end

插入提示 (Inlay Hint)

LSP 的 textDocument/inlayHint 查询会返回一组注释,这些注释将被插入到当前文件中,以揭示隐式信息。

示例

  • 在函数调用 f(1, 2) 中,提示会提供参数的名称(parameterNames),如上图所示。
  • 在调用泛型函数时,提示会提供类型参数(functionTypeParameters)。
  • 在赋值 x, y = 1, 2 中,提示会提供变量的类型(assignVariableTypes)。
  • 在结构体字面量(如 Point2D{1, 2})中,提示会提供字段名称(compositeLiteralFields)。
  • 在嵌套的复合字面量 T{{...}} 中,提示会提供内部字面量 {...} 的类型(compositeLiteralTypes)。
  • for k, v := range x {} 循环中,提示会提供变量 k 和 v 的类型(rangeVariableTypes)。
  • 对于常量表达式(可能使用 iota),提示会提供其计算值(constantValues)。

有关完整列表和示例,请参阅 插入提示

设置 (Settings)

  • hints 设置指示所需的提示集。为减少干扰,其默认值为空。要启用提示,请将上面一个或多个标识符添加到 hints 映射中。例如:
    "hints": {"parameterNames": true}
    

客户端支持 (Client support)

  • VS Code:除了 hints 配置值外,VS Code 还提供了一个图形化配置菜单(“Preferences: Open Settings (UI)” 然后搜索“Go Inlay Hints”),用于配置每种支持的插入提示类型。
  • Emacs + eglot:默认禁用。需要 M-x eglot-inlay-hints-mode 以及 此处描述的配置。
  • Vim + coc.nvim: ??
  • CLI:不支持

语义令牌 (Semantic Tokens)

LSP 的 textDocument/semanticTokens 查询会报告当前文件或其一部分中所有令牌的信息。客户端可以使用这些信息来提供语法高亮,以传达例如函数与类型、常量与变量、或库函数与内置函数之间的语义区别。

客户端必须指定其感兴趣的类型和修饰符集合。

Gopls 报告以下令牌类型:

  • "comment":注释
  • "function":函数
  • "keyword":关键字
  • "label":控制标签(非 LSP 标准类型)
  • "macro":text/template 令牌
  • "method":方法
  • "namespace":导入的包名
  • "number":数字字面量
  • "operator":运算符
  • "parameter":参数变量
  • "string":字符串字面量
  • "type":类型名称(以及其他用途)
  • "typeParameter":类型参数
  • "variable":变量或常量(参见 readonly 修饰符)

Gopls 还报告以下标准修饰符:

  • "defaultLibrary":预声明的符号
  • "definition":符号的声明标识符
  • "readonly":用于常量

以及这些非标准修饰符,每个代表该符号类型的顶层构造函数:

  • "array"
  • "bool"
  • "chan"
  • "interface"
  • "map"
  • "number"
  • "pointer"
  • "signature"
  • "slice"
  • "string"
  • "struct"

设置 (Settings)

客户端支持 (Client Support)

  • VS Code:请参阅 语义高亮指南
  • Emacs + eglot:不支持;请参阅 joaotavora/eglot#615。
  • Vim + coc.nvim: ??
  • CLIgopls semtok file.go

折叠范围 (Folding Range)

LSP 的 textDocument/foldingRange 查询会报告当前文件中可以独立折叠或展开的区域列表。例如,在研究某些代码时,折叠大型注释或函数可能很方便,这样可以在单个屏幕上显示更多内容。

该协议 允许 客户端指示它们更偏好细粒度范围(如匹配的括号对),还是仅限完整行组成的范围。

客户端支持 (Client support)

  • VS Code:显示在左边距。通过切换箭头(>)来折叠或展开。
  • Emacs + eglot:不支持。
  • Vim + coc.nvim: ??
  • CLIgopls folding_ranges file.go

LSP 的 textDocument/documentLink 查询使用启发式方法从当前文件中的文档注释和字符串字面量中提取 URL,以便客户端可以将它们显示为可点击链接。

除了显式 URL 之外,gopls 还会将 import 声明中的字符串字面量转换为指向已导入包的 pkg.go.dev 文档的链接。

设置 (Settings)

  • importShortcut 设置决定为 import 声明返回哪种类型的链接。
  • linkTarget 设置指定 Go 包链接的基础 URI。

客户端支持 (Client support)

  • VS Code:悬停在链接上会显示“Follow link (cmd+click)”弹出窗口。
  • Emacs + eglot:目前未使用。
  • Vim + coc.nvim: ??
  • CLIgopls links file.go

本文档的源代码可以在 golang.org/x/tools/gopls/doc 下找到。