ripple 0.3.13 → 0.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/package.json +5 -30
- package/src/runtime/array.js +38 -38
- package/src/runtime/create-subscriber.js +2 -2
- package/src/runtime/internal/client/bindings.js +4 -6
- package/src/runtime/internal/client/events.js +8 -3
- package/src/runtime/internal/client/hmr.js +5 -17
- package/src/runtime/internal/client/runtime.js +1 -0
- package/src/runtime/internal/server/blocks.js +7 -9
- package/src/runtime/internal/server/index.js +14 -22
- package/src/runtime/media-query.js +34 -33
- package/src/runtime/object.js +7 -10
- package/src/runtime/proxy.js +2 -3
- package/src/runtime/reactive-value.js +23 -21
- package/src/utils/ast.js +1 -1
- package/src/utils/attributes.js +43 -0
- package/src/utils/builders.js +2 -2
- package/tests/client/basic/basic.components.test.rsrx +103 -1
- package/tests/client/basic/basic.errors.test.rsrx +1 -1
- package/tests/client/basic/basic.styling.test.rsrx +1 -1
- package/tests/client/compiler/compiler.assignments.test.rsrx +1 -1
- package/tests/client/compiler/compiler.attributes.test.rsrx +1 -1
- package/tests/client/compiler/compiler.basic.test.rsrx +51 -14
- package/tests/client/compiler/compiler.tracked-access.test.rsrx +1 -1
- package/tests/client/compiler/compiler.try-in-function.test.rsrx +1 -1
- package/tests/client/compiler/compiler.typescript.test.rsrx +1 -1
- package/tests/client/css/global-additional-cases.test.rsrx +1 -1
- package/tests/client/css/global-advanced-selectors.test.rsrx +1 -1
- package/tests/client/css/global-at-rules.test.rsrx +1 -1
- package/tests/client/css/global-basic.test.rsrx +1 -1
- package/tests/client/css/global-classes-ids.test.rsrx +1 -1
- package/tests/client/css/global-combinators.test.rsrx +1 -1
- package/tests/client/css/global-complex-nesting.test.rsrx +1 -1
- package/tests/client/css/global-edge-cases.test.rsrx +1 -1
- package/tests/client/css/global-keyframes.test.rsrx +1 -1
- package/tests/client/css/global-nested.test.rsrx +1 -1
- package/tests/client/css/global-pseudo.test.rsrx +1 -1
- package/tests/client/css/global-scoping.test.rsrx +1 -1
- package/tests/client/css/style-identifier.test.rsrx +1 -1
- package/tests/client/return.test.rsrx +1 -1
- package/tests/hydration/build-components.js +1 -1
- package/tests/server/basic.components.test.rsrx +114 -0
- package/tests/server/compiler.test.rsrx +38 -1
- package/tests/server/style-identifier.test.rsrx +1 -1
- package/tests/setup-server.js +1 -1
- package/tests/utils/compiler-compat-config.test.js +1 -1
- package/types/index.d.ts +1 -1
- package/src/compiler/comment-utils.js +0 -91
- package/src/compiler/errors.js +0 -77
- package/src/compiler/identifier-utils.js +0 -80
- package/src/compiler/index.d.ts +0 -127
- package/src/compiler/index.js +0 -89
- package/src/compiler/phases/1-parse/index.js +0 -3007
- package/src/compiler/phases/1-parse/style.js +0 -704
- package/src/compiler/phases/2-analyze/css-analyze.js +0 -160
- package/src/compiler/phases/2-analyze/index.js +0 -2208
- package/src/compiler/phases/2-analyze/prune.js +0 -1131
- package/src/compiler/phases/2-analyze/validation.js +0 -168
- package/src/compiler/phases/3-transform/client/index.js +0 -5264
- package/src/compiler/phases/3-transform/segments.js +0 -2125
- package/src/compiler/phases/3-transform/server/index.js +0 -1749
- package/src/compiler/phases/3-transform/stylesheet.js +0 -545
- package/src/compiler/scope.js +0 -476
- package/src/compiler/source-map-utils.js +0 -358
- package/src/compiler/types/acorn.d.ts +0 -11
- package/src/compiler/types/estree-jsx.d.ts +0 -11
- package/src/compiler/types/estree.d.ts +0 -11
- package/src/compiler/types/index.d.ts +0 -1411
- package/src/compiler/types/parse.d.ts +0 -1723
- package/src/compiler/utils.js +0 -1258
|
@@ -1,2125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
@import * as AST from 'estree';
|
|
3
|
-
@import * as ESTreeJSX from 'estree-jsx';
|
|
4
|
-
@import { DocumentHighlightKind } from 'vscode-languageserver-types';
|
|
5
|
-
@import { RawSourceMap } from 'source-map';
|
|
6
|
-
@import {
|
|
7
|
-
CustomMappingData,
|
|
8
|
-
PluginActionOverrides,
|
|
9
|
-
CodeMapping,
|
|
10
|
-
VolarMappingsResult,
|
|
11
|
-
} from 'ripple/compiler';
|
|
12
|
-
@import { PostProcessingChanges } from './client/index.js';
|
|
13
|
-
@import { CodeMapping as VolarCodeMapping } from '@volar/language-core';
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
@typedef {{
|
|
18
|
-
start: number,
|
|
19
|
-
end: number,
|
|
20
|
-
content: string,
|
|
21
|
-
id: string,
|
|
22
|
-
}} CssSourceRegion;
|
|
23
|
-
@typedef {{
|
|
24
|
-
source: string | null | undefined;
|
|
25
|
-
generated: string;
|
|
26
|
-
loc: AST.SourceLocation;
|
|
27
|
-
metadata: PluginActionOverrides;
|
|
28
|
-
end_loc?: AST.SourceLocation;
|
|
29
|
-
mappingData?: Partial<VolarCodeMapping['data']>;
|
|
30
|
-
}} Token;
|
|
31
|
-
@typedef {{
|
|
32
|
-
name: string,
|
|
33
|
-
line: number,
|
|
34
|
-
column: number,
|
|
35
|
-
offset: number,
|
|
36
|
-
length: number,
|
|
37
|
-
sourceOffset: number,
|
|
38
|
-
}} TokenClass
|
|
39
|
-
@typedef {Map<string, AST.Element['metadata']['css']>} CssElementInfo
|
|
40
|
-
*/
|
|
41
|
-
|
|
42
|
-
import { walk } from 'zimmerframe';
|
|
43
|
-
import {
|
|
44
|
-
build_src_to_gen_map,
|
|
45
|
-
get_generated_position,
|
|
46
|
-
offset_to_line_col,
|
|
47
|
-
loc_to_offset,
|
|
48
|
-
mapping_data,
|
|
49
|
-
mapping_data_verify_only,
|
|
50
|
-
mapping_data_verify_complete,
|
|
51
|
-
build_line_offsets,
|
|
52
|
-
get_mapping_from_node,
|
|
53
|
-
} from '../../source-map-utils.js';
|
|
54
|
-
|
|
55
|
-
const LABEL_TO_COMPONENT_REPLACE_REGEX = /(function|\((property|method)\))/;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* @param {string} content
|
|
59
|
-
* @returns {string}
|
|
60
|
-
*/
|
|
61
|
-
function replace_label_to_component(content) {
|
|
62
|
-
return content.replace(LABEL_TO_COMPONENT_REPLACE_REGEX, (_, fn, kind) => {
|
|
63
|
-
if (fn === 'function') return 'component';
|
|
64
|
-
return `(component ${kind})`;
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* @param {string} [hash]
|
|
70
|
-
* @param {string} [fallback]
|
|
71
|
-
* @returns `style-${hash | fallback}`
|
|
72
|
-
*/
|
|
73
|
-
function get_style_region_id(hash, fallback) {
|
|
74
|
-
return `style-${hash || fallback}`;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Extract CSS source regions from style elements in the AST
|
|
79
|
-
* @param {AST.Node} ast - The parsed AST
|
|
80
|
-
* @param {number[]} src_line_offsets
|
|
81
|
-
* @param {{
|
|
82
|
-
* regions: CssSourceRegion[],
|
|
83
|
-
* css_element_info: CssElementInfo,
|
|
84
|
-
* }} param2
|
|
85
|
-
* @returns {void}
|
|
86
|
-
*/
|
|
87
|
-
function visit_source_ast(ast, src_line_offsets, { regions, css_element_info }) {
|
|
88
|
-
let region_id = 0;
|
|
89
|
-
walk(ast, null, {
|
|
90
|
-
Element(node, context) {
|
|
91
|
-
// Check if this is a style element with CSS content
|
|
92
|
-
if (node.id?.type === 'Identifier' && node.id?.name === 'style' && node.css) {
|
|
93
|
-
const openLoc = /** @type {ESTreeJSX.JSXOpeningElement & AST.NodeWithLocation} */ (
|
|
94
|
-
node.openingElement
|
|
95
|
-
).loc;
|
|
96
|
-
const cssStart = loc_to_offset(openLoc.end.line, openLoc.end.column, src_line_offsets);
|
|
97
|
-
|
|
98
|
-
const closeLoc = /** @type {ESTreeJSX.JSXClosingElement & AST.NodeWithLocation} */ (
|
|
99
|
-
node.closingElement
|
|
100
|
-
).loc;
|
|
101
|
-
const cssEnd = loc_to_offset(closeLoc.start.line, closeLoc.start.column, src_line_offsets);
|
|
102
|
-
|
|
103
|
-
regions.push({
|
|
104
|
-
start: cssStart,
|
|
105
|
-
end: cssEnd,
|
|
106
|
-
content: node.css,
|
|
107
|
-
id: get_style_region_id(node.metadata.styleScopeHash, `head-${region_id}`),
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
context.next();
|
|
112
|
-
},
|
|
113
|
-
Attribute(node, context) {
|
|
114
|
-
const element = context.path?.find((n) => n.type === 'Element');
|
|
115
|
-
if (element?.metadata?.css?.scopedClasses) {
|
|
116
|
-
// we don't need to check is_element_dom_element(node)
|
|
117
|
-
// since scopedClasses are added during pruning only to DOM elements
|
|
118
|
-
const css = element.metadata.css;
|
|
119
|
-
const { line, column } = node.value?.loc?.start ?? {};
|
|
120
|
-
|
|
121
|
-
if (line === undefined || column === undefined) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
css_element_info.set(`${line}:${column}`, css);
|
|
126
|
-
}
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Extract individual class names and their offsets from class attribute values
|
|
133
|
-
* Handles: "foo bar", { foo: true }, ['foo', { bar: true }], etc.
|
|
134
|
-
*
|
|
135
|
-
* @param {AST.Node} node - The attribute value node
|
|
136
|
-
* @param {ReturnType<typeof build_src_to_gen_map>[0]} src_to_gen_map
|
|
137
|
-
* @param {number[]} gen_line_offsets
|
|
138
|
-
* @param {number[]} src_line_offsets
|
|
139
|
-
* @returns {TokenClass[]}
|
|
140
|
-
*/
|
|
141
|
-
function extract_classes(node, src_to_gen_map, gen_line_offsets, src_line_offsets) {
|
|
142
|
-
/** @type {TokenClass[]} */
|
|
143
|
-
const classes = [];
|
|
144
|
-
|
|
145
|
-
switch (node.type) {
|
|
146
|
-
case 'Literal': {
|
|
147
|
-
// Static: class="foo bar baz"
|
|
148
|
-
|
|
149
|
-
const content = node.raw ?? '';
|
|
150
|
-
let text = content;
|
|
151
|
-
let textOffset = 0;
|
|
152
|
-
|
|
153
|
-
// Remove quotes
|
|
154
|
-
if (
|
|
155
|
-
(content.startsWith(`'`) && content.endsWith(`'`)) ||
|
|
156
|
-
(content.startsWith(`"`) && content.endsWith(`"`)) ||
|
|
157
|
-
(content.startsWith('`') && content.endsWith('`'))
|
|
158
|
-
) {
|
|
159
|
-
text = content.slice(1, -1);
|
|
160
|
-
textOffset = 1;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Split by whitespace
|
|
164
|
-
const classNames = text.split(/\s+/).filter((c) => c.length > 0);
|
|
165
|
-
const nodeSrcStart = /** @type {AST.Position} */ (node.loc?.start);
|
|
166
|
-
|
|
167
|
-
let currentPos = 0;
|
|
168
|
-
const nodeGenStart = get_generated_position(
|
|
169
|
-
nodeSrcStart.line,
|
|
170
|
-
nodeSrcStart.column,
|
|
171
|
-
src_to_gen_map,
|
|
172
|
-
);
|
|
173
|
-
const offset = loc_to_offset(nodeGenStart.line, nodeGenStart.column, gen_line_offsets);
|
|
174
|
-
const sourceOffset = loc_to_offset(nodeSrcStart.line, nodeSrcStart.column, src_line_offsets);
|
|
175
|
-
|
|
176
|
-
for (const name of classNames) {
|
|
177
|
-
const classStart = text.indexOf(name, currentPos);
|
|
178
|
-
const classOffset = offset + textOffset + classStart;
|
|
179
|
-
const classSourceOffset = sourceOffset + textOffset + classStart;
|
|
180
|
-
const { line, column } = offset_to_line_col(classOffset, gen_line_offsets);
|
|
181
|
-
|
|
182
|
-
classes.push({
|
|
183
|
-
name,
|
|
184
|
-
line,
|
|
185
|
-
column,
|
|
186
|
-
offset: classOffset,
|
|
187
|
-
length: name.length,
|
|
188
|
-
sourceOffset: classSourceOffset,
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
currentPos = classStart + name.length;
|
|
192
|
-
}
|
|
193
|
-
break;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
case 'ObjectExpression': {
|
|
197
|
-
// Dynamic: class={{ foo: true, bar: @show }}
|
|
198
|
-
for (const prop of node.properties) {
|
|
199
|
-
if (prop.type === 'Property' && prop.key) {
|
|
200
|
-
const key = prop.key;
|
|
201
|
-
if (key.type === 'Identifier' && key.name && key.loc) {
|
|
202
|
-
const nodeSrcStart = /** @type {AST.Position} */ (key.loc?.start);
|
|
203
|
-
const nodeGenStart = get_generated_position(
|
|
204
|
-
nodeSrcStart.line,
|
|
205
|
-
nodeSrcStart.column,
|
|
206
|
-
src_to_gen_map,
|
|
207
|
-
);
|
|
208
|
-
const offset = loc_to_offset(nodeGenStart.line, nodeGenStart.column, gen_line_offsets);
|
|
209
|
-
const sourceOffset = loc_to_offset(
|
|
210
|
-
nodeSrcStart.line,
|
|
211
|
-
nodeSrcStart.column,
|
|
212
|
-
src_line_offsets,
|
|
213
|
-
);
|
|
214
|
-
const { line, column } = offset_to_line_col(offset, gen_line_offsets);
|
|
215
|
-
|
|
216
|
-
classes.push({
|
|
217
|
-
name: key.name,
|
|
218
|
-
line,
|
|
219
|
-
column,
|
|
220
|
-
offset,
|
|
221
|
-
length: key.name.length,
|
|
222
|
-
sourceOffset,
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
break;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
case 'ArrayExpression': {
|
|
231
|
-
// Dynamic: class={['foo', { bar: true }]}
|
|
232
|
-
for (const el of node.elements) {
|
|
233
|
-
if (el) {
|
|
234
|
-
classes.push(...extract_classes(el, src_to_gen_map, gen_line_offsets, src_line_offsets));
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
break;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
case 'ConditionalExpression': {
|
|
241
|
-
// Conditional: class={@show ? 'active' : 'inactive'}
|
|
242
|
-
if (node.consequent) {
|
|
243
|
-
classes.push(
|
|
244
|
-
...extract_classes(node.consequent, src_to_gen_map, gen_line_offsets, src_line_offsets),
|
|
245
|
-
);
|
|
246
|
-
}
|
|
247
|
-
if (node.alternate) {
|
|
248
|
-
classes.push(
|
|
249
|
-
...extract_classes(node.alternate, src_to_gen_map, gen_line_offsets, src_line_offsets),
|
|
250
|
-
);
|
|
251
|
-
}
|
|
252
|
-
break;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
case 'LogicalExpression': {
|
|
256
|
-
// Logical: class={[@show && 'active']}
|
|
257
|
-
if (node.operator === '&&' && node.right) {
|
|
258
|
-
classes.push(
|
|
259
|
-
...extract_classes(node.right, src_to_gen_map, gen_line_offsets, src_line_offsets),
|
|
260
|
-
);
|
|
261
|
-
} else if (node.operator === '||') {
|
|
262
|
-
if (node.left) {
|
|
263
|
-
classes.push(
|
|
264
|
-
...extract_classes(node.left, src_to_gen_map, gen_line_offsets, src_line_offsets),
|
|
265
|
-
);
|
|
266
|
-
}
|
|
267
|
-
if (node.right) {
|
|
268
|
-
classes.push(
|
|
269
|
-
...extract_classes(node.right, src_to_gen_map, gen_line_offsets, src_line_offsets),
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
break;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
return classes;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Create Volar mappings by walking the transformed AST
|
|
282
|
-
* @param {AST.Node} ast - The transformed AST
|
|
283
|
-
* @param {AST.Node} ast_from_source - The original AST from source
|
|
284
|
-
* @param {string} source - Original source code
|
|
285
|
-
* @param {string} generated_code - Generated code (returned in output, not used for searching)
|
|
286
|
-
* @param {RawSourceMap} source_map - Esrap source map for accurate position lookup
|
|
287
|
-
* @param {PostProcessingChanges } post_processing_changes - Optional post-processing changes
|
|
288
|
-
* @param {number[]} line_offsets - Pre-computed line offsets array for generated code
|
|
289
|
-
* @returns {Omit<VolarMappingsResult, 'errors'>}
|
|
290
|
-
*/
|
|
291
|
-
export function convert_source_map_to_mappings(
|
|
292
|
-
ast,
|
|
293
|
-
ast_from_source,
|
|
294
|
-
source,
|
|
295
|
-
generated_code,
|
|
296
|
-
source_map,
|
|
297
|
-
post_processing_changes,
|
|
298
|
-
line_offsets,
|
|
299
|
-
) {
|
|
300
|
-
/** @type {CodeMapping[]} */
|
|
301
|
-
const mappings = [];
|
|
302
|
-
let isImportDeclarationPresent = false;
|
|
303
|
-
|
|
304
|
-
const src_line_offsets = build_line_offsets(source);
|
|
305
|
-
const gen_line_offsets = build_line_offsets(generated_code);
|
|
306
|
-
|
|
307
|
-
const [src_to_gen_map] = build_src_to_gen_map(
|
|
308
|
-
source_map,
|
|
309
|
-
post_processing_changes,
|
|
310
|
-
line_offsets,
|
|
311
|
-
generated_code,
|
|
312
|
-
);
|
|
313
|
-
|
|
314
|
-
/** @type {Token[]} */
|
|
315
|
-
const tokens = [];
|
|
316
|
-
/** @type {CssSourceRegion[]} */
|
|
317
|
-
const css_regions = [];
|
|
318
|
-
/** @type {CssElementInfo} */
|
|
319
|
-
const css_element_info = new Map();
|
|
320
|
-
|
|
321
|
-
visit_source_ast(ast_from_source, src_line_offsets, {
|
|
322
|
-
regions: css_regions,
|
|
323
|
-
css_element_info,
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Needed for a mapping that includes the computed brackets for diagnostics
|
|
328
|
-
* @param {AST.MethodDefinition | AST.Property} node
|
|
329
|
-
* @param {CodeMapping[]} mappings
|
|
330
|
-
* @returns {void}
|
|
331
|
-
*/
|
|
332
|
-
function set_bracket_computed_mapping(node, mappings) {
|
|
333
|
-
if (node.loc) {
|
|
334
|
-
const key = /** @type {typeof node.key & AST.NodeWithLocation} */ (node.key);
|
|
335
|
-
mappings.push(
|
|
336
|
-
get_mapping_from_node(
|
|
337
|
-
/** @type {AST.NodeWithLocation} */ ({
|
|
338
|
-
start: key.start - 1,
|
|
339
|
-
end: key.end + 1,
|
|
340
|
-
loc: {
|
|
341
|
-
start: { line: key.loc.start.line, column: key.loc.start.column - 1 },
|
|
342
|
-
end: { line: key.loc.end.line, column: key.loc.end.column + 1 },
|
|
343
|
-
},
|
|
344
|
-
}),
|
|
345
|
-
src_to_gen_map,
|
|
346
|
-
gen_line_offsets,
|
|
347
|
-
mapping_data_verify_only,
|
|
348
|
-
),
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* @typedef {AST.MethodDefinition & {value: {metadata: {is_component: true}}}} MethodIsComponent
|
|
355
|
-
* @typedef {AST.Property & {value: AST.FunctionExpression, method: true} & {value: {metadata: {is_component: true}}}} PropertyIsComponent
|
|
356
|
-
*/
|
|
357
|
-
|
|
358
|
-
/**
|
|
359
|
-
* Maps `component` to the identifier's location
|
|
360
|
-
* e.g. const obj = { component something() { } }
|
|
361
|
-
* since there is no function keyword in source maps
|
|
362
|
-
* @param {MethodIsComponent | PropertyIsComponent} node
|
|
363
|
-
* @returns {void}
|
|
364
|
-
*/
|
|
365
|
-
function set_component_mapping_to_name(node) {
|
|
366
|
-
if (node.key.loc) {
|
|
367
|
-
/** @type {CodeMapping} */
|
|
368
|
-
let mapping;
|
|
369
|
-
let start = /** @type {AST.NodeWithLocation} */ (node).start;
|
|
370
|
-
let length = 'component'.length;
|
|
371
|
-
|
|
372
|
-
if (node.value.type === 'FunctionExpression' && node.value.id) {
|
|
373
|
-
const id = /** @type {AST.Identifier & AST.NodeWithLocation} */ (node.value.id);
|
|
374
|
-
mapping = get_mapping_from_node(id, src_to_gen_map, gen_line_offsets);
|
|
375
|
-
} else {
|
|
376
|
-
// e.g. key is computed or literal
|
|
377
|
-
mapping = get_mapping_from_node(node.key, src_to_gen_map, gen_line_offsets);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// overwrite source start and length to point to 'component' keyword
|
|
381
|
-
mapping.sourceOffsets = [start];
|
|
382
|
-
mapping.lengths = [length];
|
|
383
|
-
mapping.data.customData.hover = replace_label_to_component;
|
|
384
|
-
|
|
385
|
-
mappings.push(mapping);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
/**
|
|
390
|
-
* @param {AST.Literal} node
|
|
391
|
-
* @param {boolean} [is_component]
|
|
392
|
-
*/
|
|
393
|
-
function handle_literal(node, is_component = false) {
|
|
394
|
-
if (node.loc) {
|
|
395
|
-
const mapping = get_mapping_from_node(node, src_to_gen_map, gen_line_offsets);
|
|
396
|
-
|
|
397
|
-
if (is_component) {
|
|
398
|
-
mapping.data.customData.hover = replace_label_to_component;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
mappings.push(mapping);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// We have to visit everything in generated order to maintain correct indices
|
|
406
|
-
|
|
407
|
-
walk(ast, null, {
|
|
408
|
-
_(node, { visit }) {
|
|
409
|
-
// Collect key node types: Identifiers, Literals, and JSX Elements
|
|
410
|
-
if (node.type === 'Identifier') {
|
|
411
|
-
// Only create mappings for identifiers with location info (from source)
|
|
412
|
-
// Synthesized identifiers (created by builders) don't have .loc and are skipped
|
|
413
|
-
if (node.name && node.loc) {
|
|
414
|
-
/** @type {Token} */
|
|
415
|
-
let token;
|
|
416
|
-
// Check if this identifier was changed in metadata (e.g., #Map -> RippleMap)
|
|
417
|
-
// Or if it was capitalized during transformation
|
|
418
|
-
if (node.metadata?.source_name) {
|
|
419
|
-
token = {
|
|
420
|
-
source: node.metadata.source_name,
|
|
421
|
-
generated: node.name,
|
|
422
|
-
loc: node.loc,
|
|
423
|
-
metadata: {},
|
|
424
|
-
};
|
|
425
|
-
} else {
|
|
426
|
-
token = {
|
|
427
|
-
source: node.name,
|
|
428
|
-
generated: node.name,
|
|
429
|
-
loc: node.loc,
|
|
430
|
-
metadata: {},
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
if (node.metadata?.is_component) {
|
|
435
|
-
// only if the node has a component as the parent
|
|
436
|
-
token.metadata.hover = replace_label_to_component;
|
|
437
|
-
}
|
|
438
|
-
tokens.push(token);
|
|
439
|
-
}
|
|
440
|
-
return; // Leaf node, don't traverse further
|
|
441
|
-
} else if (node.type === 'JSXIdentifier') {
|
|
442
|
-
// JSXIdentifiers can also be capitalized (for dynamic components)
|
|
443
|
-
if (node.loc && node.name) {
|
|
444
|
-
if (node.metadata?.is_capitalized) {
|
|
445
|
-
tokens.push({
|
|
446
|
-
source: node.metadata.source_name,
|
|
447
|
-
generated: node.name,
|
|
448
|
-
loc: node.loc,
|
|
449
|
-
metadata: {},
|
|
450
|
-
});
|
|
451
|
-
} else {
|
|
452
|
-
tokens.push({ source: node.name, generated: node.name, loc: node.loc, metadata: {} });
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
return; // Leaf node, don't traverse further
|
|
456
|
-
} else if (node.type === 'Literal') {
|
|
457
|
-
handle_literal(node);
|
|
458
|
-
return; // Leaf node, don't traverse further
|
|
459
|
-
} else if (node.type === 'ImportDeclaration') {
|
|
460
|
-
isImportDeclarationPresent = true;
|
|
461
|
-
|
|
462
|
-
// Add 'import' keyword token to anchor statement-level diagnostics
|
|
463
|
-
// And the last character of the statement (semicolon or closing brace)
|
|
464
|
-
// (e.g., when ALL imports are unused, TS reports on the whole statement)
|
|
465
|
-
// We only map the 'import' and the last character
|
|
466
|
-
// to avoid overlapping with individual specifier mappings
|
|
467
|
-
// which would interfere when only SOME imports are unused.
|
|
468
|
-
if (node.loc) {
|
|
469
|
-
tokens.push({
|
|
470
|
-
source: 'import',
|
|
471
|
-
generated: 'import',
|
|
472
|
-
loc: {
|
|
473
|
-
start: node.loc.start,
|
|
474
|
-
end: {
|
|
475
|
-
line: node.loc.start.line,
|
|
476
|
-
column: node.loc.start.column + 'import'.length,
|
|
477
|
-
},
|
|
478
|
-
},
|
|
479
|
-
metadata: {},
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
tokens.push({
|
|
483
|
-
source:
|
|
484
|
-
source[loc_to_offset(node.loc.end.line, node.loc.end.column - 1, src_line_offsets)],
|
|
485
|
-
// we always add `;' in the generated import
|
|
486
|
-
generated: ';',
|
|
487
|
-
loc: {
|
|
488
|
-
start: {
|
|
489
|
-
line: node.loc.end.line,
|
|
490
|
-
column: node.loc.end.column - 1,
|
|
491
|
-
},
|
|
492
|
-
end: node.loc.end,
|
|
493
|
-
},
|
|
494
|
-
metadata: {},
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
// Visit specifiers in source order
|
|
499
|
-
if (node.specifiers) {
|
|
500
|
-
for (const specifier of node.specifiers) {
|
|
501
|
-
visit(specifier);
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
visit(node.source);
|
|
505
|
-
return;
|
|
506
|
-
} else if (node.type === 'ImportSpecifier') {
|
|
507
|
-
// If local and imported are the same, only visit local to avoid duplicates
|
|
508
|
-
// Otherwise visit both in order
|
|
509
|
-
if (
|
|
510
|
-
node.imported &&
|
|
511
|
-
node.local &&
|
|
512
|
-
/** @type {AST.Identifier} */ (node.imported).name !== node.local.name
|
|
513
|
-
) {
|
|
514
|
-
visit(node.imported);
|
|
515
|
-
visit(node.local);
|
|
516
|
-
} else if (node.local) {
|
|
517
|
-
visit(node.local);
|
|
518
|
-
}
|
|
519
|
-
return;
|
|
520
|
-
} else if (
|
|
521
|
-
node.type === 'ImportDefaultSpecifier' ||
|
|
522
|
-
node.type === 'ImportNamespaceSpecifier'
|
|
523
|
-
) {
|
|
524
|
-
// Just visit local
|
|
525
|
-
if (node.local) {
|
|
526
|
-
visit(node.local);
|
|
527
|
-
}
|
|
528
|
-
return;
|
|
529
|
-
} else if (node.type === 'ExportSpecifier') {
|
|
530
|
-
// If local and exported are the same, only visit local to avoid duplicates
|
|
531
|
-
// Otherwise visit both in order
|
|
532
|
-
if (
|
|
533
|
-
node.local &&
|
|
534
|
-
node.exported &&
|
|
535
|
-
/** @type {AST.Identifier} */ (node.local).name !==
|
|
536
|
-
/** @type {AST.Identifier} */ (node.exported).name
|
|
537
|
-
) {
|
|
538
|
-
visit(node.local);
|
|
539
|
-
visit(node.exported);
|
|
540
|
-
} else if (node.local) {
|
|
541
|
-
visit(node.local);
|
|
542
|
-
}
|
|
543
|
-
return;
|
|
544
|
-
} else if (node.type === 'ExportNamedDeclaration') {
|
|
545
|
-
if (node.specifiers && node.specifiers.length > 0) {
|
|
546
|
-
for (const specifier of node.specifiers) {
|
|
547
|
-
visit(specifier);
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
if (node.declaration) {
|
|
551
|
-
// The declaration will be visited with proper ordering
|
|
552
|
-
visit(node.declaration);
|
|
553
|
-
}
|
|
554
|
-
return;
|
|
555
|
-
} else if (node.type === 'ExportDefaultDeclaration') {
|
|
556
|
-
// Visit the declaration
|
|
557
|
-
if (node.declaration) {
|
|
558
|
-
visit(/** @type {AST.Node} */ (node.declaration));
|
|
559
|
-
}
|
|
560
|
-
return;
|
|
561
|
-
} else if (node.type === 'ExportAllDeclaration') {
|
|
562
|
-
// Nothing to visit (just source string)
|
|
563
|
-
return;
|
|
564
|
-
} else if (node.type === 'JSXOpeningElement') {
|
|
565
|
-
// Visit name and attributes in source order
|
|
566
|
-
visit(node.name);
|
|
567
|
-
for (const attr of node.attributes) {
|
|
568
|
-
visit(attr);
|
|
569
|
-
}
|
|
570
|
-
return;
|
|
571
|
-
} else if (node.type === 'JSXClosingElement') {
|
|
572
|
-
visit(node.name);
|
|
573
|
-
return;
|
|
574
|
-
} else if (node.type === 'JSXAttribute') {
|
|
575
|
-
// Visit name and value in source order
|
|
576
|
-
// For shorthand attributes ({ count }), key and value are the same node, only visit once
|
|
577
|
-
if (node.shorthand) {
|
|
578
|
-
if (node.value) {
|
|
579
|
-
visit(node.value);
|
|
580
|
-
}
|
|
581
|
-
} else {
|
|
582
|
-
const attr =
|
|
583
|
-
node.name.name === 'class' && node.value?.type === 'JSXExpressionContainer'
|
|
584
|
-
? node.value.expression
|
|
585
|
-
: node.value;
|
|
586
|
-
|
|
587
|
-
const css = attr
|
|
588
|
-
? css_element_info.get(`${attr.loc?.start.line}:${attr.loc?.start.column}`)
|
|
589
|
-
: null;
|
|
590
|
-
|
|
591
|
-
if (attr && css) {
|
|
592
|
-
// Extract class names from the attribute value
|
|
593
|
-
const classes = extract_classes(
|
|
594
|
-
attr,
|
|
595
|
-
src_to_gen_map,
|
|
596
|
-
gen_line_offsets,
|
|
597
|
-
src_line_offsets,
|
|
598
|
-
);
|
|
599
|
-
|
|
600
|
-
// For each class name, look up CSS location and create token
|
|
601
|
-
for (const { name, line, column, offset, sourceOffset, length } of classes) {
|
|
602
|
-
const cssLocation = css.scopedClasses.get(name);
|
|
603
|
-
|
|
604
|
-
if (!cssLocation) {
|
|
605
|
-
continue;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
mappings.push({
|
|
609
|
-
sourceOffsets: [sourceOffset],
|
|
610
|
-
generatedOffsets: [offset],
|
|
611
|
-
lengths: [length],
|
|
612
|
-
generatedLengths: [length],
|
|
613
|
-
data: {
|
|
614
|
-
...mapping_data,
|
|
615
|
-
customData: {
|
|
616
|
-
hover:
|
|
617
|
-
'```css\n.' +
|
|
618
|
-
name +
|
|
619
|
-
'\n```\n\nCSS class selector.\n\nUse **Cmd+Click** (macOS) or **Ctrl+Click** (Windows/Linux) to navigate to its definition.',
|
|
620
|
-
definition: {
|
|
621
|
-
description: `CSS class selector for '.${name}'`,
|
|
622
|
-
location: {
|
|
623
|
-
embeddedId: get_style_region_id(css.hash),
|
|
624
|
-
start: cssLocation.start,
|
|
625
|
-
end: cssLocation.end,
|
|
626
|
-
},
|
|
627
|
-
},
|
|
628
|
-
},
|
|
629
|
-
},
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
} else {
|
|
633
|
-
if (node.name) {
|
|
634
|
-
visit(node.name);
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
if (
|
|
638
|
-
node.name.type === 'JSXIdentifier' &&
|
|
639
|
-
node.name.metadata?.is_component &&
|
|
640
|
-
node.name.loc
|
|
641
|
-
) {
|
|
642
|
-
const mapping = get_mapping_from_node(
|
|
643
|
-
node.name,
|
|
644
|
-
src_to_gen_map,
|
|
645
|
-
gen_line_offsets,
|
|
646
|
-
mapping_data,
|
|
647
|
-
);
|
|
648
|
-
mapping.sourceOffsets = [
|
|
649
|
-
/** @type {AST.NodeWithLocation} */ (node.name).start - 'component '.length,
|
|
650
|
-
];
|
|
651
|
-
mapping.lengths = ['component'.length];
|
|
652
|
-
|
|
653
|
-
mapping.data.customData.hover = replace_label_to_component;
|
|
654
|
-
mappings.push(mapping);
|
|
655
|
-
}
|
|
656
|
-
if (node.value) {
|
|
657
|
-
visit(node.value);
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
return;
|
|
662
|
-
} else if (node.type === 'JSXSpreadAttribute') {
|
|
663
|
-
// Visit the spread argument
|
|
664
|
-
if (node.argument) {
|
|
665
|
-
visit(node.argument);
|
|
666
|
-
}
|
|
667
|
-
return;
|
|
668
|
-
} else if (node.type === 'JSXExpressionContainer') {
|
|
669
|
-
if (node.loc) {
|
|
670
|
-
mappings.push(
|
|
671
|
-
get_mapping_from_node(node, src_to_gen_map, gen_line_offsets, mapping_data_verify_only),
|
|
672
|
-
);
|
|
673
|
-
}
|
|
674
|
-
// Visit the expression inside {}
|
|
675
|
-
if (node.expression) {
|
|
676
|
-
visit(node.expression);
|
|
677
|
-
}
|
|
678
|
-
return;
|
|
679
|
-
} else if (node.type === 'JSXText') {
|
|
680
|
-
// Text content, no tokens to collect
|
|
681
|
-
return;
|
|
682
|
-
} else if (node.type === 'JSXElement') {
|
|
683
|
-
// Manually visit in source order: opening element, children, closing element
|
|
684
|
-
|
|
685
|
-
// 1. Visit opening element (name and attributes)
|
|
686
|
-
// Add tokens for '<' and '>' brackets to ensure auto-close feature works
|
|
687
|
-
const opening = node.openingElement;
|
|
688
|
-
const closing = node.closingElement;
|
|
689
|
-
|
|
690
|
-
if (opening.loc) {
|
|
691
|
-
// Add tokens for '<' and '>' brackets to ensure auto-close feature works
|
|
692
|
-
tokens.push({
|
|
693
|
-
source: '<',
|
|
694
|
-
generated: '<',
|
|
695
|
-
loc: {
|
|
696
|
-
start: { line: opening.loc.start.line, column: opening.loc.start.column },
|
|
697
|
-
end: { line: opening.loc.start.line, column: opening.loc.start.column + 1 },
|
|
698
|
-
},
|
|
699
|
-
metadata: {},
|
|
700
|
-
mappingData: mapping_data_verify_only,
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
if (!opening.selfClosing) {
|
|
704
|
-
tokens.push({
|
|
705
|
-
source: '>',
|
|
706
|
-
generated: '>',
|
|
707
|
-
loc: {
|
|
708
|
-
start: { line: opening.loc.end.line, column: opening.loc.end.column - 1 },
|
|
709
|
-
end: { line: opening.loc.end.line, column: opening.loc.end.column },
|
|
710
|
-
},
|
|
711
|
-
metadata: {},
|
|
712
|
-
// we need the completion only on the closing tag `>`
|
|
713
|
-
// to cause the closing tag to be auto-added
|
|
714
|
-
mappingData: mapping_data_verify_complete,
|
|
715
|
-
});
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
visit(opening);
|
|
720
|
-
|
|
721
|
-
// 2. Visit children in order
|
|
722
|
-
if (node.children) {
|
|
723
|
-
for (const child of node.children) {
|
|
724
|
-
visit(/** @type {AST.Node} */ (child));
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
if (closing || opening.selfClosing) {
|
|
729
|
-
// Add the whole closing tag or the self-closing
|
|
730
|
-
const mapping = get_mapping_from_node(
|
|
731
|
-
closing ? closing : opening,
|
|
732
|
-
src_to_gen_map,
|
|
733
|
-
gen_line_offsets,
|
|
734
|
-
mapping_data_verify_only,
|
|
735
|
-
);
|
|
736
|
-
|
|
737
|
-
// The generated code includes a semicolon after the closing or self-closed tag
|
|
738
|
-
// We're extending the mapping to include the semicolon
|
|
739
|
-
// because the diagnostics errors can include the whole element
|
|
740
|
-
// and we need to account for the semicolon as it's a part of the diagnostic
|
|
741
|
-
// At the same time, we could've instead applied this logic to the whole `node` element
|
|
742
|
-
// but since we already map the opening - start, we just need the proper end
|
|
743
|
-
// and it was causing some issues with mappings
|
|
744
|
-
mapping.generatedLengths = [mapping.generatedLengths[0] + 1];
|
|
745
|
-
mappings.push(mapping);
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
if (closing) {
|
|
749
|
-
visit(closing);
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
return;
|
|
753
|
-
} else if (
|
|
754
|
-
node.type === 'FunctionDeclaration' ||
|
|
755
|
-
node.type === 'FunctionExpression' ||
|
|
756
|
-
node.type === 'ArrowFunctionExpression'
|
|
757
|
-
) {
|
|
758
|
-
const is_method = node.metadata?.is_method;
|
|
759
|
-
// Add function/component keyword token
|
|
760
|
-
if (
|
|
761
|
-
(node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') &&
|
|
762
|
-
!is_method
|
|
763
|
-
) {
|
|
764
|
-
const node_fn = /** @type (typeof node) & AST.NodeWithLocation */ (node);
|
|
765
|
-
const is_component = node_fn.metadata?.is_component;
|
|
766
|
-
const source_func_keyword = is_component ? 'component' : 'function';
|
|
767
|
-
let start_col = node_fn.loc.start.column;
|
|
768
|
-
let start = node_fn.start;
|
|
769
|
-
const async_keyword = 'async';
|
|
770
|
-
|
|
771
|
-
if (node_fn.async) {
|
|
772
|
-
// We explicitly mapped async and function in esrap
|
|
773
|
-
tokens.push({
|
|
774
|
-
source: async_keyword,
|
|
775
|
-
generated: async_keyword,
|
|
776
|
-
loc: {
|
|
777
|
-
start: { line: node_fn.loc.start.line, column: start_col },
|
|
778
|
-
end: {
|
|
779
|
-
line: node_fn.loc.start.line,
|
|
780
|
-
column: start_col + async_keyword.length,
|
|
781
|
-
},
|
|
782
|
-
},
|
|
783
|
-
metadata: {},
|
|
784
|
-
});
|
|
785
|
-
|
|
786
|
-
start_col += async_keyword.length + 1; // +1 for space
|
|
787
|
-
start += async_keyword.length + 1;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
tokens.push({
|
|
791
|
-
source: source_func_keyword,
|
|
792
|
-
generated: 'function',
|
|
793
|
-
loc: {
|
|
794
|
-
start: { line: node_fn.loc.start.line, column: start_col },
|
|
795
|
-
end: {
|
|
796
|
-
line: node_fn.loc.start.line,
|
|
797
|
-
column: start_col + source_func_keyword.length,
|
|
798
|
-
},
|
|
799
|
-
},
|
|
800
|
-
metadata: is_component ? { hover: replace_label_to_component } : {},
|
|
801
|
-
});
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
// Visit in source order: id, params, body
|
|
805
|
-
// If it's a part of a method, skip visiting id
|
|
806
|
-
// as the name was already covered by the key in MethodDefinition or Property
|
|
807
|
-
if (
|
|
808
|
-
/** @type {AST.FunctionDeclaration | AST.FunctionExpression} */ (node).id &&
|
|
809
|
-
!is_method
|
|
810
|
-
) {
|
|
811
|
-
visit(/** @type {AST.FunctionDeclaration | AST.FunctionExpression} */ (node).id);
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
if (node.typeParameters) {
|
|
815
|
-
visit(node.typeParameters);
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
if (node.params) {
|
|
819
|
-
for (const param of node.params) {
|
|
820
|
-
visit(param);
|
|
821
|
-
if (param.typeAnnotation) {
|
|
822
|
-
visit(param.typeAnnotation);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
if (node.returnType) {
|
|
828
|
-
visit(node.returnType);
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
if (node.body) {
|
|
832
|
-
visit(node.body);
|
|
833
|
-
}
|
|
834
|
-
return;
|
|
835
|
-
} else if (node.type === 'VariableDeclaration') {
|
|
836
|
-
// Visit declarators in order
|
|
837
|
-
if (node.declarations) {
|
|
838
|
-
for (const declarator of node.declarations) {
|
|
839
|
-
visit(declarator);
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
return;
|
|
843
|
-
} else if (node.type === 'VariableDeclarator') {
|
|
844
|
-
// Visit in source order: id, typeAnnotation, init
|
|
845
|
-
if (node.id) {
|
|
846
|
-
visit(node.id);
|
|
847
|
-
// Visit type annotation if present
|
|
848
|
-
if (node.id.typeAnnotation) {
|
|
849
|
-
visit(node.id.typeAnnotation);
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
if (node.init) {
|
|
853
|
-
visit(node.init);
|
|
854
|
-
}
|
|
855
|
-
return;
|
|
856
|
-
} else if (node.type === 'IfStatement') {
|
|
857
|
-
// Visit in source order: test, consequent, alternate
|
|
858
|
-
if (node.test) {
|
|
859
|
-
visit(node.test);
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
if (node.consequent) {
|
|
863
|
-
if (node.consequent.loc) {
|
|
864
|
-
// We're mapping only the brackets because mapping the whole thing
|
|
865
|
-
// would be way too broad and causes
|
|
866
|
-
// issues with partial mapping of something inside the body that we need
|
|
867
|
-
tokens.push(
|
|
868
|
-
{
|
|
869
|
-
source: '{',
|
|
870
|
-
generated: '{',
|
|
871
|
-
loc: {
|
|
872
|
-
start: {
|
|
873
|
-
line: node.consequent.loc.start.line,
|
|
874
|
-
column: node.consequent.loc.start.column,
|
|
875
|
-
},
|
|
876
|
-
end: {
|
|
877
|
-
line: node.consequent.loc.start.line,
|
|
878
|
-
column: node.consequent.loc.start.column + 1,
|
|
879
|
-
},
|
|
880
|
-
},
|
|
881
|
-
metadata: {},
|
|
882
|
-
mappingData: mapping_data_verify_only,
|
|
883
|
-
},
|
|
884
|
-
{
|
|
885
|
-
source: '}',
|
|
886
|
-
generated: '}',
|
|
887
|
-
loc: {
|
|
888
|
-
start: {
|
|
889
|
-
line: node.consequent.loc.end.line,
|
|
890
|
-
column: node.consequent.loc.end.column - 1,
|
|
891
|
-
},
|
|
892
|
-
end: {
|
|
893
|
-
line: node.consequent.loc.end.line,
|
|
894
|
-
column: node.consequent.loc.end.column,
|
|
895
|
-
},
|
|
896
|
-
},
|
|
897
|
-
metadata: {},
|
|
898
|
-
mappingData: mapping_data_verify_only,
|
|
899
|
-
},
|
|
900
|
-
);
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
visit(node.consequent);
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
if (node.alternate) {
|
|
907
|
-
if (node.alternate.loc) {
|
|
908
|
-
tokens.push(
|
|
909
|
-
{
|
|
910
|
-
source: '{',
|
|
911
|
-
generated: '{',
|
|
912
|
-
loc: {
|
|
913
|
-
start: {
|
|
914
|
-
line: node.alternate.loc.start.line,
|
|
915
|
-
column: node.alternate.loc.start.column,
|
|
916
|
-
},
|
|
917
|
-
end: {
|
|
918
|
-
line: node.alternate.loc.start.line,
|
|
919
|
-
column: node.alternate.loc.start.column + 1,
|
|
920
|
-
},
|
|
921
|
-
},
|
|
922
|
-
metadata: {},
|
|
923
|
-
mappingData: mapping_data_verify_only,
|
|
924
|
-
},
|
|
925
|
-
{
|
|
926
|
-
source: '}',
|
|
927
|
-
generated: '}',
|
|
928
|
-
loc: {
|
|
929
|
-
start: {
|
|
930
|
-
line: node.alternate.loc.end.line,
|
|
931
|
-
column: node.alternate.loc.end.column - 1,
|
|
932
|
-
},
|
|
933
|
-
end: { line: node.alternate.loc.end.line, column: node.alternate.loc.end.column },
|
|
934
|
-
},
|
|
935
|
-
metadata: {},
|
|
936
|
-
mappingData: mapping_data_verify_only,
|
|
937
|
-
},
|
|
938
|
-
);
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
visit(node.alternate);
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
return;
|
|
945
|
-
} else if (node.type === 'ForStatement') {
|
|
946
|
-
// Visit in source order: init, test, update, body
|
|
947
|
-
if (node.init) {
|
|
948
|
-
visit(node.init);
|
|
949
|
-
}
|
|
950
|
-
if (node.test) {
|
|
951
|
-
visit(node.test);
|
|
952
|
-
}
|
|
953
|
-
if (node.update) {
|
|
954
|
-
visit(node.update);
|
|
955
|
-
}
|
|
956
|
-
if (node.body) {
|
|
957
|
-
visit(node.body);
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
mappings.push(
|
|
961
|
-
get_mapping_from_node(node, src_to_gen_map, gen_line_offsets, mapping_data_verify_only),
|
|
962
|
-
);
|
|
963
|
-
return;
|
|
964
|
-
} else if (node.type === 'ForOfStatement' || node.type === 'ForInStatement') {
|
|
965
|
-
// Visit in source order: left, right, index (Ripple-specific), body
|
|
966
|
-
if (node.left) {
|
|
967
|
-
visit(node.left);
|
|
968
|
-
}
|
|
969
|
-
if (node.right) {
|
|
970
|
-
visit(node.right);
|
|
971
|
-
}
|
|
972
|
-
// Ripple-specific: index variable
|
|
973
|
-
if (/** @type {AST.ForOfStatement} */ (node).index) {
|
|
974
|
-
visit(/** @type {AST.ForOfStatement} */ (node).index);
|
|
975
|
-
}
|
|
976
|
-
if (node.body) {
|
|
977
|
-
visit(node.body);
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
mappings.push(
|
|
981
|
-
get_mapping_from_node(node, src_to_gen_map, gen_line_offsets, mapping_data_verify_only),
|
|
982
|
-
);
|
|
983
|
-
|
|
984
|
-
return;
|
|
985
|
-
} else if (node.type === 'WhileStatement' || node.type === 'DoWhileStatement') {
|
|
986
|
-
// Visit in source order: test, body (while) or body, test (do-while)
|
|
987
|
-
if (node.type === 'WhileStatement') {
|
|
988
|
-
if (node.test) {
|
|
989
|
-
visit(node.test);
|
|
990
|
-
}
|
|
991
|
-
if (node.body) {
|
|
992
|
-
visit(node.body);
|
|
993
|
-
}
|
|
994
|
-
} else {
|
|
995
|
-
if (node.body) {
|
|
996
|
-
visit(node.body);
|
|
997
|
-
}
|
|
998
|
-
if (node.test) {
|
|
999
|
-
visit(node.test);
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
return;
|
|
1003
|
-
} else if (node.type === 'TryStatement') {
|
|
1004
|
-
// Visit in source order: block, pending, handler, finalizer
|
|
1005
|
-
if (node.block) {
|
|
1006
|
-
mappings.push(
|
|
1007
|
-
get_mapping_from_node(
|
|
1008
|
-
node.block,
|
|
1009
|
-
src_to_gen_map,
|
|
1010
|
-
gen_line_offsets,
|
|
1011
|
-
mapping_data_verify_only,
|
|
1012
|
-
),
|
|
1013
|
-
);
|
|
1014
|
-
visit(node.block);
|
|
1015
|
-
}
|
|
1016
|
-
if (node.pending) {
|
|
1017
|
-
mappings.push(
|
|
1018
|
-
get_mapping_from_node(
|
|
1019
|
-
node.pending,
|
|
1020
|
-
src_to_gen_map,
|
|
1021
|
-
gen_line_offsets,
|
|
1022
|
-
mapping_data_verify_only,
|
|
1023
|
-
),
|
|
1024
|
-
);
|
|
1025
|
-
|
|
1026
|
-
// Add a special token for the 'pending' keyword with customData
|
|
1027
|
-
// to suppress TypeScript diagnostics and provide custom hover/definition
|
|
1028
|
-
const pending = /** @type {(typeof node.pending) & AST.NodeWithLocation} */ (
|
|
1029
|
-
node.pending
|
|
1030
|
-
);
|
|
1031
|
-
const pendingKeywordLoc = {
|
|
1032
|
-
start: {
|
|
1033
|
-
line: pending.loc.start.line,
|
|
1034
|
-
column: pending.loc.start.column - 'pending '.length,
|
|
1035
|
-
},
|
|
1036
|
-
end: {
|
|
1037
|
-
line: pending.loc.start.line,
|
|
1038
|
-
column: pending.loc.start.column - 1,
|
|
1039
|
-
},
|
|
1040
|
-
};
|
|
1041
|
-
tokens.push({
|
|
1042
|
-
source: 'pending',
|
|
1043
|
-
generated: 'pending',
|
|
1044
|
-
loc: pendingKeywordLoc,
|
|
1045
|
-
metadata: {
|
|
1046
|
-
wordHighlight: {
|
|
1047
|
-
/** @type {DocumentHighlightKind} */
|
|
1048
|
-
kind: 1,
|
|
1049
|
-
},
|
|
1050
|
-
suppressedDiagnostics: [
|
|
1051
|
-
1472, // 'catch' or 'finally' expected
|
|
1052
|
-
2304, // Cannot find name 'pending'
|
|
1053
|
-
],
|
|
1054
|
-
// suppress all hovers
|
|
1055
|
-
hover: false,
|
|
1056
|
-
|
|
1057
|
-
// Example of a custom hover contents (uses markdown)
|
|
1058
|
-
// hover: '```ripple\npending\n```\n\nRipple-specific keyword for try/pending blocks.\n\nThe `pending` block executes while async operations inside the `try` block are awaiting. This provides a built-in loading state for async components.',
|
|
1059
|
-
|
|
1060
|
-
// Example of a custom definition and its type definition file
|
|
1061
|
-
// definition: {
|
|
1062
|
-
// typeReplace: {
|
|
1063
|
-
// name: 'SomeType',
|
|
1064
|
-
// path: 'types/index.d.ts',
|
|
1065
|
-
// },
|
|
1066
|
-
// },
|
|
1067
|
-
},
|
|
1068
|
-
});
|
|
1069
|
-
visit(node.pending);
|
|
1070
|
-
}
|
|
1071
|
-
if (node.handler) {
|
|
1072
|
-
visit(node.handler);
|
|
1073
|
-
}
|
|
1074
|
-
if (node.finalizer) {
|
|
1075
|
-
visit(node.finalizer);
|
|
1076
|
-
}
|
|
1077
|
-
return;
|
|
1078
|
-
} else if (node.type === 'CatchClause') {
|
|
1079
|
-
// Visit in source order: param, resetParam, body
|
|
1080
|
-
if (node.param) {
|
|
1081
|
-
visit(node.param);
|
|
1082
|
-
}
|
|
1083
|
-
if (node.resetParam) {
|
|
1084
|
-
visit(node.resetParam);
|
|
1085
|
-
}
|
|
1086
|
-
if (node.body) {
|
|
1087
|
-
visit(node.body);
|
|
1088
|
-
}
|
|
1089
|
-
return;
|
|
1090
|
-
} else if (node.type === 'CallExpression' || node.type === 'NewExpression') {
|
|
1091
|
-
if (node.type === 'NewExpression' && node.loc) {
|
|
1092
|
-
mappings.push(
|
|
1093
|
-
get_mapping_from_node(node, src_to_gen_map, gen_line_offsets, mapping_data_verify_only),
|
|
1094
|
-
);
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
if (node.arguments) {
|
|
1098
|
-
for (const arg of node.arguments) {
|
|
1099
|
-
visit(arg);
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
if (node.typeArguments) {
|
|
1104
|
-
visit(node.typeArguments);
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
if (node.callee) {
|
|
1108
|
-
visit(node.callee);
|
|
1109
|
-
}
|
|
1110
|
-
return;
|
|
1111
|
-
} else if (node.type === 'LogicalExpression' || node.type === 'BinaryExpression') {
|
|
1112
|
-
// Visit in source order: left, right
|
|
1113
|
-
if (node.left) {
|
|
1114
|
-
visit(node.left);
|
|
1115
|
-
}
|
|
1116
|
-
if (node.right) {
|
|
1117
|
-
visit(node.right);
|
|
1118
|
-
}
|
|
1119
|
-
return;
|
|
1120
|
-
} else if (node.type === 'MemberExpression') {
|
|
1121
|
-
if (node.loc) {
|
|
1122
|
-
const mapping = get_mapping_from_node(
|
|
1123
|
-
node,
|
|
1124
|
-
src_to_gen_map,
|
|
1125
|
-
gen_line_offsets,
|
|
1126
|
-
mapping_data_verify_only,
|
|
1127
|
-
);
|
|
1128
|
-
|
|
1129
|
-
mappings.push(mapping);
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
|
-
if (node.object) {
|
|
1133
|
-
visit(node.object);
|
|
1134
|
-
}
|
|
1135
|
-
if (node.property) {
|
|
1136
|
-
visit(node.property);
|
|
1137
|
-
|
|
1138
|
-
if (node.computed && node.property.loc) {
|
|
1139
|
-
mappings.push(
|
|
1140
|
-
get_mapping_from_node(
|
|
1141
|
-
node.property,
|
|
1142
|
-
src_to_gen_map,
|
|
1143
|
-
gen_line_offsets,
|
|
1144
|
-
mapping_data_verify_only,
|
|
1145
|
-
),
|
|
1146
|
-
);
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
return;
|
|
1150
|
-
} else if (node.type === 'AssignmentExpression' || node.type === 'AssignmentPattern') {
|
|
1151
|
-
// Visit in source order: left, typeAnnotation, right
|
|
1152
|
-
if (node.left) {
|
|
1153
|
-
visit(node.left);
|
|
1154
|
-
// Visit type annotation if present (for AssignmentPattern)
|
|
1155
|
-
if (node.left.typeAnnotation) {
|
|
1156
|
-
visit(node.left.typeAnnotation);
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
if (node.right) {
|
|
1160
|
-
visit(node.right);
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
if (node.type === 'AssignmentPattern') {
|
|
1164
|
-
// We need a mapping for the whole AssignmentPattern for diagnostics
|
|
1165
|
-
// Only enable diagnostic verification here to avoid duplicate mappings
|
|
1166
|
-
// that can cause things like double definitions
|
|
1167
|
-
mappings.push(
|
|
1168
|
-
get_mapping_from_node(node, src_to_gen_map, gen_line_offsets, mapping_data_verify_only),
|
|
1169
|
-
);
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
return;
|
|
1173
|
-
} else if (node.type === 'ObjectExpression' || node.type === 'ObjectPattern') {
|
|
1174
|
-
if (node.loc && node.type === 'ObjectExpression') {
|
|
1175
|
-
mappings.push(
|
|
1176
|
-
get_mapping_from_node(node, src_to_gen_map, gen_line_offsets, mapping_data_verify_only),
|
|
1177
|
-
);
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
|
-
// Visit properties in order
|
|
1181
|
-
if (node.properties) {
|
|
1182
|
-
for (const prop of node.properties) {
|
|
1183
|
-
visit(prop);
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
return;
|
|
1187
|
-
} else if (node.type === 'Property') {
|
|
1188
|
-
// Visit in source order: key, value
|
|
1189
|
-
// For shorthand properties ({ count }), key and value are the same node, only visit once
|
|
1190
|
-
if (node.shorthand) {
|
|
1191
|
-
if (node.value) {
|
|
1192
|
-
visit(node.value);
|
|
1193
|
-
}
|
|
1194
|
-
} else {
|
|
1195
|
-
if (node.computed) {
|
|
1196
|
-
set_bracket_computed_mapping(node, mappings);
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
if (
|
|
1200
|
-
node.value.type === 'FunctionExpression' &&
|
|
1201
|
-
node.method &&
|
|
1202
|
-
node.value.metadata.is_component
|
|
1203
|
-
) {
|
|
1204
|
-
set_component_mapping_to_name(/** @type {PropertyIsComponent} */ (node));
|
|
1205
|
-
}
|
|
1206
|
-
|
|
1207
|
-
if (node.key.type === 'Literal') {
|
|
1208
|
-
handle_literal(
|
|
1209
|
-
node.key,
|
|
1210
|
-
/** @type {AST.FunctionExpression} */ (node.value).metadata.is_component,
|
|
1211
|
-
);
|
|
1212
|
-
} else {
|
|
1213
|
-
visit(node.key);
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
if (node.value) {
|
|
1217
|
-
visit(node.value);
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
return;
|
|
1221
|
-
} else if (node.type === 'ArrayExpression' || node.type === 'ArrayPattern') {
|
|
1222
|
-
// Visit elements in order
|
|
1223
|
-
if (node.elements) {
|
|
1224
|
-
for (const element of node.elements) {
|
|
1225
|
-
if (element) visit(element);
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
return;
|
|
1229
|
-
} else if (node.type === 'ConditionalExpression') {
|
|
1230
|
-
// Visit in source order: test, consequent, alternate
|
|
1231
|
-
if (node.test) {
|
|
1232
|
-
visit(node.test);
|
|
1233
|
-
}
|
|
1234
|
-
if (node.consequent) {
|
|
1235
|
-
visit(node.consequent);
|
|
1236
|
-
}
|
|
1237
|
-
if (node.alternate) {
|
|
1238
|
-
visit(node.alternate);
|
|
1239
|
-
}
|
|
1240
|
-
return;
|
|
1241
|
-
} else if (node.type === 'UnaryExpression' || node.type === 'UpdateExpression') {
|
|
1242
|
-
// Visit argument
|
|
1243
|
-
if (node.argument) {
|
|
1244
|
-
visit(node.argument);
|
|
1245
|
-
}
|
|
1246
|
-
return;
|
|
1247
|
-
} else if (node.type === 'TemplateLiteral') {
|
|
1248
|
-
if (node.loc) {
|
|
1249
|
-
mappings.push(
|
|
1250
|
-
get_mapping_from_node(node, src_to_gen_map, gen_line_offsets, mapping_data_verify_only),
|
|
1251
|
-
);
|
|
1252
|
-
}
|
|
1253
|
-
|
|
1254
|
-
// Visit quasis and expressions in order
|
|
1255
|
-
for (let i = 0; i < node.quasis.length; i++) {
|
|
1256
|
-
if (node.quasis[i]) {
|
|
1257
|
-
visit(node.quasis[i]);
|
|
1258
|
-
}
|
|
1259
|
-
if (i < node.expressions.length && node.expressions[i]) {
|
|
1260
|
-
visit(node.expressions[i]);
|
|
1261
|
-
}
|
|
1262
|
-
}
|
|
1263
|
-
return;
|
|
1264
|
-
} else if (node.type === 'TaggedTemplateExpression') {
|
|
1265
|
-
// Visit in source order: tag, quasi
|
|
1266
|
-
if (node.tag) {
|
|
1267
|
-
visit(node.tag);
|
|
1268
|
-
}
|
|
1269
|
-
if (node.quasi) {
|
|
1270
|
-
visit(node.quasi);
|
|
1271
|
-
}
|
|
1272
|
-
return;
|
|
1273
|
-
} else if (node.type === 'ReturnStatement' || node.type === 'ThrowStatement') {
|
|
1274
|
-
// Visit argument
|
|
1275
|
-
if (node.argument) {
|
|
1276
|
-
visit(node.argument);
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
if (node.type === 'ReturnStatement' && node.loc) {
|
|
1280
|
-
const mapping = get_mapping_from_node(
|
|
1281
|
-
node,
|
|
1282
|
-
src_to_gen_map,
|
|
1283
|
-
gen_line_offsets,
|
|
1284
|
-
mapping_data_verify_only,
|
|
1285
|
-
);
|
|
1286
|
-
// We're only mapping the 'return' keyword, otherwise the mapping would be too broad
|
|
1287
|
-
// and likely may cause issues with partial mappings of something inside the return statement that we need
|
|
1288
|
-
const return_keyword_length = 'return'.length;
|
|
1289
|
-
mapping.lengths = [return_keyword_length];
|
|
1290
|
-
mapping.generatedLengths = [return_keyword_length];
|
|
1291
|
-
|
|
1292
|
-
mappings.push(mapping);
|
|
1293
|
-
}
|
|
1294
|
-
return;
|
|
1295
|
-
} else if (node.type === 'ExpressionStatement') {
|
|
1296
|
-
if (node.expression) {
|
|
1297
|
-
visit(node.expression);
|
|
1298
|
-
}
|
|
1299
|
-
return;
|
|
1300
|
-
} else if (node.type === 'BlockStatement' || node.type === 'Program') {
|
|
1301
|
-
// Visit body statements in order
|
|
1302
|
-
if (node.body) {
|
|
1303
|
-
for (const statement of node.body) {
|
|
1304
|
-
visit(statement);
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
return;
|
|
1308
|
-
} else if (node.type === 'SwitchStatement') {
|
|
1309
|
-
// Visit in source order: discriminant, cases
|
|
1310
|
-
if (node.discriminant) {
|
|
1311
|
-
visit(node.discriminant);
|
|
1312
|
-
}
|
|
1313
|
-
if (node.cases) {
|
|
1314
|
-
for (const caseNode of node.cases) {
|
|
1315
|
-
visit(caseNode);
|
|
1316
|
-
}
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
mappings.push(
|
|
1320
|
-
get_mapping_from_node(node, src_to_gen_map, gen_line_offsets, mapping_data_verify_only),
|
|
1321
|
-
);
|
|
1322
|
-
|
|
1323
|
-
return;
|
|
1324
|
-
} else if (node.type === 'SwitchCase') {
|
|
1325
|
-
// Visit in source order: test, consequent
|
|
1326
|
-
if (node.test) {
|
|
1327
|
-
visit(node.test);
|
|
1328
|
-
}
|
|
1329
|
-
if (node.consequent) {
|
|
1330
|
-
for (const statement of node.consequent) {
|
|
1331
|
-
visit(statement);
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
return;
|
|
1335
|
-
} else if (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') {
|
|
1336
|
-
// Visit in source order: id, superClass, body
|
|
1337
|
-
if (node.id) {
|
|
1338
|
-
visit(node.id);
|
|
1339
|
-
}
|
|
1340
|
-
if (node.superClass) {
|
|
1341
|
-
visit(node.superClass);
|
|
1342
|
-
}
|
|
1343
|
-
if (node.body) {
|
|
1344
|
-
visit(node.body);
|
|
1345
|
-
}
|
|
1346
|
-
return;
|
|
1347
|
-
} else if (node.type === 'ClassBody') {
|
|
1348
|
-
// Visit body in order
|
|
1349
|
-
if (node.body) {
|
|
1350
|
-
for (const member of node.body) {
|
|
1351
|
-
visit(member);
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
return;
|
|
1355
|
-
} else if (node.type === 'MethodDefinition') {
|
|
1356
|
-
if (node.computed) {
|
|
1357
|
-
set_bracket_computed_mapping(node, mappings);
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
if (node.value.metadata.is_component) {
|
|
1361
|
-
set_component_mapping_to_name(/** @type {MethodIsComponent} */ (node));
|
|
1362
|
-
}
|
|
1363
|
-
|
|
1364
|
-
if (node.key.type === 'Literal') {
|
|
1365
|
-
handle_literal(
|
|
1366
|
-
node.key,
|
|
1367
|
-
/** @type {AST.FunctionExpression} */ (node.value).metadata.is_component,
|
|
1368
|
-
);
|
|
1369
|
-
} else {
|
|
1370
|
-
visit(node.key);
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
if (node.value) {
|
|
1374
|
-
visit(node.value);
|
|
1375
|
-
}
|
|
1376
|
-
return;
|
|
1377
|
-
} else if (node.type === 'SequenceExpression') {
|
|
1378
|
-
// Visit expressions in order
|
|
1379
|
-
if (node.expressions) {
|
|
1380
|
-
for (const expr of node.expressions) {
|
|
1381
|
-
visit(expr);
|
|
1382
|
-
}
|
|
1383
|
-
}
|
|
1384
|
-
return;
|
|
1385
|
-
} else if (node.type === 'SpreadElement' || node.type === 'RestElement') {
|
|
1386
|
-
// Visit the argument
|
|
1387
|
-
if (node.argument) {
|
|
1388
|
-
visit(node.argument);
|
|
1389
|
-
// Visit type annotation if present (for RestElement)
|
|
1390
|
-
if (/** @type {AST.Pattern} */ (node.argument).typeAnnotation) {
|
|
1391
|
-
visit(/** @type {AST.Pattern} */ (node.argument).typeAnnotation);
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
// RestElement itself can have typeAnnotation
|
|
1395
|
-
if (node.typeAnnotation) {
|
|
1396
|
-
visit(node.typeAnnotation);
|
|
1397
|
-
}
|
|
1398
|
-
return;
|
|
1399
|
-
} else if (node.type === 'YieldExpression' || node.type === 'AwaitExpression') {
|
|
1400
|
-
// Visit the argument if present
|
|
1401
|
-
if (node.argument) {
|
|
1402
|
-
visit(node.argument);
|
|
1403
|
-
}
|
|
1404
|
-
|
|
1405
|
-
if (node.type === 'AwaitExpression') {
|
|
1406
|
-
const max_len = 'await'.length;
|
|
1407
|
-
// We need a mapping for diagnostics but only on the 'await' keyword
|
|
1408
|
-
const mapping = get_mapping_from_node(
|
|
1409
|
-
node,
|
|
1410
|
-
src_to_gen_map,
|
|
1411
|
-
gen_line_offsets,
|
|
1412
|
-
mapping_data_verify_only,
|
|
1413
|
-
max_len,
|
|
1414
|
-
max_len,
|
|
1415
|
-
);
|
|
1416
|
-
|
|
1417
|
-
mappings.push(mapping);
|
|
1418
|
-
}
|
|
1419
|
-
return;
|
|
1420
|
-
} else if (node.type === 'ChainExpression') {
|
|
1421
|
-
// Visit the expression
|
|
1422
|
-
if (node.expression) {
|
|
1423
|
-
visit(node.expression);
|
|
1424
|
-
}
|
|
1425
|
-
return;
|
|
1426
|
-
} else if (node.type === 'Super' || node.type === 'ThisExpression') {
|
|
1427
|
-
// Leaf nodes, no children
|
|
1428
|
-
return;
|
|
1429
|
-
} else if (node.type === 'MetaProperty') {
|
|
1430
|
-
// Visit meta and property (e.g., new.target, import.meta)
|
|
1431
|
-
if (node.meta) {
|
|
1432
|
-
visit(node.meta);
|
|
1433
|
-
}
|
|
1434
|
-
if (node.property) {
|
|
1435
|
-
visit(node.property);
|
|
1436
|
-
}
|
|
1437
|
-
return;
|
|
1438
|
-
} else if (node.type === 'EmptyStatement' || node.type === 'DebuggerStatement') {
|
|
1439
|
-
// No children to visit
|
|
1440
|
-
return;
|
|
1441
|
-
} else if (node.type === 'LabeledStatement') {
|
|
1442
|
-
// Visit label and statement
|
|
1443
|
-
if (node.label) {
|
|
1444
|
-
visit(node.label);
|
|
1445
|
-
}
|
|
1446
|
-
if (node.body) {
|
|
1447
|
-
visit(node.body);
|
|
1448
|
-
}
|
|
1449
|
-
return;
|
|
1450
|
-
} else if (node.type === 'BreakStatement' || node.type === 'ContinueStatement') {
|
|
1451
|
-
// Visit label if present
|
|
1452
|
-
if (node.label) {
|
|
1453
|
-
visit(node.label);
|
|
1454
|
-
}
|
|
1455
|
-
return;
|
|
1456
|
-
} else if (node.type === 'WithStatement') {
|
|
1457
|
-
// Visit object and body
|
|
1458
|
-
if (node.object) {
|
|
1459
|
-
visit(node.object);
|
|
1460
|
-
}
|
|
1461
|
-
if (node.body) {
|
|
1462
|
-
visit(node.body);
|
|
1463
|
-
}
|
|
1464
|
-
return;
|
|
1465
|
-
} else if (node.type === 'JSXFragment') {
|
|
1466
|
-
// Visit children in order
|
|
1467
|
-
if (node.children) {
|
|
1468
|
-
for (const child of node.children) {
|
|
1469
|
-
visit(/** @type {AST.Node} */ (child));
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
return;
|
|
1473
|
-
} else if (node.type === 'JSXClosingFragment' || node.type === 'JSXOpeningFragment') {
|
|
1474
|
-
// These are handled by their parent nodes
|
|
1475
|
-
return;
|
|
1476
|
-
} else if (node.type === 'JSXMemberExpression') {
|
|
1477
|
-
// Visit object and property (e.g., <Foo.Bar>)
|
|
1478
|
-
if (node.object) {
|
|
1479
|
-
visit(node.object);
|
|
1480
|
-
}
|
|
1481
|
-
if (node.property) {
|
|
1482
|
-
visit(node.property);
|
|
1483
|
-
}
|
|
1484
|
-
return;
|
|
1485
|
-
} else if (node.type === 'JSXNamespacedName') {
|
|
1486
|
-
// Visit namespace and name (e.g., <svg:circle>)
|
|
1487
|
-
if (node.namespace) {
|
|
1488
|
-
visit(node.namespace);
|
|
1489
|
-
}
|
|
1490
|
-
if (node.name) {
|
|
1491
|
-
visit(node.name);
|
|
1492
|
-
}
|
|
1493
|
-
return;
|
|
1494
|
-
} else if (node.type === 'JSXEmptyExpression') {
|
|
1495
|
-
// No children
|
|
1496
|
-
return;
|
|
1497
|
-
} else if (node.type === 'TemplateElement') {
|
|
1498
|
-
// Leaf node, no children to visit
|
|
1499
|
-
return;
|
|
1500
|
-
} else if (node.type === 'PrivateIdentifier') {
|
|
1501
|
-
// Leaf node
|
|
1502
|
-
return;
|
|
1503
|
-
} else if (node.type === 'PropertyDefinition') {
|
|
1504
|
-
// Visit key and value
|
|
1505
|
-
if (node.key) {
|
|
1506
|
-
visit(node.key);
|
|
1507
|
-
}
|
|
1508
|
-
if (node.value) {
|
|
1509
|
-
visit(node.value);
|
|
1510
|
-
}
|
|
1511
|
-
return;
|
|
1512
|
-
} else if (node.type === 'StaticBlock') {
|
|
1513
|
-
// Visit body
|
|
1514
|
-
if (node.body) {
|
|
1515
|
-
for (const statement of node.body) {
|
|
1516
|
-
visit(statement);
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
return;
|
|
1520
|
-
} else if (node.type === 'ImportExpression') {
|
|
1521
|
-
// Visit source
|
|
1522
|
-
if (node.source) {
|
|
1523
|
-
visit(node.source);
|
|
1524
|
-
}
|
|
1525
|
-
return;
|
|
1526
|
-
} else if (node.type === 'ParenthesizedExpression') {
|
|
1527
|
-
if (node.metadata.forceMapping && node.loc) {
|
|
1528
|
-
const mapping = get_mapping_from_node(node, src_to_gen_map, gen_line_offsets);
|
|
1529
|
-
if (node.metadata.skipParenthesisMapping) {
|
|
1530
|
-
mapping.generatedOffsets[0] = mapping.generatedOffsets[0] + 1; // Skip the opening parenthesis
|
|
1531
|
-
mapping.generatedLengths[0] = mapping.generatedLengths[0] - 2; // Skip both parentheses
|
|
1532
|
-
}
|
|
1533
|
-
mappings.push(mapping);
|
|
1534
|
-
}
|
|
1535
|
-
// Visit the wrapped expression
|
|
1536
|
-
if (node.expression) {
|
|
1537
|
-
visit(node.expression);
|
|
1538
|
-
}
|
|
1539
|
-
return;
|
|
1540
|
-
} else if (node.type === 'TSAsExpression' || node.type === 'TSSatisfiesExpression') {
|
|
1541
|
-
// Type assertion: value as Type
|
|
1542
|
-
if (node.expression) {
|
|
1543
|
-
visit(node.expression);
|
|
1544
|
-
}
|
|
1545
|
-
if (node.typeAnnotation) {
|
|
1546
|
-
visit(node.typeAnnotation);
|
|
1547
|
-
}
|
|
1548
|
-
return;
|
|
1549
|
-
} else if (node.type === 'TSNonNullExpression') {
|
|
1550
|
-
// Non-null assertion: value!
|
|
1551
|
-
if (node.expression) {
|
|
1552
|
-
visit(node.expression);
|
|
1553
|
-
}
|
|
1554
|
-
return;
|
|
1555
|
-
} else if (node.type === 'TSTypeAssertion') {
|
|
1556
|
-
// Type assertion: <Type>value
|
|
1557
|
-
if (node.expression) {
|
|
1558
|
-
visit(node.expression);
|
|
1559
|
-
}
|
|
1560
|
-
// Skip typeAnnotation
|
|
1561
|
-
return;
|
|
1562
|
-
} else if (
|
|
1563
|
-
node.type === 'TSTypeParameterInstantiation' ||
|
|
1564
|
-
node.type === 'TSTypeParameterDeclaration'
|
|
1565
|
-
) {
|
|
1566
|
-
if (node.loc) {
|
|
1567
|
-
mappings.push(
|
|
1568
|
-
get_mapping_from_node(node, src_to_gen_map, gen_line_offsets, mapping_data_verify_only),
|
|
1569
|
-
);
|
|
1570
|
-
}
|
|
1571
|
-
// Generic type parameters - visit to collect type variable names
|
|
1572
|
-
if (node.params) {
|
|
1573
|
-
for (const param of node.params) {
|
|
1574
|
-
visit(param);
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
return;
|
|
1578
|
-
} else if (node.type === 'TSTypeParameter') {
|
|
1579
|
-
// Type parameter like T in <T> or key in mapped types
|
|
1580
|
-
// Note: node.name is a string, not an Identifier node
|
|
1581
|
-
if (node.name && node.loc && typeof node.name === 'string') {
|
|
1582
|
-
tokens.push({ source: node.name, generated: node.name, loc: node.loc, metadata: {} });
|
|
1583
|
-
} else if (node.name && typeof node.name === 'object') {
|
|
1584
|
-
// In some cases, name might be an Identifier node
|
|
1585
|
-
visit(node.name);
|
|
1586
|
-
}
|
|
1587
|
-
if (node.constraint) {
|
|
1588
|
-
visit(node.constraint);
|
|
1589
|
-
}
|
|
1590
|
-
if (node.default) {
|
|
1591
|
-
visit(node.default);
|
|
1592
|
-
}
|
|
1593
|
-
return;
|
|
1594
|
-
} else if (node.type === 'TSTypeAnnotation') {
|
|
1595
|
-
// Type annotation - visit the type
|
|
1596
|
-
if (node.typeAnnotation) {
|
|
1597
|
-
visit(node.typeAnnotation);
|
|
1598
|
-
}
|
|
1599
|
-
return;
|
|
1600
|
-
} else if (node.type === 'TSTypeReference') {
|
|
1601
|
-
// Type reference like "string" or "Array<T>"
|
|
1602
|
-
if (node.typeName) {
|
|
1603
|
-
visit(node.typeName);
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
// typeParameters and typeArguments (different parsers use different names)
|
|
1607
|
-
// tsTypeParameters is a bug in the estree-typescript
|
|
1608
|
-
// but we fixed in the analyzer to typeArguments.
|
|
1609
|
-
|
|
1610
|
-
if (node.typeArguments) {
|
|
1611
|
-
visit(node.typeArguments);
|
|
1612
|
-
}
|
|
1613
|
-
return;
|
|
1614
|
-
} else if (node.type === 'TSQualifiedName') {
|
|
1615
|
-
// Qualified name (e.g., Foo.Bar in types)
|
|
1616
|
-
if (node.left) {
|
|
1617
|
-
visit(node.left);
|
|
1618
|
-
}
|
|
1619
|
-
if (node.right) {
|
|
1620
|
-
visit(node.right);
|
|
1621
|
-
}
|
|
1622
|
-
return;
|
|
1623
|
-
} else if (node.type === 'TSArrayType') {
|
|
1624
|
-
// Array type like T[]
|
|
1625
|
-
if (node.elementType) {
|
|
1626
|
-
visit(node.elementType);
|
|
1627
|
-
}
|
|
1628
|
-
return;
|
|
1629
|
-
} else if (node.type === 'TSTupleType') {
|
|
1630
|
-
// Tuple type like [string, number]
|
|
1631
|
-
if (node.elementTypes) {
|
|
1632
|
-
for (const type of node.elementTypes) {
|
|
1633
|
-
visit(type);
|
|
1634
|
-
}
|
|
1635
|
-
}
|
|
1636
|
-
return;
|
|
1637
|
-
} else if (node.type === 'TSUnionType' || node.type === 'TSIntersectionType') {
|
|
1638
|
-
// Union (A | B) or Intersection (A & B) types
|
|
1639
|
-
if (node.types) {
|
|
1640
|
-
for (const type of node.types) {
|
|
1641
|
-
visit(type);
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
return;
|
|
1645
|
-
} else if (node.type === 'TSFunctionType' || node.type === 'TSConstructorType') {
|
|
1646
|
-
// Function or constructor type
|
|
1647
|
-
if (node.typeParameters) {
|
|
1648
|
-
visit(node.typeParameters);
|
|
1649
|
-
}
|
|
1650
|
-
if (node.parameters) {
|
|
1651
|
-
for (const param of node.parameters) {
|
|
1652
|
-
visit(param);
|
|
1653
|
-
// Visit type annotation on the parameter
|
|
1654
|
-
if (
|
|
1655
|
-
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param).typeAnnotation
|
|
1656
|
-
) {
|
|
1657
|
-
visit(
|
|
1658
|
-
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param)
|
|
1659
|
-
.typeAnnotation,
|
|
1660
|
-
);
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
|
-
if (node.typeAnnotation) {
|
|
1665
|
-
visit(node.typeAnnotation);
|
|
1666
|
-
}
|
|
1667
|
-
return;
|
|
1668
|
-
} else if (node.type === 'TSTypeLiteral') {
|
|
1669
|
-
// Object type literal { foo: string }
|
|
1670
|
-
if (node.members) {
|
|
1671
|
-
for (const member of node.members) {
|
|
1672
|
-
visit(member);
|
|
1673
|
-
}
|
|
1674
|
-
}
|
|
1675
|
-
return;
|
|
1676
|
-
} else if (node.type === 'TSPropertySignature') {
|
|
1677
|
-
// Property signature in type
|
|
1678
|
-
if (node.key) {
|
|
1679
|
-
visit(node.key);
|
|
1680
|
-
}
|
|
1681
|
-
if (node.typeAnnotation) {
|
|
1682
|
-
visit(node.typeAnnotation);
|
|
1683
|
-
}
|
|
1684
|
-
return;
|
|
1685
|
-
} else if (node.type === 'TSMethodSignature') {
|
|
1686
|
-
// Method signature in type
|
|
1687
|
-
if (node.key) {
|
|
1688
|
-
visit(node.key);
|
|
1689
|
-
}
|
|
1690
|
-
if (node.typeParameters) {
|
|
1691
|
-
visit(node.typeParameters);
|
|
1692
|
-
}
|
|
1693
|
-
if (node.parameters) {
|
|
1694
|
-
for (const param of node.parameters) {
|
|
1695
|
-
visit(param);
|
|
1696
|
-
// Visit type annotation on the parameter
|
|
1697
|
-
if (
|
|
1698
|
-
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param).typeAnnotation
|
|
1699
|
-
) {
|
|
1700
|
-
visit(
|
|
1701
|
-
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param)
|
|
1702
|
-
.typeAnnotation,
|
|
1703
|
-
);
|
|
1704
|
-
}
|
|
1705
|
-
}
|
|
1706
|
-
}
|
|
1707
|
-
if (node.typeAnnotation) {
|
|
1708
|
-
visit(node.typeAnnotation);
|
|
1709
|
-
}
|
|
1710
|
-
return;
|
|
1711
|
-
} else if (node.type === 'TSIndexSignature') {
|
|
1712
|
-
// Index signature [key: string]: Type
|
|
1713
|
-
if (node.parameters) {
|
|
1714
|
-
for (const param of node.parameters) {
|
|
1715
|
-
visit(param);
|
|
1716
|
-
// Visit type annotation on the parameter
|
|
1717
|
-
if (
|
|
1718
|
-
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param).typeAnnotation
|
|
1719
|
-
) {
|
|
1720
|
-
visit(
|
|
1721
|
-
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param)
|
|
1722
|
-
.typeAnnotation,
|
|
1723
|
-
);
|
|
1724
|
-
}
|
|
1725
|
-
}
|
|
1726
|
-
}
|
|
1727
|
-
if (node.typeAnnotation) {
|
|
1728
|
-
visit(node.typeAnnotation);
|
|
1729
|
-
}
|
|
1730
|
-
return;
|
|
1731
|
-
} else if (
|
|
1732
|
-
node.type === 'TSCallSignatureDeclaration' ||
|
|
1733
|
-
node.type === 'TSConstructSignatureDeclaration'
|
|
1734
|
-
) {
|
|
1735
|
-
// Call or construct signature
|
|
1736
|
-
if (node.typeParameters) {
|
|
1737
|
-
visit(node.typeParameters);
|
|
1738
|
-
}
|
|
1739
|
-
if (node.parameters) {
|
|
1740
|
-
for (const param of node.parameters) {
|
|
1741
|
-
visit(param);
|
|
1742
|
-
// Visit type annotation on the parameter
|
|
1743
|
-
if (
|
|
1744
|
-
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param).typeAnnotation
|
|
1745
|
-
) {
|
|
1746
|
-
visit(
|
|
1747
|
-
/** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param)
|
|
1748
|
-
.typeAnnotation,
|
|
1749
|
-
);
|
|
1750
|
-
}
|
|
1751
|
-
}
|
|
1752
|
-
}
|
|
1753
|
-
if (node.typeAnnotation) {
|
|
1754
|
-
visit(node.typeAnnotation);
|
|
1755
|
-
}
|
|
1756
|
-
return;
|
|
1757
|
-
} else if (node.type === 'TSConditionalType') {
|
|
1758
|
-
// Conditional type: T extends U ? X : Y
|
|
1759
|
-
if (node.checkType) {
|
|
1760
|
-
visit(node.checkType);
|
|
1761
|
-
}
|
|
1762
|
-
if (node.extendsType) {
|
|
1763
|
-
visit(node.extendsType);
|
|
1764
|
-
}
|
|
1765
|
-
if (node.trueType) {
|
|
1766
|
-
visit(node.trueType);
|
|
1767
|
-
}
|
|
1768
|
-
if (node.falseType) {
|
|
1769
|
-
visit(node.falseType);
|
|
1770
|
-
}
|
|
1771
|
-
return;
|
|
1772
|
-
} else if (node.type === 'TSInferType') {
|
|
1773
|
-
// Infer type: infer T
|
|
1774
|
-
if (node.typeParameter) {
|
|
1775
|
-
visit(node.typeParameter);
|
|
1776
|
-
}
|
|
1777
|
-
return;
|
|
1778
|
-
} else if (node.type === 'TSParenthesizedType') {
|
|
1779
|
-
// Parenthesized type: (T)
|
|
1780
|
-
if (node.typeAnnotation) {
|
|
1781
|
-
visit(node.typeAnnotation);
|
|
1782
|
-
}
|
|
1783
|
-
return;
|
|
1784
|
-
} else if (node.type === 'TSTypeOperator') {
|
|
1785
|
-
// Type operator: keyof T, readonly T
|
|
1786
|
-
if (node.typeAnnotation) {
|
|
1787
|
-
visit(node.typeAnnotation);
|
|
1788
|
-
}
|
|
1789
|
-
return;
|
|
1790
|
-
} else if (node.type === 'TSIndexedAccessType') {
|
|
1791
|
-
// Indexed access: T[K]
|
|
1792
|
-
if (node.objectType) {
|
|
1793
|
-
visit(node.objectType);
|
|
1794
|
-
}
|
|
1795
|
-
if (node.indexType) {
|
|
1796
|
-
visit(node.indexType);
|
|
1797
|
-
}
|
|
1798
|
-
return;
|
|
1799
|
-
} else if (node.type === 'TSMappedType') {
|
|
1800
|
-
// Mapped type: { [K in keyof T]: ... }
|
|
1801
|
-
if (node.typeParameter) {
|
|
1802
|
-
visit(node.typeParameter);
|
|
1803
|
-
}
|
|
1804
|
-
if (node.typeAnnotation) {
|
|
1805
|
-
visit(node.typeAnnotation);
|
|
1806
|
-
}
|
|
1807
|
-
return;
|
|
1808
|
-
} else if (node.type === 'TSLiteralType') {
|
|
1809
|
-
// Literal type: "foo" | 123 | true
|
|
1810
|
-
if (node.literal) {
|
|
1811
|
-
visit(node.literal);
|
|
1812
|
-
}
|
|
1813
|
-
return;
|
|
1814
|
-
} else if (node.type === 'TSExpressionWithTypeArguments') {
|
|
1815
|
-
// Expression with type arguments: Foo<Bar>
|
|
1816
|
-
if (node.expression) {
|
|
1817
|
-
visit(node.expression);
|
|
1818
|
-
}
|
|
1819
|
-
if (node.typeParameters) {
|
|
1820
|
-
visit(node.typeParameters);
|
|
1821
|
-
}
|
|
1822
|
-
return;
|
|
1823
|
-
} else if (node.type === 'TSImportType') {
|
|
1824
|
-
// Import type: import("module").Type
|
|
1825
|
-
if (node.argument) {
|
|
1826
|
-
visit(node.argument);
|
|
1827
|
-
}
|
|
1828
|
-
if (node.qualifier) {
|
|
1829
|
-
visit(node.qualifier);
|
|
1830
|
-
}
|
|
1831
|
-
if (node.typeParameters) {
|
|
1832
|
-
visit(node.typeParameters);
|
|
1833
|
-
}
|
|
1834
|
-
return;
|
|
1835
|
-
} else if (node.type === 'TSTypeQuery') {
|
|
1836
|
-
// Type query: typeof x
|
|
1837
|
-
if (node.exprName) {
|
|
1838
|
-
visit(node.exprName);
|
|
1839
|
-
}
|
|
1840
|
-
if (node.typeArguments) {
|
|
1841
|
-
visit(node.typeArguments);
|
|
1842
|
-
}
|
|
1843
|
-
return;
|
|
1844
|
-
} else if (node.type === 'TSInterfaceDeclaration') {
|
|
1845
|
-
// Interface declaration
|
|
1846
|
-
if (node.id) {
|
|
1847
|
-
visit(node.id);
|
|
1848
|
-
}
|
|
1849
|
-
if (node.typeParameters) {
|
|
1850
|
-
visit(node.typeParameters);
|
|
1851
|
-
}
|
|
1852
|
-
if (node.extends) {
|
|
1853
|
-
for (const ext of node.extends) {
|
|
1854
|
-
visit(ext);
|
|
1855
|
-
}
|
|
1856
|
-
}
|
|
1857
|
-
if (node.body) {
|
|
1858
|
-
visit(node.body);
|
|
1859
|
-
}
|
|
1860
|
-
return;
|
|
1861
|
-
} else if (node.type === 'TSInterfaceBody') {
|
|
1862
|
-
// Interface body
|
|
1863
|
-
if (node.body) {
|
|
1864
|
-
for (const member of node.body) {
|
|
1865
|
-
visit(member);
|
|
1866
|
-
}
|
|
1867
|
-
}
|
|
1868
|
-
return;
|
|
1869
|
-
} else if (node.type === 'TSTypeAliasDeclaration') {
|
|
1870
|
-
// Type alias
|
|
1871
|
-
if (node.id) {
|
|
1872
|
-
visit(node.id);
|
|
1873
|
-
}
|
|
1874
|
-
if (node.typeParameters) {
|
|
1875
|
-
visit(node.typeParameters);
|
|
1876
|
-
}
|
|
1877
|
-
if (node.typeAnnotation) {
|
|
1878
|
-
visit(node.typeAnnotation);
|
|
1879
|
-
}
|
|
1880
|
-
return;
|
|
1881
|
-
} else if (node.type === 'TSEnumDeclaration') {
|
|
1882
|
-
// Visit id and members
|
|
1883
|
-
if (node.id) {
|
|
1884
|
-
visit(node.id);
|
|
1885
|
-
}
|
|
1886
|
-
if (node.members) {
|
|
1887
|
-
for (const member of node.members) {
|
|
1888
|
-
visit(member);
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1891
|
-
return;
|
|
1892
|
-
} else if (node.type === 'TSEnumMember') {
|
|
1893
|
-
// Visit id and initializer
|
|
1894
|
-
if (node.id) {
|
|
1895
|
-
visit(node.id);
|
|
1896
|
-
}
|
|
1897
|
-
if (node.initializer) {
|
|
1898
|
-
visit(node.initializer);
|
|
1899
|
-
}
|
|
1900
|
-
return;
|
|
1901
|
-
} else if (node.type === 'TSModuleDeclaration') {
|
|
1902
|
-
// Namespace/module declaration
|
|
1903
|
-
if (node.id) {
|
|
1904
|
-
visit(node.id);
|
|
1905
|
-
}
|
|
1906
|
-
if (node.body) {
|
|
1907
|
-
visit(node.body);
|
|
1908
|
-
}
|
|
1909
|
-
return;
|
|
1910
|
-
} else if (node.type === 'TSModuleBlock') {
|
|
1911
|
-
// Module body
|
|
1912
|
-
if (node.body) {
|
|
1913
|
-
for (const statement of node.body) {
|
|
1914
|
-
visit(statement);
|
|
1915
|
-
}
|
|
1916
|
-
}
|
|
1917
|
-
return;
|
|
1918
|
-
} else if (node.type === 'TSNamedTupleMember') {
|
|
1919
|
-
// Named tuple member: [name: Type]
|
|
1920
|
-
if (node.label) {
|
|
1921
|
-
visit(node.label);
|
|
1922
|
-
}
|
|
1923
|
-
if (node.elementType) {
|
|
1924
|
-
visit(node.elementType);
|
|
1925
|
-
}
|
|
1926
|
-
return;
|
|
1927
|
-
} else if (node.type === 'TSRestType') {
|
|
1928
|
-
// Rest type: ...T[]
|
|
1929
|
-
if (node.typeAnnotation) {
|
|
1930
|
-
visit(node.typeAnnotation);
|
|
1931
|
-
}
|
|
1932
|
-
return;
|
|
1933
|
-
} else if (node.type === 'TSOptionalType') {
|
|
1934
|
-
// Optional type: T?
|
|
1935
|
-
if (node.typeAnnotation) {
|
|
1936
|
-
visit(node.typeAnnotation);
|
|
1937
|
-
}
|
|
1938
|
-
return;
|
|
1939
|
-
} else if (
|
|
1940
|
-
node.type === 'TSAnyKeyword' ||
|
|
1941
|
-
node.type === 'TSUnknownKeyword' ||
|
|
1942
|
-
node.type === 'TSNumberKeyword' ||
|
|
1943
|
-
node.type === 'TSObjectKeyword' ||
|
|
1944
|
-
node.type === 'TSBooleanKeyword' ||
|
|
1945
|
-
node.type === 'TSBigIntKeyword' ||
|
|
1946
|
-
node.type === 'TSStringKeyword' ||
|
|
1947
|
-
node.type === 'TSSymbolKeyword' ||
|
|
1948
|
-
node.type === 'TSVoidKeyword' ||
|
|
1949
|
-
node.type === 'TSUndefinedKeyword' ||
|
|
1950
|
-
node.type === 'TSNullKeyword' ||
|
|
1951
|
-
node.type === 'TSNeverKeyword' ||
|
|
1952
|
-
node.type === 'TSThisType' ||
|
|
1953
|
-
node.type === 'TSIntrinsicKeyword'
|
|
1954
|
-
) {
|
|
1955
|
-
// Primitive type keywords - leaf nodes, no children
|
|
1956
|
-
return;
|
|
1957
|
-
} else if (node.type === 'TSDeclareFunction') {
|
|
1958
|
-
// TypeScript declare function: declare function foo(): void;
|
|
1959
|
-
// Visit in source order: id, typeParameters, params, returnType
|
|
1960
|
-
if (node.id) {
|
|
1961
|
-
visit(node.id);
|
|
1962
|
-
}
|
|
1963
|
-
if (node.typeParameters) {
|
|
1964
|
-
visit(node.typeParameters);
|
|
1965
|
-
}
|
|
1966
|
-
if (node.params) {
|
|
1967
|
-
for (const param of node.params) {
|
|
1968
|
-
visit(param);
|
|
1969
|
-
}
|
|
1970
|
-
}
|
|
1971
|
-
if (node.returnType) {
|
|
1972
|
-
visit(node.returnType);
|
|
1973
|
-
}
|
|
1974
|
-
return;
|
|
1975
|
-
} else if (node.type === 'TSExportAssignment') {
|
|
1976
|
-
// TypeScript export assignment: export = foo;
|
|
1977
|
-
if (node.expression) {
|
|
1978
|
-
visit(node.expression);
|
|
1979
|
-
}
|
|
1980
|
-
return;
|
|
1981
|
-
} else if (node.type === 'TSNamespaceExportDeclaration') {
|
|
1982
|
-
// TypeScript namespace export: export as namespace foo;
|
|
1983
|
-
if (node.id) {
|
|
1984
|
-
visit(node.id);
|
|
1985
|
-
}
|
|
1986
|
-
return;
|
|
1987
|
-
} else if (node.type === 'TSExternalModuleReference') {
|
|
1988
|
-
// TypeScript external module reference: import foo = require('bar');
|
|
1989
|
-
if (node.expression) {
|
|
1990
|
-
visit(node.expression);
|
|
1991
|
-
}
|
|
1992
|
-
return;
|
|
1993
|
-
} else if (node.type === 'TSInstantiationExpression') {
|
|
1994
|
-
// TypeScript instantiation expression: new Foo<T>()
|
|
1995
|
-
if (node.expression) {
|
|
1996
|
-
visit(node.expression);
|
|
1997
|
-
}
|
|
1998
|
-
if (node.typeArguments) {
|
|
1999
|
-
visit(node.typeArguments);
|
|
2000
|
-
}
|
|
2001
|
-
return;
|
|
2002
|
-
}
|
|
2003
|
-
|
|
2004
|
-
throw new Error(`Unhandled AST node type in mapping walker: ${node.type}`);
|
|
2005
|
-
},
|
|
2006
|
-
});
|
|
2007
|
-
|
|
2008
|
-
for (const token of tokens) {
|
|
2009
|
-
const source_text = token.source ?? '';
|
|
2010
|
-
const gen_text = token.generated;
|
|
2011
|
-
const source_start = loc_to_offset(
|
|
2012
|
-
token.loc.start.line,
|
|
2013
|
-
token.loc.start.column,
|
|
2014
|
-
src_line_offsets,
|
|
2015
|
-
);
|
|
2016
|
-
const source_length = source_text.length;
|
|
2017
|
-
const gen_length = gen_text.length;
|
|
2018
|
-
const gen_line_col = get_generated_position(
|
|
2019
|
-
token.loc.start.line,
|
|
2020
|
-
token.loc.start.column,
|
|
2021
|
-
src_to_gen_map,
|
|
2022
|
-
);
|
|
2023
|
-
const gen_start = loc_to_offset(gen_line_col.line, gen_line_col.column, gen_line_offsets);
|
|
2024
|
-
|
|
2025
|
-
/** @type {CustomMappingData} */
|
|
2026
|
-
const customData = {};
|
|
2027
|
-
|
|
2028
|
-
// Add optional metadata from token if present
|
|
2029
|
-
if ('wordHighlight' in token.metadata) {
|
|
2030
|
-
customData.wordHighlight = token.metadata.wordHighlight;
|
|
2031
|
-
}
|
|
2032
|
-
if ('suppressedDiagnostics' in token.metadata) {
|
|
2033
|
-
customData.suppressedDiagnostics = token.metadata.suppressedDiagnostics;
|
|
2034
|
-
}
|
|
2035
|
-
if ('hover' in token.metadata) {
|
|
2036
|
-
customData.hover = token.metadata.hover;
|
|
2037
|
-
}
|
|
2038
|
-
if ('definition' in token.metadata) {
|
|
2039
|
-
customData.definition = token.metadata.definition;
|
|
2040
|
-
}
|
|
2041
|
-
|
|
2042
|
-
mappings.push({
|
|
2043
|
-
sourceOffsets: [source_start],
|
|
2044
|
-
generatedOffsets: [gen_start],
|
|
2045
|
-
lengths: [source_length],
|
|
2046
|
-
generatedLengths: [gen_length],
|
|
2047
|
-
data: {
|
|
2048
|
-
...(token.mappingData ?? mapping_data),
|
|
2049
|
-
customData,
|
|
2050
|
-
},
|
|
2051
|
-
});
|
|
2052
|
-
}
|
|
2053
|
-
|
|
2054
|
-
// Sort mappings by start position, but prioritize narrower ranges that are fully contained
|
|
2055
|
-
// within wider ones. This ensures that specific tokens (like identifiers) take precedence
|
|
2056
|
-
// over broader ranges (like `if` consequent blocks) during language server lookups.
|
|
2057
|
-
// Otherwise, volar may pick the wrong mapping for diagnostics or other features.
|
|
2058
|
-
mappings.sort((a, b) => {
|
|
2059
|
-
const aStart = a.sourceOffsets[0];
|
|
2060
|
-
const aEnd = aStart + a.lengths[0];
|
|
2061
|
-
const bStart = b.sourceOffsets[0];
|
|
2062
|
-
const bEnd = bStart + b.lengths[0];
|
|
2063
|
-
|
|
2064
|
-
if (aStart === bStart && aEnd === bEnd) {
|
|
2065
|
-
// ranges are identical
|
|
2066
|
-
return 0;
|
|
2067
|
-
}
|
|
2068
|
-
|
|
2069
|
-
// Check if one range is fully contained within the other
|
|
2070
|
-
const bInsideA = bStart >= aStart && bEnd <= aEnd;
|
|
2071
|
-
const aInsideB = aStart >= bStart && aEnd <= bEnd;
|
|
2072
|
-
|
|
2073
|
-
if (bInsideA) {
|
|
2074
|
-
// B (narrower) should come first
|
|
2075
|
-
return 1;
|
|
2076
|
-
}
|
|
2077
|
-
if (aInsideB) {
|
|
2078
|
-
// A (narrower) should come first
|
|
2079
|
-
return -1;
|
|
2080
|
-
}
|
|
2081
|
-
|
|
2082
|
-
// Neither contains the other - sort by start position
|
|
2083
|
-
return aStart - bStart;
|
|
2084
|
-
});
|
|
2085
|
-
|
|
2086
|
-
// Add a mapping for the very beginning of the file to handle import additions
|
|
2087
|
-
// This ensures that code actions adding imports at the top work correctly
|
|
2088
|
-
if (!isImportDeclarationPresent && mappings.length > 0 && mappings[0].sourceOffsets[0] > 0) {
|
|
2089
|
-
mappings.unshift({
|
|
2090
|
-
sourceOffsets: [0],
|
|
2091
|
-
generatedOffsets: [0],
|
|
2092
|
-
lengths: [1],
|
|
2093
|
-
generatedLengths: [1],
|
|
2094
|
-
data: {
|
|
2095
|
-
...mapping_data,
|
|
2096
|
-
customData: {},
|
|
2097
|
-
},
|
|
2098
|
-
});
|
|
2099
|
-
}
|
|
2100
|
-
|
|
2101
|
-
/** @type {CodeMapping[]} */
|
|
2102
|
-
const cssMappings = [];
|
|
2103
|
-
for (let i = 0; i < css_regions.length; i++) {
|
|
2104
|
-
const region = css_regions[i];
|
|
2105
|
-
cssMappings.push({
|
|
2106
|
-
sourceOffsets: [region.start],
|
|
2107
|
-
generatedOffsets: [0],
|
|
2108
|
-
lengths: [region.content.length],
|
|
2109
|
-
generatedLengths: [region.content.length],
|
|
2110
|
-
data: {
|
|
2111
|
-
...mapping_data,
|
|
2112
|
-
customData: {
|
|
2113
|
-
embeddedId: region.id,
|
|
2114
|
-
content: region.content,
|
|
2115
|
-
},
|
|
2116
|
-
},
|
|
2117
|
-
});
|
|
2118
|
-
}
|
|
2119
|
-
|
|
2120
|
-
return {
|
|
2121
|
-
code: generated_code,
|
|
2122
|
-
mappings,
|
|
2123
|
-
cssMappings,
|
|
2124
|
-
};
|
|
2125
|
-
}
|