菜单

格式化系统

相关源文件

目的与范围

TypeScript 中的格式化系统负责对 TypeScript 和 JavaScript 源代码应用一致的代码格式化规则。这包括管理空格、缩进、换行和其他代码布局方面。语言服务使用该系统来提供编辑器和 IDE 的代码格式化功能,从而实现“格式化文档”和“格式化选区”等功能,以及在键入分号、大括号和回车键等特定字符时自动格式化。

本文档解释了格式化系统的架构和组件、格式化规则的定义和应用方式,以及代码格式化的过程。

系统架构

格式化系统由几个关键组件组成,它们协同工作以分析和格式化代码。

来源: src/services/formatting/formatting.ts1-500 src/services/formatting/formattingContext.ts1-111 src/services/formatting/formattingScanner.ts1-336 src/services/formatting/rules.ts1-100 src/services/formatting/smartIndenter.ts1-100

格式化流程

格式化过程遵循一个明确定义的流程,根据格式化规则转换代码。

来源: src/services/formatting/formatting.ts159-187 src/services/formatting/formatting.ts465-487

关键组件

格式化上下文

FormattingContext 包含做出格式化决策所需的的状态。它跟踪

  • 当前和下一个 token 范围
  • 这些 token 的父节点
  • 共同的祖先节点(上下文节点)
  • 有关这些元素的行位置信息

来源: src/services/formatting/formattingContext.ts12-111

格式化扫描器

FormattingScanner 负责遍历源代码,识别 token 和 trivia(空格、注释),并向格式化过程提供 token 信息。

主要职责

  • 推进 token 流
  • 读取 token 信息
  • 跟踪前导和尾随 trivia
  • 支持各种 token 类型的专用扫描操作

来源: src/services/formatting/formattingScanner.ts28-335

规则和规则映射

格式化规则定义了代码应如何格式化。每条规则指定

  • 规则适用的左侧和右侧 token 范围
  • 规则应适用的上下文条件
  • 要执行的操作(插入/删除空格、插入新行等)

RulesMap 为给定的 token 对提供了高效的适用规则查找。

来源: src/services/formatting/rules.ts36-338 src/services/formatting/rulesMap.ts1-157 src/services/formatting/rule.ts1-49

智能缩进

SmartIndenter 负责智能地缩进代码。它根据以下内容确定适当的缩进:

  • 代码结构(块、语句、表达式)
  • 节点之间的父子关系
  • 用户定义的缩进设置

来源: src/services/formatting/smartIndenter.ts62-634

格式化操作

格式化系统支持几种类型的格式化操作:

操作功能描述来源
格式化文档formatDocument格式化整个源文件src/services/formatting/formatting.ts230-237
格式选择格式化选区格式化选定的文本范围src/services/formatting/formatting.ts240-247
回车键格式化formatOnEnter按下回车键时格式化src/services/formatting/formatting.ts160-187
分号格式化formatOnSemicolon键入分号时格式化src/services/formatting/formatting.ts189-193
左花括号格式化formatOnOpeningCurly键入左花括号时格式化src/services/formatting/formatting.ts196-222
右花括号格式化formatOnClosingCurly键入右花括号时格式化src/services/formatting/formatting.ts224-228

来源: src/services/formatting/formatting.ts159-247

缩进流程

缩进系统使用一种复杂的方法来确定不同代码结构的适当缩进。

来源: src/services/formatting/smartIndenter.ts82-229

规则系统

格式化系统使用基于规则的方法来确定如何格式化代码。规则按优先级和特异性组织。

  1. 高优先级规则:始终优先应用,无论用户设置如何。
  2. 用户可配置规则:根据FormatCodeSettings中的用户偏好进行应用。

每条规则由以下部分组成:

  • 左 token 范围(潜在格式化更改之前的 token)
  • 右 token 范围(潜在格式化更改之后的 token)
  • 上下文谓词(必须满足的条件)
  • 要执行的操作(插入/删除空格、插入新行等)

来源: src/services/formatting/rules.ts36-338 src/services/formatting/rule.ts8-48

格式化示例流程

为了说明格式化系统的工作原理,让我们通过格式化文档的过程进行追踪

来源: src/services/formatting/formatting.ts230-237 src/services/formatting/formatting.ts465-487 src/services/formatting/formatting.ts489-582 tests/cases/fourslash/formattingOptionsChange.ts1-45

与语言服务的集成

格式化系统与 TypeScript 语言服务集成,为编辑器和 IDE 提供格式化功能

来源: src/services/formatting/formatting.ts159-247

用户可配置设置

格式化系统的行为可以通过 FormatCodeSettings 接口进行自定义,其中包含的选项有:

设置描述
insertSpaceAfterCommaDelimiter逗号后插入空格
insertSpaceAfterSemicolonInForStatementsfor 语句中的分号后插入空格
insertSpaceBeforeAndAfterBinaryOperators二元运算符前后插入空格
insertSpaceAfterKeywordsInControlFlowStatements控制流语句中的关键字后插入空格
insertSpaceAfterFunctionKeywordForAnonymousFunctions匿名函数的 function 关键字后插入空格
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis非空括号的开括号后和闭括号前插入空格
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets非空方括号的开括号后和闭括号前插入空格
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces非空花括号的开括号后和闭括号前插入空格
insertSpaceAfterOpeningAndBeforeClosingEmptyBraces空花括号的开括号后和闭括号前插入空格
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces模板字符串花括号的开括号后和闭括号前插入空格
insertSpaceAfterTypeAssertion类型断言后插入空格
placeOpenBraceOnNewLineForFunctions函数开花括号换行
placeOpenBraceOnNewLineForControlBlocks控制块开花括号换行

来源: src/services/formatting/rules.ts296-342 tests/cases/fourslash/formattingOptionsChange.ts1-45