@nudojs/service 4.0.0 → 5.0.0-beta.0

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.
@@ -0,0 +1,651 @@
1
+ import {
2
+ collectAbsBindingsFromGraph,
3
+ collectEnvNames,
4
+ isBPathCapable,
5
+ locFromNode,
6
+ mockDirectivesToAbsSeeds
7
+ } from "./chunk-QAFMPM2E.js";
8
+ import {
9
+ builtinProtoMember,
10
+ builtinProtoMemberNames,
11
+ describeAbsMember
12
+ } from "./chunk-YLALZXTZ.js";
13
+ import {
14
+ preloadPathEnvs
15
+ } from "./chunk-PVJIMQRI.js";
16
+
17
+ // src/lsp-surface.ts
18
+ import { dirname } from "path";
19
+ import traverse from "@babel/traverse";
20
+ import {
21
+ generalizeFromAst,
22
+ formatAbs,
23
+ formatAbsMultiline,
24
+ formatShape,
25
+ interfaceTierOf
26
+ } from "@nudojs/core";
27
+ import { parse, extractDirectives, extractFileDirectives } from "@nudojs/parser";
28
+ function getCasesForFile(filePath, source) {
29
+ const ast = parse(source);
30
+ const functions = extractDirectives(ast);
31
+ return functions.map((fn) => {
32
+ const cases = fn.directives.filter((d) => d.kind === "case").map((d, i) => ({ name: d.name, index: i }));
33
+ return { functionName: fn.name, cases, loc: locFromNode(fn.node) };
34
+ });
35
+ }
36
+ async function getTypeAtPositionAsync(filePath, source, line, column, activeCases) {
37
+ const envNames = collectEnvNames(filePath, source, false);
38
+ if (envNames.length > 0) {
39
+ await preloadPathEnvs(envNames, dirname(filePath));
40
+ }
41
+ return getTypeAtPosition(filePath, source, line, column, activeCases);
42
+ }
43
+ async function getAbsAtPositionAsync(filePath, source, line, column, activeCases) {
44
+ const envNames = collectEnvNames(filePath, source, false);
45
+ if (envNames.length > 0) {
46
+ await preloadPathEnvs(envNames, dirname(filePath));
47
+ }
48
+ return getAbsAtPosition(filePath, source, line, column, activeCases);
49
+ }
50
+ function positionInsideCaseFunction(source, ast, line) {
51
+ try {
52
+ const enclosing = findEnclosingFunction(extractDirectives(ast), line);
53
+ return !!enclosing && enclosing.directives.some((d) => d.kind === "case");
54
+ } catch {
55
+ return false;
56
+ }
57
+ }
58
+ function absFromBPath(filePath, source, line, column, ast, envNames) {
59
+ if (!isBPathCapable(source, envNames)) return null;
60
+ if (positionInsideCaseFunction(source, ast, line)) return null;
61
+ try {
62
+ const seeds = mockDirectivesToAbsSeeds(extractDirectives(ast), { fromFile: filePath });
63
+ const ident = findIdentNameAtPosition(source, line, column, ast);
64
+ if (ident) {
65
+ const binds = collectAbsBindingsFromGraph(source, filePath, {
66
+ seedVars: seeds.seedVars,
67
+ seedFns: seeds.seedFns
68
+ });
69
+ const bound = binds.get(ident);
70
+ if (bound) return bound;
71
+ }
72
+ } catch {
73
+ }
74
+ return null;
75
+ }
76
+ function absFromCaseReplay(_filePath, _source, _line, _column, _ast, _activeCases) {
77
+ return null;
78
+ }
79
+ function getAbsAtPosition(filePath, source, line, column, activeCases) {
80
+ const ast = parse(source);
81
+ const envNames = extractFileDirectives(ast).filter((d) => d.kind === "env").flatMap((d) => d.envs);
82
+ const fromB = absFromBPath(filePath, source, line, column, ast, envNames);
83
+ if (fromB) return fromB;
84
+ if (positionInsideCaseFunction(source, ast, line)) {
85
+ const fromCase = absFromCaseReplay(filePath, source, line, column, ast, activeCases);
86
+ if (fromCase) return fromCase;
87
+ }
88
+ return null;
89
+ }
90
+ function getTypeAtPosition(filePath, source, line, column, activeCases) {
91
+ return getAbsAtPosition(filePath, source, line, column, activeCases);
92
+ }
93
+ function getHoverAtPosition(filePath, source, line, column, activeCases, opts) {
94
+ let file;
95
+ try {
96
+ file = parse(source);
97
+ } catch {
98
+ file = void 0;
99
+ }
100
+ const envNames = collectEnvNames(filePath, source, false);
101
+ const fnName = findFunctionNameAtPosition(source, line, column, file);
102
+ const tier = fnName !== void 0 ? interfaceTierOf(source, fnName, filePath, opts ?? {}) : void 0;
103
+ let gDisplay;
104
+ let gAbs;
105
+ let gMulti;
106
+ if (fnName) {
107
+ try {
108
+ const g = generalizeFromAst(fnName, source, file ? { file } : {});
109
+ if (g) {
110
+ gDisplay = g.display;
111
+ gAbs = formatAbs(g.symbolic);
112
+ gMulti = formatAbsMultiline(g.symbolic, fnName);
113
+ }
114
+ } catch {
115
+ }
116
+ }
117
+ const withTier = (info) => {
118
+ if (!info || !tier) return info;
119
+ return {
120
+ ...info,
121
+ interfaceSource: tier.source,
122
+ ...tier.display !== void 0 ? { interfaceDisplay: tier.display } : {}
123
+ };
124
+ };
125
+ const attachIntension = (info) => {
126
+ if (!gDisplay) return withTier(info);
127
+ if (!info) {
128
+ return withTier({ typeText: gDisplay, intension: gDisplay, abs: gAbs, absMultiline: gMulti });
129
+ }
130
+ return withTier({
131
+ ...info,
132
+ intension: gDisplay,
133
+ // 外延侧已有更准 Abs 时保留;否则用 symbolic 兜底
134
+ abs: info.abs ?? gAbs,
135
+ absMultiline: info.absMultiline ?? gMulti
136
+ });
137
+ };
138
+ const insideCaseFn = positionInsideCaseFunction(
139
+ source,
140
+ file ?? parse(source),
141
+ line
142
+ );
143
+ if (!insideCaseFn) {
144
+ const fromB = absFromBPath(
145
+ filePath,
146
+ source,
147
+ line,
148
+ column,
149
+ file ?? parse(source),
150
+ envNames
151
+ );
152
+ if (fromB) {
153
+ const absLine = formatAbs(fromB);
154
+ const absMulti = formatAbsMultiline(fromB, void 0);
155
+ return attachIntension({ typeText: absLine, abs: absLine, absMultiline: absMulti });
156
+ }
157
+ } else {
158
+ const fromCase = absFromCaseReplay(
159
+ filePath,
160
+ source,
161
+ line,
162
+ column,
163
+ file ?? parse(source),
164
+ activeCases
165
+ );
166
+ if (fromCase) {
167
+ const absLine = formatAbs(fromCase);
168
+ const absMulti = formatAbsMultiline(fromCase, void 0);
169
+ return attachIntension({ typeText: absLine, abs: absLine, absMultiline: absMulti });
170
+ }
171
+ }
172
+ const absFallback = getAbsAtPosition(filePath, source, line, column, activeCases);
173
+ if (absFallback) {
174
+ const absLine = formatAbs(absFallback);
175
+ const absMulti = formatAbsMultiline(absFallback, void 0);
176
+ return attachIntension({ typeText: absLine, abs: absLine, absMultiline: absMulti });
177
+ }
178
+ const ident = findIdentNameAtPosition(source, line, column, file);
179
+ if (ident && !fnName && !insideCaseFn) {
180
+ try {
181
+ if (isBPathCapable(source, []) || !/\brequire\s*\(/.test(source)) {
182
+ const seeds = mockDirectivesToAbsSeeds(extractDirectives(file ?? parse(source)), {
183
+ fromFile: filePath
184
+ });
185
+ const absBinds = collectAbsBindingsFromGraph(source, filePath, {
186
+ seedVars: seeds.seedVars,
187
+ seedFns: seeds.seedFns
188
+ });
189
+ const absBound = absBinds.get(ident);
190
+ if (absBound) {
191
+ const absLine = formatAbs(absBound);
192
+ const absMulti = formatAbsMultiline(absBound, ident);
193
+ return attachIntension({ typeText: absLine, abs: absLine, absMultiline: absMulti });
194
+ }
195
+ }
196
+ } catch {
197
+ }
198
+ }
199
+ if (tier && gDisplay) {
200
+ return withTier({
201
+ typeText: gDisplay,
202
+ intension: gDisplay,
203
+ abs: gAbs,
204
+ absMultiline: gMulti
205
+ });
206
+ }
207
+ return null;
208
+ }
209
+ function findIdentNameAtPosition(source, line, column, fileAst) {
210
+ try {
211
+ const ast = fileAst ?? parse(source);
212
+ let found;
213
+ traverse(ast, {
214
+ Identifier(path) {
215
+ const loc = path.node.loc;
216
+ if (!loc) return;
217
+ if (loc.start.line !== line) return;
218
+ if (column < loc.start.column || column > loc.end.column) return;
219
+ found = path.node.name;
220
+ }
221
+ });
222
+ return found;
223
+ } catch {
224
+ return void 0;
225
+ }
226
+ }
227
+ function findFunctionNameAtPosition(source, line, column, fileAst) {
228
+ try {
229
+ const ast = fileAst ?? parse(source);
230
+ let found;
231
+ traverse(ast, {
232
+ Identifier(path) {
233
+ const loc = path.node.loc;
234
+ if (!loc) return;
235
+ if (loc.start.line !== line) return;
236
+ if (column < loc.start.column || column > loc.end.column) return;
237
+ const parent = path.parent;
238
+ if (parent.type === "FunctionDeclaration" && parent.id === path.node) {
239
+ found = path.node.name;
240
+ } else if (parent.type === "CallExpression" && parent.callee === path.node) {
241
+ found = path.node.name;
242
+ }
243
+ }
244
+ });
245
+ return found;
246
+ } catch {
247
+ return void 0;
248
+ }
249
+ }
250
+ function findEnclosingFunction(functions, line) {
251
+ for (const fn of functions) {
252
+ const loc = fn.node.loc;
253
+ if (!loc) continue;
254
+ if (loc.start.line <= line && loc.end.line >= line) {
255
+ return fn;
256
+ }
257
+ }
258
+ return null;
259
+ }
260
+ function getCompletionsAtPosition(filePath, source, line, column) {
261
+ const textBefore = getTextBeforePosition(source, line, column);
262
+ const dotMatch = textBefore.match(/(\w+)\.\s*\w*$/);
263
+ if (!dotMatch) return getVariableCompletions(filePath, source);
264
+ const objName = dotMatch[1];
265
+ const safeSource = sanitizeSourceForParsing(source);
266
+ let ast;
267
+ try {
268
+ ast = parse(safeSource);
269
+ } catch {
270
+ try {
271
+ ast = parse(source);
272
+ } catch {
273
+ return [];
274
+ }
275
+ }
276
+ try {
277
+ const seeds = mockDirectivesToAbsSeeds(extractDirectives(ast), { fromFile: filePath });
278
+ const binds = collectAbsBindingsFromGraph(source, filePath, {
279
+ seedVars: seeds.seedVars,
280
+ seedFns: seeds.seedFns
281
+ });
282
+ const bound = binds.get(objName);
283
+ if (bound && bound.shape.k !== "unknown" && bound.shape.k !== "never") {
284
+ const absCompletions = getCompletionsForAbs(bound);
285
+ if (absCompletions.length > 0) return absCompletions;
286
+ }
287
+ } catch {
288
+ }
289
+ return [];
290
+ }
291
+ function sanitizeSourceForParsing(source) {
292
+ return source.replace(/(\w+)\.\s*$/gm, "$1._ ");
293
+ }
294
+ function getTextBeforePosition(source, line, column) {
295
+ const lines = source.split("\n");
296
+ if (line < 1 || line > lines.length) return "";
297
+ return lines[line - 1].slice(0, column);
298
+ }
299
+ function getVariableCompletions(filePath, source) {
300
+ const ast = parse(source);
301
+ try {
302
+ const seeds = mockDirectivesToAbsSeeds(extractDirectives(ast), { fromFile: filePath });
303
+ const binds = collectAbsBindingsFromGraph(source, filePath, {
304
+ seedVars: seeds.seedVars,
305
+ seedFns: seeds.seedFns
306
+ });
307
+ if (binds.size > 0) {
308
+ const completions = [];
309
+ for (const [name, absVal] of binds) {
310
+ if (name.startsWith("__export_")) continue;
311
+ completions.push({
312
+ label: name,
313
+ kind: absVal.shape.k === "fn" ? "method" : "variable",
314
+ detail: absDetail(absVal)
315
+ });
316
+ }
317
+ if (completions.length > 0) return completions;
318
+ }
319
+ } catch {
320
+ }
321
+ return [];
322
+ }
323
+ function builtinMemberAbs(className, member) {
324
+ return builtinProtoMember(className, member);
325
+ }
326
+ function builtinProtoMembers(className) {
327
+ return builtinProtoMemberNames(className);
328
+ }
329
+ function describeMember(label, a, fallbackClass) {
330
+ if (a) {
331
+ const s = describeAbsMember(a);
332
+ if (s) return s;
333
+ }
334
+ return `${label}(\u2026)@${fallbackClass}`;
335
+ }
336
+ function getPromiseCompletions() {
337
+ return builtinProtoMembers("Promise").map((m) => ({
338
+ label: m,
339
+ kind: "method",
340
+ detail: describeMember(m, builtinMemberAbs("Promise", m), "Promise")
341
+ }));
342
+ }
343
+ function getStringCompletions() {
344
+ const completions = [];
345
+ for (const m of builtinProtoMembers("String")) {
346
+ completions.push({
347
+ label: m,
348
+ kind: "method",
349
+ detail: describeMember(m, builtinMemberAbs("String", m), "String")
350
+ });
351
+ }
352
+ completions.push({ label: "length", kind: "property", detail: "number" });
353
+ return completions;
354
+ }
355
+ function absDetail(a) {
356
+ try {
357
+ return formatShape(a);
358
+ } catch {
359
+ return formatAbs(a);
360
+ }
361
+ }
362
+ function absIsFn(a) {
363
+ return a.shape.k === "fn";
364
+ }
365
+ function getCompletionsForAbs(a) {
366
+ const s = a.shape;
367
+ switch (s.k) {
368
+ case "obj": {
369
+ const completions = [];
370
+ for (const [key, slot] of Object.entries(s.slots)) {
371
+ completions.push({
372
+ label: key,
373
+ kind: absIsFn(slot.value) ? "method" : "property",
374
+ detail: absDetail(slot.value)
375
+ });
376
+ }
377
+ return completions;
378
+ }
379
+ case "brand":
380
+ return getCompletionsForAbs(s.shape);
381
+ case "sum":
382
+ return getSumCompletions(s.members);
383
+ case "tuple":
384
+ if (a.conf === "exact") return getArrayCompletionsAbs(s.elements.length);
385
+ return [];
386
+ case "arr":
387
+ return getArrayCompletionsAbs(void 0);
388
+ case "eff":
389
+ if (s.eff === "promise") return getPromiseCompletions();
390
+ return [];
391
+ case "prim":
392
+ if (s.type === "string") return getStringCompletions();
393
+ return [];
394
+ default:
395
+ return [];
396
+ }
397
+ }
398
+ function getArrayCompletionsAbs(tupleLen) {
399
+ const completions = [];
400
+ for (const m of builtinProtoMembers("Array")) {
401
+ const detail = describeMember(m, builtinMemberAbs("Array", m), "Array");
402
+ completions.push({ label: m, kind: "method", detail });
403
+ }
404
+ completions.push({
405
+ label: "length",
406
+ kind: "property",
407
+ detail: tupleLen !== void 0 ? `${tupleLen}` : "number"
408
+ });
409
+ return completions;
410
+ }
411
+ function getSumCompletions(members) {
412
+ if (members.length === 0) return [];
413
+ const labelsByMember = members.map((m) => getCompletionsForAbs(m));
414
+ const baseIdx = labelsByMember.findIndex((labels) => labels.length > 0);
415
+ if (baseIdx === -1) return [];
416
+ const common = [];
417
+ for (const base of labelsByMember[baseIdx]) {
418
+ let allPresent = true;
419
+ const memberTypes = [base.detail ?? base.label];
420
+ for (let i = 0; i < members.length; i++) {
421
+ if (i === baseIdx) continue;
422
+ const labels = labelsByMember[i];
423
+ if (labels.length === 0) continue;
424
+ const hit = labels.find((l) => l.label === base.label);
425
+ if (!hit) {
426
+ allPresent = false;
427
+ break;
428
+ }
429
+ memberTypes.push(hit.detail ?? hit.label);
430
+ }
431
+ if (allPresent) {
432
+ common.push({ ...base, detail: memberTypes.join(" | ") });
433
+ }
434
+ }
435
+ return common;
436
+ }
437
+
438
+ // src/semantic-tokens.ts
439
+ import { parse as parse2 } from "@nudojs/parser";
440
+ import {
441
+ interfaceTierOf as interfaceTierOf2
442
+ } from "@nudojs/core";
443
+ var SEMANTIC_TOKEN_TYPES = [
444
+ "function",
445
+ "variable",
446
+ "parameter",
447
+ "property",
448
+ "type",
449
+ "keyword",
450
+ "string",
451
+ "number",
452
+ "comment",
453
+ "decorator",
454
+ "method"
455
+ ];
456
+ var SEMANTIC_TOKEN_MODIFIERS = [
457
+ "declaration",
458
+ "readonly",
459
+ "deprecated",
460
+ "unreachable",
461
+ /** handwritten:显式契约(侧车手写 / @nudo:contract) */
462
+ "contract",
463
+ /** generated:侧车 @generated 段 */
464
+ "generated",
465
+ /** derived:implicit 展示档(非义务契约) */
466
+ "derived"
467
+ ];
468
+ function encodeSemanticTokens(tokens) {
469
+ const result = [];
470
+ let prevLine = 0;
471
+ let prevChar = 0;
472
+ for (const token of tokens) {
473
+ const deltaLine = token.line - prevLine;
474
+ const deltaChar = deltaLine === 0 ? token.char - prevChar : token.char;
475
+ result.push(deltaLine, deltaChar, token.length, token.typeIndex, token.modifierBitmask);
476
+ prevLine = token.line;
477
+ prevChar = token.char;
478
+ }
479
+ return result;
480
+ }
481
+ var TYPE_FUNCTION = SEMANTIC_TOKEN_TYPES.indexOf("function");
482
+ var TYPE_VARIABLE = SEMANTIC_TOKEN_TYPES.indexOf("variable");
483
+ var TYPE_PARAMETER = SEMANTIC_TOKEN_TYPES.indexOf("parameter");
484
+ var TYPE_PROPERTY = SEMANTIC_TOKEN_TYPES.indexOf("property");
485
+ var TYPE_METHOD = SEMANTIC_TOKEN_TYPES.indexOf("method");
486
+ var MOD_DECLARATION = 1 << SEMANTIC_TOKEN_MODIFIERS.indexOf("declaration");
487
+ var MOD_CONTRACT = 1 << SEMANTIC_TOKEN_MODIFIERS.indexOf("contract");
488
+ var MOD_GENERATED = 1 << SEMANTIC_TOKEN_MODIFIERS.indexOf("generated");
489
+ var MOD_DERIVED = 1 << SEMANTIC_TOKEN_MODIFIERS.indexOf("derived");
490
+ function interfaceTierModifierBit(src) {
491
+ return src === "handwritten" ? MOD_CONTRACT : src === "generated" ? MOD_GENERATED : MOD_DERIVED;
492
+ }
493
+ function collectFunctionBindingNames(filePath, source, _ast) {
494
+ try {
495
+ const binds = collectAbsBindingsFromGraph(source, filePath);
496
+ if (binds.size > 0) {
497
+ const fns = /* @__PURE__ */ new Set();
498
+ for (const [name, a] of binds) {
499
+ if (a.shape.k === "fn") fns.add(name);
500
+ }
501
+ return fns;
502
+ }
503
+ } catch {
504
+ }
505
+ return /* @__PURE__ */ new Set();
506
+ }
507
+ function buildSemanticTokens(filePath, source, opts) {
508
+ let ast;
509
+ try {
510
+ ast = parse2(source);
511
+ } catch {
512
+ return [];
513
+ }
514
+ const functionNames = collectFunctionBindingNames(filePath, source, ast);
515
+ const program = ast.program ?? ast;
516
+ const topLevelDeclarators = /* @__PURE__ */ new Set();
517
+ const topLevelFnDeclNodes = /* @__PURE__ */ new Set();
518
+ for (const stmt of program.body ?? []) {
519
+ const decl = stmt.type === "ExportNamedDeclaration" || stmt.type === "ExportDefaultDeclaration" ? stmt.declaration ?? null : stmt;
520
+ if (decl && decl.type === "VariableDeclaration") {
521
+ for (const d of decl.declarations) {
522
+ topLevelDeclarators.add(d);
523
+ }
524
+ }
525
+ if (decl && decl.type === "FunctionDeclaration" && decl.id) {
526
+ topLevelFnDeclNodes.add(decl);
527
+ }
528
+ }
529
+ const tierOpts = {
530
+ ...opts?.loadModule ? { loadModule: opts.loadModule } : {},
531
+ ...opts?.autoBind !== void 0 ? { autoBind: opts.autoBind } : {}
532
+ };
533
+ const tierModCache = /* @__PURE__ */ new Map();
534
+ const tierModFor = (name) => {
535
+ const cached = tierModCache.get(name);
536
+ if (cached !== void 0) return cached;
537
+ let bit = 0;
538
+ try {
539
+ const tier = interfaceTierOf2(source, name, filePath, tierOpts);
540
+ if (tier) bit = interfaceTierModifierBit(tier.source);
541
+ } catch {
542
+ bit = 0;
543
+ }
544
+ tierModCache.set(name, bit);
545
+ return bit;
546
+ };
547
+ const tokens = [];
548
+ const pushIdentifier = (id, typeIndex, extraMod = 0) => {
549
+ const loc = id.loc;
550
+ const name = id.name;
551
+ if (!loc || typeof name !== "string") return;
552
+ tokens.push({
553
+ line: loc.start.line - 1,
554
+ char: loc.start.column,
555
+ length: name.length,
556
+ typeIndex,
557
+ modifierBitmask: MOD_DECLARATION | extraMod
558
+ });
559
+ };
560
+ const collectParams = (params) => {
561
+ for (const p of params) {
562
+ if (!p) continue;
563
+ if (p.type === "Identifier") pushIdentifier(p, TYPE_PARAMETER);
564
+ else if (p.type === "AssignmentPattern" && p.left?.type === "Identifier") {
565
+ pushIdentifier(p.left, TYPE_PARAMETER);
566
+ } else if (p.type === "RestElement" && p.argument?.type === "Identifier") {
567
+ pushIdentifier(p.argument, TYPE_PARAMETER);
568
+ }
569
+ }
570
+ };
571
+ const isFunctionValue = (name) => functionNames.has(name);
572
+ const visit = (node) => {
573
+ if (!node || typeof node !== "object") return;
574
+ const n = node;
575
+ switch (n.type) {
576
+ case "VariableDeclarator": {
577
+ const id = n.id;
578
+ if (id?.type === "Identifier") {
579
+ const isTopLevel = topLevelDeclarators.has(node);
580
+ const name = id.name;
581
+ const isFn = isTopLevel && isFunctionValue(name);
582
+ const typeIndex = isFn ? TYPE_FUNCTION : TYPE_VARIABLE;
583
+ const extraMod = isFn ? tierModFor(name) : 0;
584
+ pushIdentifier(id, typeIndex, extraMod);
585
+ }
586
+ break;
587
+ }
588
+ case "FunctionDeclaration":
589
+ case "FunctionExpression": {
590
+ const id = n.id;
591
+ if (id?.type === "Identifier") {
592
+ const name = id.name;
593
+ const isTopLevelFnDecl = n.type === "FunctionDeclaration" && topLevelFnDeclNodes.has(node);
594
+ const extraMod = isTopLevelFnDecl ? tierModFor(name) : 0;
595
+ pushIdentifier(id, TYPE_FUNCTION, extraMod);
596
+ }
597
+ collectParams(n.params ?? []);
598
+ break;
599
+ }
600
+ case "ArrowFunctionExpression":
601
+ collectParams(n.params ?? []);
602
+ break;
603
+ case "ObjectMethod": {
604
+ const key = n.key;
605
+ if (key?.type === "Identifier" && !n.computed) pushIdentifier(key, TYPE_METHOD);
606
+ collectParams(n.params ?? []);
607
+ break;
608
+ }
609
+ case "ObjectProperty": {
610
+ const key = n.key;
611
+ const value = n.value;
612
+ if (key?.type === "Identifier" && !n.computed) {
613
+ const isFn = value?.type === "FunctionExpression" || value?.type === "ArrowFunctionExpression";
614
+ pushIdentifier(key, isFn ? TYPE_METHOD : TYPE_PROPERTY);
615
+ }
616
+ break;
617
+ }
618
+ }
619
+ for (const key of Object.keys(n)) {
620
+ if (key === "loc" || key === "start" || key === "end" || key === "leadingComments" || key === "trailingComments" || key === "innerComments") continue;
621
+ const child = n[key];
622
+ if (Array.isArray(child)) {
623
+ for (const item of child) {
624
+ if (item && typeof item === "object" && typeof item.type === "string") {
625
+ visit(item);
626
+ }
627
+ }
628
+ } else if (child && typeof child === "object" && typeof child.type === "string") {
629
+ visit(child);
630
+ }
631
+ }
632
+ };
633
+ visit(program);
634
+ tokens.sort((a, b) => a.line - b.line || a.char - b.char);
635
+ return encodeSemanticTokens(tokens);
636
+ }
637
+
638
+ export {
639
+ getCasesForFile,
640
+ getTypeAtPositionAsync,
641
+ getAbsAtPositionAsync,
642
+ getAbsAtPosition,
643
+ getTypeAtPosition,
644
+ getHoverAtPosition,
645
+ getCompletionsAtPosition,
646
+ SEMANTIC_TOKEN_TYPES,
647
+ SEMANTIC_TOKEN_MODIFIERS,
648
+ encodeSemanticTokens,
649
+ interfaceTierModifierBit,
650
+ buildSemanticTokens
651
+ };