mcpField
T
type-inference

type-inference

github.com/biomejs开发26.0k90 次安装今天更新
代码仓库

关于 type-inference

面向 Biome 贡献者的 JavaScript 和 TypeScript 类型推断开发技能,涵盖推断边界、Salsa 查询、结果语义与针对性测试。

主要功能

  1. 01五层推断模型
  2. 02原始类型与推断类型指南
  3. 03精简请求和查询边界
  4. 04不确定性与结果语义
  5. 05分层测试与性能分析

适用场景

  1. 01添加语法派生的类型信息
  2. 02创建或修改跟踪查询
  3. 03构建类型感知的 lint 规则
  4. 04测试推断与失效行为

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/biomejs/biome --skill type-inference

安装后在 Claude Code 中输入/type-inference确认已加载。

详细介绍

基于 Salsa 的类型推断

范围

在处理 JavaScript 和 TypeScript 类型推断时使用此技能:原始集合、基于 Salsa 的推断值、分析器请求、跟踪查询以及推断专用测试。

对于通用 lint 脚手架、诊断、快照或变更集,请加载相应技能。除非 CSS 和 HTML 模块图数据直接参与 JavaScript 或 TypeScript 类型推断,否则不属于此技能范围。

阅读相关指南

不要在每项推断任务中都完整加载两份架构指南。请阅读与所更改边界相对应的章节:

任务权威指南
原始表示和推断表示、收集、推断层、句柄、规范化、工作限制biome_js_type_info/CONTRIBUTING.md
分析器请求、跟踪查询、解析上下文、扩宽、性能分析、Salsa 执行测试biome_module_graph/CONTRIBUTING.md

跨越两份指南所述边界更改架构时,请同时阅读两份指南。然后检查与具体请求、查询系列或表示相关的实现文件。

心智模型

类型推断分为五层:

syntax and semantic collection
    -> raw module tables
    -> analyzer-facing requests
    -> tracked Salsa queries
    -> resolver helpers

收集过程遍历单个模块,不访问数据库。它会在 JsModuleInfo 中记录原始类型、表达式和绑定类型。请求定义面向分析器的结果约定。跟踪查询提供记忆化和失效边界。解析器辅助函数在这些边界内评估引用和推断结构。

请区分以下三种类型世界:

世界主要类型用途
原始收集器TypeData / RawTypeData、TypeReference、RawTypeId、TypeStore模块本地语法、声明、导入和延迟表达式
数据库支持InferredTypeData<'db>、LocalTypeHandle、GlobalTypeId跟踪计算中的推断值和模块所有权
面向分析器InferredType<'db>为 lint 规则提供保守且有界的检查

TypeReference 属于原始类型世界。如果 InferredType 已提供所需操作,lint 规则就不应对原始 TypeData 进行模式匹配。

推断数据仍归声明它的模块所有。不要将其他模块的推断负载复制到当前模块中,包括通过 Arc 复制。请通过引用、模块感知句柄、全局 ID 和跟踪查询保留所有权。

选择最窄的边界

推断级别是可选方案,而不是连续阶段:

需求边界
检查单个模块中收集的事实原始本地表
解析单个表达式、绑定、导出、成员、参数或分类定向请求和跟踪查询
解析模块中的所有原始类型、表达式和绑定完整模块推断

边界更宽并不一定更正确。多个级别都能满足需求时,请按以下顺序决策:

inspect raw local information
    -> return when the local result is conclusive
    -> resolve the smallest selected reference
    -> preserve uncertainty or widen only when the contract requires it
    -> use complete-module inference as the last resort

infer_module_types 用于需要完整表的约定。 infer_module_types_bottom_up 是一个非跟踪的外部调度器,不得从新的跟踪查询中调用。

类型感知 lint 规则

类型感知 JavaScript 规则使用分析器服务,而不是直接使用数据库查询:

  1. 在规则元数据中声明 domains: &[RuleDomain::Types]。
  2. 将 Typed<N> 用作规则查询。
  3. 调用 RuleContext 中现有的推断方法,该方法由 TypedService 提供支持。
  4. 通过有界辅助函数检查返回的 InferredType。
  5. 将分类结果显式处理为 Match、NoMatch 或 Indeterminate。

从 crates/biome_js_analyze/src/services/typed.rs 开始,并搜索当前的 Typed< 使用者。规则只询问一个属性时,优先使用分类请求;如果更窄的分类器即可回答问题,就不要规范化并遍历完整类型。

更改原始推断

