|
| 1 | +# How does TypeScript formatting work? |
| 2 | + |
| 3 | +To format code you need to have a formatting context and a sourcefile. The formatting context contains |
| 4 | +all user settings like tab size, newline character, etc. The sourcefile is self explanatory. |
| 5 | + |
| 6 | +The end result of formatting is represented by TextChange objects which hold the new string content, and |
| 7 | +the text to replace it with. |
| 8 | + |
| 9 | +```ts |
| 10 | +export interface TextChange { |
| 11 | + span: TextSpan; // start, length |
| 12 | + newText: string; |
| 13 | +} |
| 14 | +``` |
| 15 | + |
| 16 | +## Internals |
| 17 | + |
| 18 | +Most of the exposed APIs internally are `format*` and they all set up and configure `formatSpan` which could be considered the root call for formatting. Span in this case refers to the range of |
| 19 | +the sourcefile which should be formatted. |
| 20 | + |
| 21 | +The formatSpan then uses a scanner (either with or without JSX support) which starts at the highest |
| 22 | +node the covers the span of text and recurses down through the node's children. |
| 23 | + |
| 24 | +As it recurses, `processNode` is called on the children setting the indentation is decided and passed |
| 25 | +through into each of that node's children. |
| 26 | + |
| 27 | +The meat of formatting decisions is made via `processPair`, the pair here being the current node and the previous node. `processPair` which mutates the formatting context to represent the current place in the scanner and requests a set of rules which can be applied to the items via `createRulesMap`. |
| 28 | + |
| 29 | +There are a lot of rules, which you can find in [rules.ts](./rules.ts) each one has a left and right reference to nodes or token ranges and note of what action should be applied by the formatter. |
| 30 | + |
| 31 | +### Where is this used? |
| 32 | + |
| 33 | +The formatter is used mainly from the language service for formatting with an editor, but [services/textChanges.ts](/src/services/textChanges.ts) also uses this formatter when emitting code for quick fixes. |
| 34 | + |
| 35 | +The formatter is not exported publicly, and so all usage comes through the language server. |
| 36 | + |
| 37 | +### Sample code |
| 38 | + |
| 39 | +```ts |
| 40 | +const nonFormattedText = `[js source code]`; |
| 41 | +const sourceFile = createSourceFile("any file name", nonFormattedText, ScriptTarget.ESNext, /*setParentNodes*/ true, ScriptKind.JS); |
| 42 | +const changes = formatting.formatDocument(sourceFile, formatContext); |
| 43 | +``` |
0 commit comments