此页面上的内容

导入完成和智能注册表

语言服务器,支持 URL 的补全。

本地导入补全 跳转到标题

当尝试导入相对模块标识符(以 ./../ 开头的标识符)时,将为 Deno 认为可以运行的目录和文件提供导入补全(以扩展名 .ts.js.tsx.jsx.mjs 结尾)。

工作区导入补全 跳转到标题

当尝试导入未配置为注册表的远程 URL(见下文)时,扩展程序将提供已成为工作区一部分的远程模块。

模块注册表补全 跳转到标题

支持它的模块注册表可以配置为自动补全。这提供了一种方便的方式,可以从 IDE 的“舒适区”探索模块注册表。

自动发现 跳转到标题

默认情况下,Deno 语言服务器将尝试确定服务器是否支持补全建议。如果主机/来源尚未明确配置,它将检查服务器,如果它支持补全建议,您将被提示选择启用它还是不启用它。

您应该只为信任的注册表启用此功能,因为远程服务器可能会提供对模块的建议,这些模块试图让您运行不受信任的代码。

配置 跳转到标题

用于配置自动补全注册表的设置

  • deno.suggest.imports.autoDiscover - 如果启用,当语言服务器发现一个未明确配置的新来源时,它将检查该来源是否支持导入补全,并提示您选择启用它还是不启用它。默认情况下为 true

  • deno.suggest.imports.hosts - 这些是配置为提供导入补全的来源。目标主机需要支持 Deno 导入补全(详见下文)。该值是一个对象,其中键是主机,值是启用还是禁用。例如

    {
      "deno.suggest.imports.hosts": {
        "https://deno.land": true
      }
    }
    

它是如何工作的? 跳转到标题

在扩展程序和语言服务器启动时,Deno 将尝试从任何已配置且启用的主机中获取 /.well-known/deno-import-intellisense.json。此文件提供了以高度可配置的方式形成模块标识符自动补全所需的数据(这意味着您不必绑定到任何特定的模块注册表才能获得丰富的编辑器体验)。

当您构建或编辑模块标识符时,Deno 将根据 JSON 配置文件中配置的内容,从主机中获取 URL 的其他部分。

当您完成模块标识符时,如果它尚未在本地缓存,Deno 将尝试从注册表中获取已完成的标识符。

它适用于所有远程模块吗? 跳转到标题

不,因为扩展和 Deno 需要理解如何查找模块。配置文件提供了一种高度灵活的方式,允许人们描述如何构建 URL,包括在模块注册表支持的情况下支持语义版本控制。

导入完成的注册表支持 跳转到标题

为了支持 Deno 语言服务器发现注册表,注册表需要提供一些东西

  • 一个模式定义文件。此文件需要位于 /.well-known/deno-import-intellisense.json。此文件提供 Deno 语言服务器查询注册表并构建导入说明符所需的配置。
  • 一系列 API 端点,提供要提供给用户以完成导入说明符的值。

配置模式 跳转到标题

模式定义的 JSON 响应需要是一个具有两个必需属性的对象

  • "version" - 一个数字,必须等于 12
  • "registries" - 一个注册表对象的数组,定义了如何为该注册表构建模块说明符。

有一个 JSON 模式文档定义了此模式,作为 CLI 源代码的一部分提供。

虽然 v2 支持比 v1 更多的功能,但它们是以非破坏性的方式引入的,语言服务器会自动处理 v1 或 v2 版本,无论 "version" 键中提供了什么版本,因此从技术上讲,注册表可以声称自己是 v1 但使用所有 v2 功能。但是,这是不推荐的,因为虽然目前没有专门支持 v2 功能的代码分支,但这并不意味着将来为了支持v3或其他版本而不会有分支。

注册表 跳转到标题

在配置模式中,"registries" 属性是一个注册表数组,它们是包含两个必需属性的对象

  • "schema" - 一个字符串,它是一个类似 Express 的路径匹配表达式,定义了如何在注册表上构建 URL。语法直接基于 path-to-regexp。例如,如果注册表上 URL 的说明符是 https://example.com/a_package@v1.0.0/mod.ts,则模式值可能类似于以下内容

    {
      "version": 1,
      "registries": [
        {
          "schema": "/:package([a-z0-9_]*)@:version?/:path*"
        }
      ]
    }
    
  • "variables" - 对于在模式中定义的键,需要定义一个相应的变量,它通知语言服务器从模块说明符的该部分获取完成信息。在上面的示例中,我们有 3 个变量 packageversionpath,因此我们期望每个变量都有一个变量定义。

变量 跳转到标题

