0
# Parser and AST
1
2
Core parsing functionality that converts TypeScript source code into Abstract Syntax Trees (AST). Essential for any tool that needs to analyze or manipulate TypeScript code.
3
4
## Capabilities
5
6
### Source File Creation
7
8
Creates a TypeScript AST from source code text.
9
10
```typescript { .api }
11
/**
12
* Parse source text into a TypeScript AST
13
* @param fileName - Name of the file (used for error reporting)
14
* @param sourceText - TypeScript source code to parse
15
* @param languageVersionOrOptions - Target language version or parsing options
16
* @param setParentNodes - Whether to set parent references on nodes (default: false)
17
* @param scriptKind - Type of script being parsed
18
* @returns Parsed source file AST
19
*/
20
function createSourceFile(
21
fileName: string,
22
sourceText: string,
23
languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions,
24
setParentNodes?: boolean,
25
scriptKind?: ScriptKind
26
): SourceFile;
27
28
interface CreateSourceFileOptions {
29
languageVersion: ScriptTarget;
30
impliedNodeFormat?: ResolutionMode;
31
setExternalModuleIndicator?: (file: SourceFile) => void;
32
jsDocParsingMode?: JSDocParsingMode;
33
}
34
35
enum ScriptTarget {
36
ES3 = 0,
37
ES5 = 1,
38
ES2015 = 2,
39
ES2016 = 3,
40
ES2017 = 4,
41
ES2018 = 5,
42
ES2019 = 6,
43
ES2020 = 7,
44
ES2021 = 8,
45
ES2022 = 9,
46
ESNext = 99,
47
Latest = ESNext
48
}
49
50
enum ScriptKind {
51
Unknown = 0,
52
JS = 1,
53
JSX = 2,
54
TS = 3,
55
TSX = 4,
56
External = 5,
57
JSON = 6,
58
Deferred = 7
59
}
60
61
enum ResolutionMode {
62
Imports = 0,
63
Require = 1
64
}
65
66
enum JSDocParsingMode {
67
ParseAll = 0,
68
ParseNone = 1,
69
ParseForTypeErrors = 2,
70
ParseForTypeInfo = 3
71
}
72
```
73
74
**Usage Examples:**
75
76
```typescript
77
import * as ts from "typescript";
78
79
// Parse a simple TypeScript file
80
const sourceFile = ts.createSourceFile(
81
"example.ts",
82
`
83
interface User {
84
name: string;
85
age: number;
86
}
87
88
function greet(user: User): string {
89
return \`Hello, \${user.name}!\`;
90
}
91
`,
92
ts.ScriptTarget.ES2020,
93
true // Set parent nodes for easier traversal
94
);
95
96
console.log(sourceFile.statements.length); // Number of top-level statements
97
```
98
99
### AST Traversal
100
101
Traverse and visit AST nodes using various patterns.
102
103
```typescript { .api }
104
/**
105
* Visit each child of an AST node
106
* @param node - AST node to traverse
107
* @param cbNode - Callback for individual nodes
108
* @param cbNodes - Optional callback for node arrays
109
* @returns Result from first successful callback
110
*/
111
function forEachChild<T>(
112
node: Node,
113
cbNode: (node: Node) => T | undefined,
114
cbNodes?: (nodes: NodeArray<Node>) => T | undefined
115
): T | undefined;
116
117
/**
118
* Recursively traverse AST with depth-first search
119
* @param node - Starting AST node
120
* @param cbNode - Callback for individual nodes
121
* @param cbNodes - Optional callback for node arrays
122
* @returns Result from first successful callback
123
*/
124
function forEachChildRecursively<T>(
125
node: Node,
126
cbNode: (node: Node) => T | undefined,
127
cbNodes?: (nodes: NodeArray<Node>) => T | undefined
128
): T | undefined;
129
130
/**
131
* Visit a single AST node with a visitor function
132
* @param node - Node to visit
133
* @param visitor - Visitor function
134
* @param test - Optional type guard test
135
* @param lift - Optional lifting function
136
* @returns Visited node or array
137
*/
138
function visitNode<T extends Node>(
139
node: T | undefined,
140
visitor: Visitor,
141
test?: (node: Node) => boolean,
142
lift?: (node: NodeArray<Node>) => T
143
): T;
144
145
/**
146
* Visit an array of AST nodes
147
* @param nodes - Array of nodes to visit
148
* @param visitor - Visitor function
149
* @param test - Optional type guard test
150
* @param start - Starting index
151
* @param count - Number of nodes to visit
152
* @returns Visited node array
153
*/
154
function visitNodes<T extends Node>(
155
nodes: NodeArray<T> | undefined,
156
visitor: Visitor,
157
test?: (node: Node) => boolean,
158
start?: number,
159
count?: number
160
): NodeArray<T>;
161
```
162
163
**Usage Examples:**
164
165
```typescript
166
import * as ts from "typescript";
167
168
const sourceFile = ts.createSourceFile(
169
"example.ts",
170
"function add(a: number, b: number): number { return a + b; }",
171
ts.ScriptTarget.Latest
172
);
173
174
// Find all identifiers in the AST
175
const identifiers: string[] = [];
176
function visit(node: ts.Node) {
177
if (ts.isIdentifier(node)) {
178
identifiers.push(node.text);
179
}
180
ts.forEachChild(node, visit);
181
}
182
visit(sourceFile);
183
console.log(identifiers); // ['add', 'a', 'number', 'b', 'number', 'number', 'a', 'b']
184
185
// Find function declarations
186
const functions: ts.FunctionDeclaration[] = [];
187
ts.forEachChild(sourceFile, (node) => {
188
if (ts.isFunctionDeclaration(node)) {
189
functions.push(node);
190
}
191
});
192
```
193
194
### Incremental Parsing
195
196
Update existing source files efficiently for editor scenarios.
197
198
```typescript { .api }
199
/**
200
* Incrementally update a source file with new text
201
* @param sourceFile - Existing source file
202
* @param newText - New source text
203
* @param textChangeRange - Range of text that changed
204
* @param aggressiveChecks - Whether to perform aggressive validation
205
* @returns Updated source file
206
*/
207
function updateSourceFile(
208
sourceFile: SourceFile,
209
newText: string,
210
textChangeRange: TextChangeRange,
211
aggressiveChecks?: boolean
212
): SourceFile;
213
214
interface TextChangeRange {
215
span: TextSpan;
216
newLength: number;
217
}
218
219
interface TextSpan {
220
start: number;
221
length: number;
222
}
223
```
224
225
### Module Detection
226
227
Determine module characteristics of source files.
228
229
```typescript { .api }
230
/**
231
* Check if a source file is an external module (has imports/exports)
232
* @param file - Source file to check
233
* @returns True if file is an external module
234
*/
235
function isExternalModule(file: SourceFile): boolean;
236
237
/**
238
* Check if a filename represents a declaration file
239
* @param fileName - File name to check
240
* @returns True if filename ends with .d.ts
241
*/
242
function isDeclarationFileName(fileName: string): boolean;
243
```
244
245
### JSON Parsing
246
247
Parse JSON with TypeScript-specific handling.
248
249
```typescript { .api }
250
/**
251
* Parse JSON text with TypeScript-specific error handling
252
* @param fileName - Name of JSON file
253
* @param sourceText - JSON source text
254
* @returns Parsed JSON source file
255
*/
256
function parseJsonText(fileName: string, sourceText: string): JsonSourceFile;
257
258
interface JsonSourceFile extends SourceFile {
259
statements: NodeArray<JsonObjectExpressionStatement>;
260
}
261
```
262
263
### JSDoc Parsing
264
265
Parse JSDoc type expressions for testing and analysis.
266
267
```typescript { .api }
268
/**
269
* Parse JSDoc type expressions for testing purposes
270
* @param content - JSDoc type expression content
271
* @param start - Starting position
272
* @param length - Length of content to parse
273
* @returns Parsed JSDoc type expression
274
*/
275
function parseJSDocTypeExpressionForTests(
276
content: string,
277
start?: number,
278
length?: number
279
): { jsDocTypeExpression: JSDocTypeExpression; diagnostics: Diagnostic[] };
280
```
281
282
## Types
283
284
### Core Node Types
285
286
```typescript { .api }
287
interface Node {
288
kind: SyntaxKind;
289
flags: NodeFlags;
290
pos: number;
291
end: number;
292
parent: Node;
293
}
294
295
interface SourceFile extends Declaration {
296
kind: SyntaxKind.SourceFile;
297
statements: NodeArray<Statement>;
298
endOfFileToken: Token<SyntaxKind.EndOfFileToken>;
299
fileName: string;
300
text: string;
301
languageVersion: ScriptTarget;
302
scriptKind: ScriptKind;
303
isDeclarationFile: boolean;
304
hasNoDefaultLib: boolean;
305
externalModuleIndicator?: Node;
306
}
307
308
interface Statement extends Node {
309
_statementBrand: any;
310
}
311
312
interface Expression extends Node {
313
_expressionBrand: any;
314
}
315
316
interface Declaration extends Node {
317
_declarationBrand: any;
318
}
319
320
interface Identifier extends Declaration {
321
kind: SyntaxKind.Identifier;
322
text: string;
323
originalKeywordKind: SyntaxKind;
324
}
325
```
326
327
### Node Arrays
328
329
```typescript { .api }
330
interface NodeArray<T extends Node> extends ReadonlyArray<T> {
331
pos: number;
332
end: number;
333
hasTrailingComma: boolean;
334
}
335
336
/**
337
* Create a node array from elements
338
* @param elements - Array elements
339
* @param hasTrailingComma - Whether array has trailing comma
340
* @returns Node array
341
*/
342
function createNodeArray<T extends Node>(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray<T>;
343
```
344
345
### Scanner API
346
347
Create and use lexical scanners for tokenization.
348
349
```typescript { .api }
350
/**
351
* Create a lexical scanner for tokenizing TypeScript source
352
* @param languageVersion - Target language version
353
* @param skipTrivia - Whether to skip whitespace and comments
354
* @param languageVariant - Language variant (TypeScript, JSX, etc.)
355
* @param textInitial - Initial text to scan
356
* @param onError - Error reporting callback
357
* @param start - Starting position
358
* @param length - Length to scan
359
* @returns Scanner instance
360
*/
361
function createScanner(
362
languageVersion: ScriptTarget,
363
skipTrivia: boolean,
364
languageVariant?: LanguageVariant,
365
textInitial?: string,
366
onError?: ErrorCallback,
367
start?: number,
368
length?: number
369
): Scanner;
370
371
interface Scanner {
372
/** Get next token */
373
scan(): SyntaxKind;
374
375
/** Get current token kind */
376
getToken(): SyntaxKind;
377
378
/** Get current token position */
379
getTokenPos(): number;
380
381
/** Get current text position */
382
getTextPos(): number;
383
384
/** Get text of current token */
385
getTokenText(): string;
386
387
/** Get numeric value of token */
388
getTokenValue(): string;
389
390
/** Check if token has extended unicode escape */
391
hasUnicodeEscape(): boolean;
392
393
/** Check if token has extended unicode escape */
394
hasExtendedUnicodeEscape(): boolean;
395
396
/** Check if preceding line break */
397
hasPrecedingLineBreak(): boolean;
398
399
/** Set text to scan */
400
setText(text: string | undefined, start?: number, length?: number): void;
401
402
/** Set text position */
403
setTextPos(textPos: number): void;
404
405
/** Look ahead for next token */
406
lookAhead<T>(callback: () => T): T;
407
408
/** Scan range of text */
409
scanRange<T>(start: number, length: number, callback: () => T): T;
410
411
/** Try scan */
412
tryScan<T>(callback: () => T): T;
413
}
414
415
/**
416
* Check if character can start an identifier
417
* @param ch - Character code to check
418
* @param languageVersion - Language version context
419
* @returns True if character can start identifier
420
*/
421
function isIdentifierStart(ch: number, languageVersion?: ScriptTarget): boolean;
422
423
/**
424
* Check if character can be part of an identifier
425
* @param ch - Character code to check
426
* @param languageVersion - Language version context
427
* @returns True if character can be part of identifier
428
*/
429
function isIdentifierPart(ch: number, languageVersion?: ScriptTarget): boolean;
430
431
/**
432
* Check if character is whitespace-like
433
* @param ch - Character code to check
434
* @returns True if whitespace-like
435
*/
436
function isWhiteSpaceLike(ch: number): boolean;
437
438
/**
439
* Check if character is a line break
440
* @param ch - Character code to check
441
* @returns True if line break
442
*/
443
function isLineBreak(ch: number): boolean;
444
```
445
446
### Text Ranges
447
448
```typescript { .api }
449
interface TextRange {
450
pos: number;
451
end: number;
452
}
453
454
interface ReadonlyTextRange {
455
readonly pos: number;
456
readonly end: number;
457
}
458
459
/**
460
* Create text span from start and length
461
* @param start - Starting position
462
* @param length - Length of span
463
* @returns Text span object
464
*/
465
function createTextSpan(start: number, length: number): TextSpan;
466
467
/**
468
* Create text change range
469
* @param span - Text span that changed
470
* @param newLength - New length after change
471
* @returns Text change range
472
*/
473
function createTextChangeRange(span: TextSpan, newLength: number): TextChangeRange;
474
```