0
# AST Processing
1
2
TypeScript compiler transforms for collecting module information and performing tree-shaking operations on TypeScript abstract syntax trees.
3
4
## Capabilities
5
6
### collect Function
7
8
TypeScript compiler transform that builds the module dependency graph by analyzing imports, exports, and declarations in TypeScript source files.
9
10
```javascript { .api }
11
/**
12
* Collects module information from TypeScript AST nodes
13
* First phase transform that builds the dependency graph
14
* @param moduleGraph - Module graph to populate
15
* @param context - TypeScript transform context
16
* @param sourceFile - TypeScript source file AST node
17
* @returns Modified AST with synthetic imports for import types
18
*/
19
function collect(
20
moduleGraph: TSModuleGraph,
21
context: any,
22
sourceFile: any
23
): any;
24
```
25
26
**Collection Process:**
27
28
The collect function performs the following operations:
29
30
1. **Module Declaration Handling**: Processes nested module declarations and maintains module hierarchy
31
2. **Import Analysis**: Extracts all import statements including named, default, and namespace imports
32
3. **Export Analysis**: Collects export declarations, re-exports, and export assignments
33
4. **Declaration Processing**: Records all type declarations, interfaces, classes, functions, and variables
34
5. **Import Type Transformation**: Converts TypeScript import types to regular type references with synthetic imports
35
36
**Usage Example:**
37
38
```javascript
39
// Used as TypeScript compiler transform
40
const emitResult = program.emit(undefined, undefined, undefined, true, {
41
afterDeclarations: [
42
context => sourceFile => {
43
return collect(moduleGraph, context, sourceFile);
44
}
45
]
46
});
47
```
48
49
### shake Function
50
51
TypeScript compiler transform that removes unused types and renames symbols while flattening module declarations.
52
53
```javascript { .api }
54
/**
55
* Performs tree-shaking and symbol renaming on TypeScript AST
56
* Second phase transform that optimizes the declaration output
57
* @param moduleGraph - Module graph with usage information
58
* @param context - TypeScript transform context
59
* @param sourceFile - TypeScript source file AST node
60
* @returns Optimized AST with unused types removed and symbols renamed
61
*/
62
function shake(
63
moduleGraph: TSModuleGraph,
64
context: any,
65
sourceFile: any
66
): any;
67
```
68
69
**Tree-shaking Process:**
70
71
The shake function performs these optimizations:
72
73
1. **Usage Propagation**: Calls `moduleGraph.propagate()` to determine which types are used
74
2. **Import Hoisting**: Moves all import statements to the top level of the output
75
3. **Module Flattening**: Flattens nested module declarations into the top-level scope
76
4. **Declaration Filtering**: Removes unused type declarations, interfaces, and functions
77
5. **Symbol Renaming**: Updates all references to use renamed symbols
78
6. **Export Optimization**: Removes internal exports and preserves only public API exports
79
7. **Modifier Management**: Adds `declare` keywords for ambient declarations
80
81
### generateImports Function
82
83
Internal helper function used by the shake transform to create optimized import statements at the top of the output.
84
85
```javascript { .api }
86
/**
87
* Generates import statements for all external dependencies
88
* Called internally by shake function to hoist imports to the top
89
* @param factory - TypeScript node factory for creating AST nodes
90
* @param moduleGraph - Module graph containing import information
91
* @returns Array of ImportDeclaration AST nodes for external modules
92
*/
93
function generateImports(factory: any, moduleGraph: TSModuleGraph): any[];
94
```
95
96
**Import Generation Process:**
97
98
1. **External Import Collection**: Gets all imports to external modules via `moduleGraph.getAllImports()`
99
2. **Import Type Categorization**: Separates default, namespace, and named imports
100
3. **Import Statement Creation**: Uses compatibility wrappers to create version-appropriate import nodes
101
4. **Deduplication**: Combines multiple imports from the same module into single statements
102
103
**Usage Example:**
104
105
```javascript
106
// Used as TypeScript compiler transform
107
const emitResult = program.emit(undefined, undefined, undefined, true, {
108
afterDeclarations: [
109
// First collect phase
110
context => sourceFile => collect(moduleGraph, context, sourceFile),
111
// Then shake phase
112
context => sourceFile => shake(moduleGraph, context, sourceFile)
113
]
114
});
115
```
116
117
## AST Node Processing
118
119
### Import Statement Processing
120
121
The collect function handles various import patterns:
122
123
```typescript
124
// Named imports
125
import { Button, Dialog } from './components';
126
127
// Default imports
128
import React from 'react';
129
130
// Namespace imports
131
import * as utils from './utils';
132
133
// Mixed imports
134
import React, { Component } from 'react';
135
```
136
137
Each import type is processed and stored in the module's import map with appropriate specifier and imported name tracking.
138
139
### Export Statement Processing
140
141
The collect function handles export patterns:
142
143
```typescript
144
// Named exports
145
export { Button } from './button';
146
export function createDialog() { }
147
148
// Default exports
149
export default class App { }
150
151
// Re-exports
152
export * from './components';
153
154
// Export assignments
155
export = SomeValue;
156
```
157
158
### Declaration Processing
159
160
Both functions process TypeScript declarations:
161
162
- **Type Aliases**: `type MyType = string`
163
- **Interfaces**: `interface User { name: string }`
164
- **Classes**: `class Component { }`
165
- **Functions**: `function helper() { }`
166
- **Enums**: `enum Status { Active }`
167
- **Variables**: `const config = { }`
168
169
### Import Type Transformation
170
171
The collect function converts TypeScript import types to regular imports:
172
173
```typescript
174
// Before: import type syntax
175
type ReactElement = import('react').ReactElement;
176
177
// After: regular import with synthetic identifier
178
import { ReactElement as $$parcel$import$0 } from 'react';
179
type ReactElement = $$parcel$import$0;
180
```
181
182
## AST Visitor Patterns
183
184
### Module Hierarchy Tracking
185
186
Both functions maintain a module stack to handle nested module declarations:
187
188
```javascript
189
const moduleStack = [];
190
let currentModule = null;
191
192
// Push/pop modules as we enter/exit module declarations
193
if (ts.isModuleDeclaration(node)) {
194
moduleStack.push(currentModule);
195
currentModule = new TSModule();
196
}
197
```
198
199
### Symbol Reference Resolution
200
201
The shake function resolves qualified names and updates references:
202
203
```typescript
204
// Before: qualified reference
205
namespace.SubType
206
207
// After: direct reference (if namespace is imported)
208
ImportedSubType
209
```
210
211
### Private Member Filtering
212
213
The shake function removes private class members from declaration output:
214
215
```typescript
216
class MyClass {
217
public publicMethod() { } // Kept
218
private privateMethod() { } // Removed
219
}
220
```
221
222
## Utility Functions
223
224
Helper functions for AST node analysis and processing.
225
226
```javascript { .api }
227
/**
228
* Extracts the exported name from a TypeScript declaration node
229
* @param node - TypeScript AST node (declaration with potential modifiers)
230
* @returns Export name ('default' for default exports, symbol name for named exports, null if not exported)
231
*/
232
function getExportedName(node: any): string | null;
233
234
/**
235
* Checks if an AST node is a TypeScript declaration that can be exported
236
* @param node - TypeScript AST node to check
237
* @returns True if node is a function, class, interface, enum, or type alias declaration
238
*/
239
function isDeclaration(node: any): boolean;
240
241
/**
242
* Internal helper that processes import type nodes to extract import information
243
* Used by collect transform to convert import() types to regular imports
244
* @param qualifier - EntityName qualifier from import type (optional)
245
* @param local - Local identifier name for the synthetic import
246
* @param factory - TypeScript node factory for creating AST nodes
247
* @returns Tuple of [importSpecifier, entityReference] for the transformed import
248
*/
249
function getImportName(
250
qualifier: any,
251
local: string,
252
factory: any
253
): [string, any];
254
```
255
256
**Usage Examples:**
257
258
```javascript
259
import { getExportedName, isDeclaration } from '@parcel/transformer-typescript-types';
260
261
// Check if node is exportable declaration
262
if (isDeclaration(node)) {
263
const exportName = getExportedName(node);
264
if (exportName) {
265
// Node is exported with name
266
currentModule.addExport(exportName, exportName);
267
}
268
}
269
270
// Process import types during collection
271
if (ts.isImportTypeNode(node)) {
272
let local = `$$parcel$import$${moduleGraph.syntheticImportCount++}`;
273
let [specifier, entity] = getImportName(node.qualifier, local, factory);
274
currentModule.addImport(local, node.argument.literal.text, specifier);
275
276
// Transform: import('react').JSX.Element → JSX.Element
277
// With synthetic import: import { JSX } from 'react'
278
return factory.createTypeReferenceNode(entity, node.typeArguments);
279
}
280
```
281
282
### Export Name Detection
283
284
The `getExportedName` function handles various export patterns:
285
286
- **Named exports**: `export function myFunc() {}` → `"myFunc"`
287
- **Default exports**: `export default class MyClass {}` → `"default"`
288
- **Non-exported**: `function helper() {}` → `null`
289
290
### Declaration Type Detection
291
292
The `isDeclaration` function identifies TypeScript declaration types that can be exported:
293
294
- Function declarations (`function`)
295
- Class declarations (`class`)
296
- Interface declarations (`interface`)
297
- Enum declarations (`enum`)
298
- Type alias declarations (`type`)