添加由语法推导的类型信息时:

  1. 在 crates/biome_js_type_info/src/type_data.rs 中定义原始表示。
  2. 在 crates/biome_js_type_info/src/local_inference.rs 或 crates/biome_module_graph/src/js_module_info/collector.rs 中收集信息,并将 未解析的操作数保留为 TypeReference 值。
  3. 在 crates/biome_js_type_info/src/interned_types.rs 中进行转换。
  4. 仅当通用的原始类型到推断类型转换不足以满足需求时,才在 crates/biome_module_graph/src/db/type_inference/ 下添加求值逻辑。
  5. 检查原始类型和推断类型的匹配、遍历及格式化逻辑,确保覆盖新变体。

收集器快照可证明:在需要数据库解析的场景中,原始结构仍会延后处理。查询测试则会单独验证推断结果。

请求与跟踪查询

请求位于 crates/biome_module_graph/src/type_inference/requests/ 下。应为可复用的结果约定添加请求,而不是为单条 lint 规则添加请求。当输出和不确定性行为一致时,复用现有请求。

请求应定义稳定的元数据、唯一的规范执行路径、精确的源代码来源,以及明确的不确定性。通过 TypeInferenceRequestContext 组合操作;分析器代码不应构造底层查询输入。

只有当结果需要独立的记忆化和失效边界时,才添加跟踪查询。新查询必须:

  • 返回使用方所需的最小语义结果;
  • 接收数据库以及一个 Salsa 输入或内部化键;
  • 只读取可能影响结果的依赖项;
  • 定义缺失输入、歧义、循环和工作预算的处理方式;
  • 保留 Unknown 或 Indeterminate,而不是臆造确定结果;
  • 使用当前的查询检测系列;
  • 配备正确性测试和选择性执行测试。

对相同输入进行内部化会让它们共享标识;但这不会记忆化查询结果。有关当前的 trait、注册和测试要求,请参阅模块图指南中的 Request architecture 和 Adding a tracked query 部分。

解析与结果语义

按需解析会沿选定的查找路径进行,直到请求要求执行更广泛的工作。规范化会通过有界遍历解析可达句柄;它并不等同于完整模块推断。命名空间展开和受保护的深层导入回退可能大幅扩大工作范围,因此必须明确执行并使其可观察。

不要混淆以下结果:

结果含义
None根据其文档约定,请求没有结果
InferredTypeData::Unknown推断得到了一个结构尚不确定的类型
InferredTypeData::UnknownKeyword源代码明确使用了 TypeScript 的 unknown 类型
TypeInferenceClassification::Indeterminate推断无法证明匹配或不匹配
TypeInferenceClassification::Match推断确切证明了条件成立
TypeInferenceClassification::NoMatch推断确切证明了条件不成立

未知或不确定的信息不代表否定结果。应保留这些信息,以避免误报诊断。更改这些路径前,请阅读规范中有关扩大范围、循环恢复和结果语义的部分。

ResolutionCtx 会在每个上下文中保留其循环集合、深度限制和缓存。解析过程中不要为另一个模块创建上下文并通过它递归。应改为经过跟踪查询、已用尽的导入或步骤预算,或者共享的声明求值器。模块图指南中的 Resolver helpers 部分列出了这些边界。

测试与性能分析

针对受影响范围最小的边界进行测试:

  • 用于原始记录和引用的收集器测试;
  • 用于结果、导入、循环和不确定性的请求/查询测试;
  • 当依赖项或失效范围发生变化时,进行 Salsa 事件测试;
  • 用于最终诊断行为的分析器 fixture。

对于针对性流程,证明无关编辑会复用查询,而已消费的输入会触发重新计算。除非请求契约或受测回退逻辑有此要求,否则应断言不会执行整个模块的推断。

当请求解析的数据超出预期时,请使用模块图指南中记录的维护配置文件。请求和查询的耗时均为包含下游操作的耗时,不得相加。快照机制请加载 testing-codegen。

审查清单

  • 实现使用了正确的原始世界、推断世界或面向分析器的世界。
  • 请求或查询是满足其契约的最小边界。
  • 缺失数据、歧义、循环和预算耗尽均能保留不确定性。
  • 解析过程中不会在没有受跟踪查询、已消耗预算或共享声明求值器约束的情况下创建 ResolutionCtx。
  • 跨模块的推断数据仍归其源模块所有。
  • 新的请求契约可复用,且元数据稳定。
  • 新的查询键和依赖项是稳定的 Salsa 值。
  • 不会执行整个模块的推断,或有明确理由说明为何需要执行。
  • 正确性和选择性执行测试覆盖了变更的边界。

评论

支持 Markdown