在配置模式中,"variables" 属性是一个变量定义数组,它们是具有两个必需属性的对象

  • "key" - 一个字符串,与 "schema" 属性中的变量键名称说明符匹配。

  • "documentation" - 一个可选的 URL,语言服务器可以在其中获取单个变量条目的文档。变量可以被替换以构建最终 URL。具有单括号格式的变量(如 ${variable})将作为匹配项添加到字符串中,而具有双括号格式的变量(如 ${{variable}})将被百分比编码为 URI 组件部分。

  • "url" - 一个 URL,语言服务器可以在其中获取变量的完成信息。变量可以被替换以构建 URL。具有单括号格式的变量(如 ${variable})将作为匹配项添加到字符串中,而具有双括号格式的变量(如 ${{variable}})将被百分比编码为 URI 组件部分。如果 "key" 的值包含变量,则语言服务器将支持对部分模块的增量请求,允许服务器在用户键入变量值的一部分时提供完成信息。如果 URL 未完全限定,则模式文件的 URL 将用作基准。在我们上面的示例中,我们有三个变量,因此我们的变量定义可能如下所示

    {
      "version": 1,
      "registries": [
        {
          "schema": "/:package([a-z0-9_]*)@:version?/:path*",
          "variables": [
            {
              "key": "package",
              "documentation": "https://api.example.com/docs/packages/${package}",
              "url": "https://api.example.com/packages/${package}"
            },
            {
              "key": "version",
              "url": "https://api.example.com/packages/${package}/versions"
            },
            {
              "key": "path",
              "documentation": "https://api.example.com/docs/packages/${package}/${{version}}/paths/${path}",
              "url": "https://api.example.com/packages/${package}/${{version}}/paths/${path}"
            }
          ]
        }
      ]
    }
    

URL 端点 跳转到标题

每个 URL 终结点的响应都需要是一个 JSON 文档,该文档是一个字符串数组或一个完成列表

interface CompletionList {
  /** The list (or partial list) of completion items. */
  items: string[];
  /** If the list is a partial list, and further queries to the endpoint will
   * change the items, set `isIncomplete` to `true`. */
  isIncomplete?: boolean;
  /** If one of the items in the list should be preselected (the default
   * suggestion), then set the value of `preselect` to the value of the item. */
  preselect?: string;
}

扩展我们上面的示例,URL https://api.example.com/packages 预计会返回类似以下内容

[
  "a_package",
  "another_package",
  "my_awesome_package"
]

或者类似以下内容

{
  "items": [
    "a_package",
    "another_package",
    "my_awesome_package"
  ],
  "isIncomplete": false,
  "preselect": "a_package"
}

而对 https://api.example.com/packages/a_package/versions 的查询将返回类似以下内容

[
  "v1.0.0",
  "v1.0.1",
  "v1.1.0",
  "v2.0.0"
]

或者

{
  "items": [
    "v1.0.0",
    "v1.0.1",
    "v1.1.0",
    "v2.0.0"
  ],
  "preselect": "v2.0.0"
}

而对 https://api.example.com/packages/a_package/versions/v1.0.0/paths 的查询将返回类似以下内容

[
  "a.ts",
  "b/c.js",
  "d/e.ts"
]

或者

{
  "items": [
    "a.ts",
    "b/c.js",
    "d/e.ts"
  ],
  "isIncomplete": true,
  "preselect": "a.ts"
}

多部分变量和文件夹 跳转到标题

浏览大型文件列表对用户来说可能是一个挑战。在注册表 V2 中,语言服务器对返回的项目进行了一些特殊处理,以便更容易地完成对子文件夹中文件的路径。

当返回的项目以 / 结尾时,语言服务器将把它呈现给客户端作为“文件夹”,并在客户端中表示。因此,希望为以下文件夹结构提供子导航的注册表

examples/
└─┬─ first.ts
  └─ second.ts
sub-mod/
└─┬─ mod.ts
  └─ tests.ts
mod.ts

并且具有类似 /:package([a-z0-9_]*)@:version?/:path* 的模式,以及 path 的 API 终结点,例如 https://api.example.com/packages/${package}/${{version}}/${path},将希望对 /packages/pkg/1.0.0/ 的路径做出以下响应

{
  "items": [
    "examples/",
    "sub-mod/",
    "mod.ts"
  ],
  "isIncomplete": true
}

以及对 /packages/pkg/1.0.0/examples/ 的路径做出以下响应

{
  "items": [
    "examples/first.ts",
    "examples/second.ts"
  ],
  "isIncomplete": true
}

这将允许用户在获取文件夹中的列表之前选择 examples 文件夹,从而更容易地浏览文件结构。

文档终结点 跳转到标题

文档终结点应返回一个文档对象,其中包含与请求的实体相关的任何文档

interface Documentation {
  kind: "markdown" | "plaintext";
  value: string;
}

为了扩展上面的示例,对 https://api.example.com/packages/a_package 的查询将返回类似以下内容

{
  "kind": "markdown",
  "value": "some _markdown_ `documentation` here..."
}

模式验证 跳转到标题

当语言服务器启动(或扩展的配置发生更改)时,语言服务器将尝试获取并验证配置中域主机指定符的模式配置。

验证尝试确保定义的所有注册表都是有效的,这些模式中包含的变量在变量中指定,并且没有定义不在模式中包含的额外变量。如果验证失败,注册表将不会启用,并且错误将记录到 vscode 中的 Deno 语言服务器输出中。

如果您是注册表维护者,并且需要帮助、建议或在为自动完成设置注册表方面的帮助,请随时打开一个 问题,我们将尽力提供帮助。

已知注册表 跳转到标题

以下是已知支持该方案的注册表列表。您只需将域添加到 deno.suggest.imports.hosts 并将值设置为 true

  • https://deno.land/ - 第三方 /x/ 注册表和 /std/ 库注册表都可用。
  • https://nest.land/ - Deno 在区块链上的模块注册表。
  • https://crux.land/ - 用于永久托管小型脚本的免费开源注册表。