@mirascript/monaco 0.1.39 → 0.1.40

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/dist/lsp/index.js CHANGED
@@ -19,127 +19,7 @@ import {
19
19
  // src/lsp/providers/base.ts
20
20
  import { DefaultVmContext } from "@mirascript/mirascript/subtle";
21
21
 
22
- // src/lsp/utils.ts
23
- import { DiagnosticCode } from "@mirascript/constants";
24
- import {
25
- getVmFunctionInfo,
26
- isVmArray,
27
- isVmExtern,
28
- isVmFunction,
29
- isVmModule,
30
- isVmPrimitive,
31
- isVmRecord,
32
- isVmWrapper,
33
- serialize
34
- } from "@mirascript/mirascript";
35
- import { lib, operations, serializeRecordKey, serializeString } from "@mirascript/mirascript/subtle";
36
- var UNKNOWN_REPR = "/* .. */";
37
- function globalParamsSignature(info) {
38
- if (info == null || !info.params && !info.paramsType) return [["..", "..", ""]];
39
- const paramItems = [];
40
- const params = Object.keys(info.paramsType ?? {});
41
- for (const key of Object.keys(info.params ?? {})) {
42
- if (params.includes(key)) continue;
43
- params.push(key);
44
- }
45
- for (const key of params) {
46
- const type = info.paramsType?.[key] ?? "";
47
- const doc = info.params?.[key] ?? "";
48
- paramItems.push([key, `${key}: ${type || "any"}`, doc ? `\`${key}\`: ${doc}` : ""]);
49
- }
50
- return paramItems;
51
- }
52
- var SIG_WIDTH = 60;
53
- function fnSignature(id, info) {
54
- const prefix = id ? `fn ${id}` : "fn";
55
- const params = globalParamsSignature(info);
56
- const returns = info.returnsType ? ` -> ${info.returnsType}` : "";
57
- return {
58
- params,
59
- returns,
60
- toString() {
61
- let p;
62
- if (this.params.length >= 1 && (prefix.length + this.returns.length > SIG_WIDTH || prefix.length + this.returns.length + params.reduce((a, b) => a + b[1].length, 0) > SIG_WIDTH)) {
63
- p = `(
64
- ${params.map((item) => ` ${item[1]},`).join("\n")}
65
- )`;
66
- } else {
67
- p = `(${params.map((item) => item[1]).join(", ")})`;
68
- }
69
- return `${prefix}${p}${this.returns}`;
70
- }
71
- };
72
- }
73
- function localParamSignature(model, info) {
74
- const {
75
- args,
76
- scope: { params }
77
- } = info;
78
- if (params[0]?.code === DiagnosticCode.ParameterIt) {
79
- return params[0].references.length ? [["it", "it", ""]] : [];
80
- }
81
- return params.map((a, i) => {
82
- const rest = a.code === DiagnosticCode.ParameterRestPattern || a.code === DiagnosticCode.ParameterMutableRest || a.code === DiagnosticCode.ParameterImmutableRest;
83
- const argsInParam = args.filter((arg) => Range.containsRange(a.range, arg.definition.range));
84
- let argName;
85
- if (argsInParam.length > 0) {
86
- argName = argsInParam.map((arg) => model.getValueInRange(arg.definition.range)).join("_");
87
- } else if (rest) {
88
- argName = "args";
89
- } else {
90
- argName = `arg${i}`;
91
- }
92
- if (rest) return [`..${argName}`, `..${argName}`, ""];
93
- return [argName, argName, ""];
94
- });
95
- }
96
- function paramsList(model, info) {
97
- if (!info) return "(..)";
98
- if ("scope" in info) {
99
- return `(${localParamSignature(model, info).map((p) => p[1]).join(", ")})`;
100
- } else {
101
- if (!info.params) return "(..)";
102
- const paramItems = Object.keys(info.params).join(", ");
103
- return `(${paramItems})`;
104
- }
105
- }
106
- function globalFnDoc(info) {
107
- const doc = [];
108
- if (info.summary) {
109
- doc.push(info.summary);
110
- }
111
- const paramDoc = [];
112
- if (info.params) {
113
- for (const [key, value] of Object.entries(info.params)) {
114
- if (!value) continue;
115
- paramDoc.push(`- \`${key}\`: ${value}`);
116
- }
117
- }
118
- if (info.returns) {
119
- paramDoc.push(`- **返回值**: ${info.returns}`);
120
- }
121
- if (paramDoc.length) {
122
- doc.push("", paramDoc.join("\n"));
123
- }
124
- if (info.examples?.length) {
125
- let exp = `### 示例`;
126
- for (const example of info.examples) {
127
- exp += codeblock(example);
128
- }
129
- doc.push("", exp);
130
- }
131
- return doc;
132
- }
133
- function codeblock(value) {
134
- const lang = value.startsWith("\0") ? "mirascript-doc" : "mirascript";
135
- const includeFences = /`{3,}/.exec(value);
136
- const CODEBLOCK_FENCE = includeFences ? "`".repeat(includeFences[0].length + 1) : "```";
137
- return `
138
- ${CODEBLOCK_FENCE}${lang}
139
- ${value}
140
- ${CODEBLOCK_FENCE}
141
- `;
142
- }
22
+ // src/lsp/monaco-utils.ts
143
23
  function strictContainsPosition(range, position) {
144
24
  return !Range.isEmpty(range) && Range.containsPosition(range, position);
145
25
  }
@@ -149,347 +29,110 @@ function wordAt(model, position) {
149
29
  const range = new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn);
150
30
  return { word: word.word, range };
151
31
  }
152
- function serializeForDisplayInner(value, maxWidth) {
153
- if (maxWidth < 10) maxWidth = 10;
154
- if (typeof value === "string") {
155
- if (value.length < maxWidth) {
156
- return serializeString(value);
157
- }
158
- return `${serializeString(value.slice(0, maxWidth))}..`;
32
+
33
+ // src/lsp/compile-result.ts
34
+ import {
35
+ parseDiagnostics,
36
+ DiagnosticCode
37
+ } from "@mirascript/mirascript/subtle";
38
+ var LocalFunctionType = [DiagnosticCode.LocalFunction];
39
+ var LocalVariableType = [
40
+ DiagnosticCode.LocalMutable,
41
+ DiagnosticCode.LocalImmutable,
42
+ DiagnosticCode.LocalConst
43
+ ];
44
+ var ParameterExplicitType = [
45
+ DiagnosticCode.ParameterMutable,
46
+ DiagnosticCode.ParameterImmutable,
47
+ DiagnosticCode.ParameterMutableRest,
48
+ DiagnosticCode.ParameterImmutableRest
49
+ ];
50
+ var ParameterSubPatternType = [
51
+ DiagnosticCode.ParameterSubPatternImmutable,
52
+ DiagnosticCode.ParameterSubPatternMutable
53
+ ];
54
+ var ParameterPatternType = [DiagnosticCode.ParameterPattern, DiagnosticCode.ParameterRestPattern];
55
+ var ParameterItType = [DiagnosticCode.ParameterIt];
56
+ var ParameterDefinitionType = [
57
+ ...ParameterExplicitType,
58
+ ...ParameterSubPatternType,
59
+ ...ParameterItType
60
+ ];
61
+ var ParameterPlaceholderType = [
62
+ ...ParameterExplicitType,
63
+ ...ParameterPatternType,
64
+ ...ParameterItType
65
+ ];
66
+ var LocalDefinitionType = [...LocalVariableType, ...LocalFunctionType, ...ParameterDefinitionType];
67
+ var CompileResult = class {
68
+ constructor(cacheKey, version, source, result) {
69
+ this.cacheKey = cacheKey;
70
+ this.version = version;
71
+ this.source = source;
72
+ this.result = result;
73
+ this.diagnosticsReady = false;
74
+ this._errors = [];
75
+ this._warnings = [];
76
+ this._infos = [];
77
+ this._hints = [];
78
+ this._references = [];
79
+ this._tags = [];
80
+ this._tagsReferences = [];
81
+ this.diagnostics = result.diagnostics;
82
+ this.chunk = result.chunk;
159
83
  }
160
- if (isVmPrimitive(value)) {
161
- return serialize(value);
84
+ /** 源代码诊断信息 */
85
+ get errors() {
86
+ if (!this.diagnosticsReady) {
87
+ this.readDiagnostics();
88
+ }
89
+ return this._errors;
162
90
  }
163
- if (isVmArray(value)) {
164
- const len = value.length;
165
- if (!len) return "[]";
166
- return `[../* x${len} */]`;
91
+ /** 源代码诊断信息 */
92
+ get warnings() {
93
+ if (!this.diagnosticsReady) {
94
+ this.readDiagnostics();
95
+ }
96
+ return this._warnings;
167
97
  }
168
- if (isVmRecord(value)) {
169
- const len = Object.keys(value).length;
170
- if (!len) return "()";
171
- return `(../* x${len} */)`;
98
+ /** 源代码诊断信息 */
99
+ get infos() {
100
+ if (!this.diagnosticsReady) {
101
+ this.readDiagnostics();
102
+ }
103
+ return this._infos;
172
104
  }
173
- if (isVmExtern(value)) {
174
- return `/* <extern ${value.tag}> */`;
105
+ /** 源代码诊断信息 */
106
+ get hints() {
107
+ if (!this.diagnosticsReady) {
108
+ this.readDiagnostics();
109
+ }
110
+ return this._hints;
175
111
  }
176
- return `/* ${operations.$ToString(value)} */`;
177
- }
178
- function serializeField(obj, key, maxWidth) {
179
- const value = getField(obj, key);
180
- if (value === void 0) {
181
- return UNKNOWN_REPR;
112
+ /** 源代码诊断信息 */
113
+ get references() {
114
+ if (!this.diagnosticsReady) {
115
+ this.readDiagnostics();
116
+ }
117
+ return this._references;
182
118
  }
183
- return serializeForDisplayInner(value, maxWidth);
184
- }
185
- function serializeForDisplay(value, maxEntries = 100, maxWidth = 40) {
186
- if (isVmPrimitive(value) || isVmFunction(value)) {
187
- return serializeForDisplayInner(value, maxWidth);
119
+ /** 源代码诊断信息 */
120
+ get tags() {
121
+ if (!this.diagnosticsReady) {
122
+ this.readDiagnostics();
123
+ }
124
+ return this._tags;
188
125
  }
189
- let begin, end;
190
- const entries = [];
191
- let resultLength = 0;
192
- if (isVmArray(value)) {
193
- begin = "[";
194
- end = "]";
195
- const len = value.length;
196
- if (len === 0) return "[]";
197
- for (let i = 0; i < len; i++) {
198
- if (entries.length > maxEntries) {
199
- entries.push(`../* x${value.length - entries.length} */`);
200
- break;
201
- }
202
- const entry = serializeField(value, i, maxWidth - 2);
203
- entries.push(entry);
204
- resultLength += entry.length;
205
- }
206
- } else if (isVmRecord(value)) {
207
- const keys = Object.keys(value);
208
- if (keys.length === 0) return "()";
209
- begin = "(";
210
- end = ")";
211
- for (const key of keys) {
212
- if (entries.length > maxEntries) {
213
- entries.push(`../* x${keys.length - entries.length} */`);
214
- break;
215
- }
216
- const sk = serializeRecordKey(key);
217
- const sv = serializeField(value, key, maxWidth - sk.length - 4);
218
- const entry = `${sk}: ${sv}`;
219
- entries.push(entry);
220
- resultLength += entry.length;
221
- }
222
- } else {
223
- const hint = serializeForDisplayInner(value, 100);
224
- const isArray = value.isArrayLike();
225
- begin = `${hint} ${isArray ? "[" : "("}`;
226
- end = isArray ? "]" : ")";
227
- const keys = value.keys();
228
- if (keys.length === 0 && !isArray) {
229
- if (typeof value.value == "object") {
230
- for (const key of Object.getOwnPropertyNames(value.value)) {
231
- if (value.has(key)) keys.push(key);
232
- }
233
- } else {
234
- begin = hint;
235
- end = "";
236
- }
237
- }
238
- for (const [index, key] of keys.entries()) {
239
- if (entries.length > maxEntries) {
240
- entries.push(`../* x${keys.length - entries.length} */`);
241
- break;
242
- }
243
- let entry;
244
- if (isArray && String(index) === key) {
245
- entry = serializeForDisplayInner(value.get(key) ?? null, maxWidth - 2);
246
- } else {
247
- const sk = serializeRecordKey(key);
248
- entry = `${sk}: ${serializeForDisplayInner(value.get(key) ?? null, maxWidth - sk.length - 4)}`;
249
- }
250
- entries.push(entry);
251
- resultLength += entry.length;
252
- }
253
- }
254
- if (resultLength >= maxWidth) {
255
- return `${begin}
256
- ${entries.join(",\n ")}
257
- ${end}`;
258
- }
259
- return `${begin}${entries.join(", ")}${end}`;
260
- }
261
- function docComment(doc) {
262
- const lines = doc.flatMap((sec) => sec.split("\n").map((s) => s.trimEnd()));
263
- const firstLine = lines.findIndex((line) => line.length > 0);
264
- const lastLine = lines.findLastIndex((line) => line.length > 0);
265
- if (firstLine < 0 || lastLine < 0) return [];
266
- return [`/**`, ...lines.slice(firstLine, lastLine + 1).map((line) => ` * ${line}`), ` */`];
267
- }
268
- function valueDoc(name, value, type, parent) {
269
- const info = getVmFunctionInfo(value);
270
- const describe = parent?.describe?.(name);
271
- if (info) {
272
- const doc = globalFnDoc(info);
273
- if (describe && doc[0] !== describe) {
274
- doc.unshift(describe);
275
- }
276
- return {
277
- script: fnSignature(name, info).toString() + (type === "declare" ? ";" : ""),
278
- doc
279
- };
280
- }
281
- let prefix;
282
- let suffix = "";
283
- if (type === "hint") {
284
- prefix = `${serializeRecordKey(name)} = `;
285
- } else if (type === "declare") {
286
- if (name.startsWith("@")) {
287
- prefix = `const ${name} = `;
288
- } else {
289
- prefix = `let ${name} = `;
290
- }
291
- suffix = ";";
292
- } else if (/^\d/.test(name)) {
293
- prefix = `[${name}]: `;
294
- } else {
295
- prefix = `${name}: `;
296
- }
297
- if (isVmModule(value)) {
298
- const doc = `模块 \`${value.name}\``;
299
- let script;
300
- if (type === "declare") {
301
- const exports = value.keys();
302
- script = "\n";
303
- for (const k of exports) {
304
- const v = value.get(k);
305
- const vDoc = valueDoc(k, v, isVmModule(v) ? "field" : "declare", value);
306
- const code = [...docComment(vDoc.doc), "pub " + vDoc.script, "", ""];
307
- script += code.join("\n");
308
- }
309
- script = script.trimEnd();
310
- } else {
311
- script = `(module) ${value.name}`;
312
- if (value.name !== name) {
313
- script = `${prefix}${script}`;
314
- }
315
- }
316
- return { script, doc: doc ? [doc] : [] };
317
- }
318
- let valueStr = UNKNOWN_REPR;
319
- if (value !== void 0) {
320
- try {
321
- valueStr = serializeForDisplay(value, type === "declare" ? 1e3 : 100, type === "declare" ? 80 : 40);
322
- } catch (ex) {
323
- }
324
- }
325
- return {
326
- script: `${prefix}${valueStr}${suffix}`,
327
- doc: describe ? [describe] : []
328
- };
329
- }
330
- function getDeep(globals, name, path) {
331
- if (!globals.has(name)) return [null, void 0];
332
- let current = globals.get(name);
333
- if (!path.length) {
334
- return [globals, current];
335
- }
336
- let parent = null;
337
- for (const key of path) {
338
- if (current == null) return [null, void 0];
339
- if (!operations.$Has(current, key)) return [null, void 0];
340
- parent = current;
341
- current = operations.$Get(parent, key);
342
- }
343
- return [isVmWrapper(parent) ? parent : null, current];
344
- }
345
- function getField(obj, key) {
346
- if (obj == null) return void 0;
347
- try {
348
- if (!operations.$Has(obj, key)) return void 0;
349
- } catch {
350
- return void 0;
351
- }
352
- try {
353
- return operations.$Get(obj, key);
354
- } catch {
355
- return void 0;
356
- }
357
- }
358
- function listFields(obj, includeNonEnumerable) {
359
- if (obj == null || typeof obj != "object") return [];
360
- if (isVmWrapper(obj)) {
361
- try {
362
- return obj.keys(includeNonEnumerable);
363
- } catch {
364
- return [];
365
- }
366
- }
367
- return lib.keys(obj);
368
- }
369
- function isDeprecatedGlobal(globals, name) {
370
- if (!globals.has(name)) {
371
- return void 0;
372
- }
373
- const value = globals.get(name);
374
- const funcInfo = getVmFunctionInfo(value);
375
- if (funcInfo) {
376
- return funcInfo.deprecated;
377
- }
378
- const info = lib[name];
379
- if (!info?.deprecated) return void 0;
380
- if (info.value !== value) return void 0;
381
- const { use } = info.deprecated;
382
- if (use) {
383
- if (!globals.has(use)) return void 0;
384
- const replacement = globals.get(use);
385
- if (replacement !== info.value) return void 0;
386
- }
387
- return info.deprecated;
388
- }
389
-
390
- // src/lsp/compile-result.ts
391
- import {
392
- parseDiagnostics,
393
- DiagnosticCode as DiagnosticCode2
394
- } from "@mirascript/mirascript/subtle";
395
- var LocalFunctionType = [DiagnosticCode2.LocalFunction];
396
- var LocalVariableType = [
397
- DiagnosticCode2.LocalMutable,
398
- DiagnosticCode2.LocalImmutable,
399
- DiagnosticCode2.LocalConst
400
- ];
401
- var ParameterExplicitType = [
402
- DiagnosticCode2.ParameterMutable,
403
- DiagnosticCode2.ParameterImmutable,
404
- DiagnosticCode2.ParameterMutableRest,
405
- DiagnosticCode2.ParameterImmutableRest
406
- ];
407
- var ParameterSubPatternType = [
408
- DiagnosticCode2.ParameterSubPatternImmutable,
409
- DiagnosticCode2.ParameterSubPatternMutable
410
- ];
411
- var ParameterPatternType = [DiagnosticCode2.ParameterPattern, DiagnosticCode2.ParameterRestPattern];
412
- var ParameterItType = [DiagnosticCode2.ParameterIt];
413
- var ParameterDefinitionType = [
414
- ...ParameterExplicitType,
415
- ...ParameterSubPatternType,
416
- ...ParameterItType
417
- ];
418
- var ParameterPlaceholderType = [
419
- ...ParameterExplicitType,
420
- ...ParameterPatternType,
421
- ...ParameterItType
422
- ];
423
- var LocalDefinitionType = [...LocalVariableType, ...LocalFunctionType, ...ParameterDefinitionType];
424
- var CompileResult = class {
425
- constructor(cacheKey, version, source, result) {
426
- this.cacheKey = cacheKey;
427
- this.version = version;
428
- this.source = source;
429
- this.result = result;
430
- this.diagnosticsReady = false;
431
- this._errors = [];
432
- this._warnings = [];
433
- this._infos = [];
434
- this._hints = [];
435
- this._references = [];
436
- this._tags = [];
437
- this._tagsReferences = [];
438
- this.diagnostics = result.diagnostics;
439
- this.chunk = result.chunk;
440
- }
441
- /** 源代码诊断信息 */
442
- get errors() {
443
- if (!this.diagnosticsReady) {
444
- this.readDiagnostics();
445
- }
446
- return this._errors;
447
- }
448
- /** 源代码诊断信息 */
449
- get warnings() {
450
- if (!this.diagnosticsReady) {
451
- this.readDiagnostics();
452
- }
453
- return this._warnings;
454
- }
455
- /** 源代码诊断信息 */
456
- get infos() {
457
- if (!this.diagnosticsReady) {
458
- this.readDiagnostics();
459
- }
460
- return this._infos;
461
- }
462
- /** 源代码诊断信息 */
463
- get hints() {
464
- if (!this.diagnosticsReady) {
465
- this.readDiagnostics();
466
- }
467
- return this._hints;
468
- }
469
- /** 源代码诊断信息 */
470
- get references() {
471
- if (!this.diagnosticsReady) {
472
- this.readDiagnostics();
473
- }
474
- return this._references;
475
- }
476
- /** 源代码诊断信息 */
477
- get tags() {
478
- if (!this.diagnosticsReady) {
479
- this.readDiagnostics();
480
- }
481
- return this._tags;
482
- }
483
- /** 源代码诊断信息 */
484
- get tagsReferences() {
485
- if (!this.diagnosticsReady) {
486
- this.readDiagnostics();
126
+ /** 源代码诊断信息 */
127
+ get tagsReferences() {
128
+ if (!this.diagnosticsReady) {
129
+ this.readDiagnostics();
487
130
  }
488
131
  return this._tagsReferences;
489
132
  }
490
133
  /** 分析诊断信息 */
491
134
  readDiagnostics() {
492
- const parsed = parseDiagnostics(this.source, this.diagnostics, (c) => c !== DiagnosticCode2.SourceMap);
135
+ const parsed = parseDiagnostics(this.source, this.diagnostics, (c) => c !== DiagnosticCode.SourceMap);
493
136
  this._errors = parsed.errors;
494
137
  this._warnings = parsed.warnings;
495
138
  this._infos = parsed.infos;
@@ -524,7 +167,7 @@ var CompileResult = class {
524
167
  definition: tag,
525
168
  references: tag.references
526
169
  });
527
- } else if (tag.code === DiagnosticCode2.GlobalVariable) {
170
+ } else if (tag.code === DiagnosticCode.GlobalVariable) {
528
171
  const name = getText(tag.range);
529
172
  let def = globals.find((def2) => name === def2.name);
530
173
  if (!def) {
@@ -535,9 +178,9 @@ var CompileResult = class {
535
178
  globals.push(def);
536
179
  }
537
180
  def.references.push(tag);
538
- } else if (tag.code === DiagnosticCode2.Scope || tag.code === DiagnosticCode2.String || tag.code === DiagnosticCode2.Interpolation || tag.code === DiagnosticCode2.FunctionCall || tag.code === DiagnosticCode2.ExtensionCall) {
181
+ } else if (tag.code === DiagnosticCode.Scope || tag.code === DiagnosticCode.String || tag.code === DiagnosticCode.Interpolation || tag.code === DiagnosticCode.FunctionCall || tag.code === DiagnosticCode.ExtensionCall) {
539
182
  ranges.push(tag);
540
- } else if (tag.code === DiagnosticCode2.OmitNamedRecordField) {
183
+ } else if (tag.code === DiagnosticCode.OmitNamedRecordField) {
541
184
  omitNameFields.push(tag);
542
185
  }
543
186
  }
@@ -584,7 +227,7 @@ var CompileResult = class {
584
227
  return this._scopes;
585
228
  }
586
229
  const { locals, params, ranges } = this.groupedTags(model);
587
- const scopes = ranges.filter((r) => r.code === DiagnosticCode2.Scope).map((r) => {
230
+ const scopes = ranges.filter((r) => r.code === DiagnosticCode.Scope).map((r) => {
588
231
  return {
589
232
  range: r.range,
590
233
  locals: [],
@@ -665,7 +308,7 @@ var CompileResult = class {
665
308
  );
666
309
  for (const local of scope.locals) {
667
310
  scopeMap.set(local, scope);
668
- if (local.definition.code === DiagnosticCode2.LocalFunction) {
311
+ if (local.definition.code === DiagnosticCode.LocalFunction) {
669
312
  const funcScope = scope.children.find(
670
313
  (s) => Range.compareRangesUsingStarts(s.range, local.definition.range) > 0
671
314
  );
@@ -681,76 +324,437 @@ var CompileResult = class {
681
324
  }
682
325
  }
683
326
  }
684
- this._scopeMap = scopeMap;
685
- this._scopes = sortedScopes;
686
- return this._scopes;
327
+ this._scopeMap = scopeMap;
328
+ this._scopes = sortedScopes;
329
+ return this._scopes;
330
+ }
331
+ /** 获取定义所在作用域 */
332
+ scopeOf(model, def) {
333
+ if (!this._scopeMap) {
334
+ this.scopes(model);
335
+ }
336
+ return this._scopeMap.get(def);
337
+ }
338
+ /** 获取位置所在作用域 */
339
+ scopeAt(model, position) {
340
+ const scopes = this.scopes(model);
341
+ let scope = scopes.findLast((s) => Range.containsPosition(s.range, position)) ?? scopes[0];
342
+ while (scope.children.length > 0) {
343
+ const inner = scope.children.find((s) => Range.containsPosition(s.range, position));
344
+ if (!inner) break;
345
+ scope = inner;
346
+ }
347
+ return scope;
348
+ }
349
+ /** 获取指定位置的字段访问信息 */
350
+ fieldAccessAt(model, position) {
351
+ let prevDef;
352
+ const { globals } = this.groupedTags(model);
353
+ for (const d of globals) {
354
+ for (const [refIndex, ref] of d.references.entries()) {
355
+ if (!Position.isBefore(Range.getEndPosition(ref.range), position)) continue;
356
+ if (prevDef && Position.isBefore(Range.getEndPosition(ref.range), Range.getEndPosition(prevDef.range)))
357
+ continue;
358
+ prevDef = { def: d, ref: refIndex, range: ref.range };
359
+ }
360
+ }
361
+ this.scopes(model);
362
+ const { locals } = this.groupedTags(model);
363
+ for (const d of locals) {
364
+ for (const [refIndex, ref] of d.references.entries()) {
365
+ if (!Position.isBefore(Range.getEndPosition(ref.range), position)) continue;
366
+ if (prevDef && Position.isBefore(Range.getEndPosition(ref.range), Range.getEndPosition(prevDef.range)))
367
+ continue;
368
+ prevDef = { def: d, ref: refIndex, range: ref.range };
369
+ }
370
+ }
371
+ if (!prevDef) return void 0;
372
+ const chain = model.getValueInRange(Range.fromPositions(Range.getStartPosition(prevDef.range), position));
373
+ const chainParts = chain.split(/\s*(?:!\.|\.)\s*/);
374
+ if (
375
+ // 至少包含变量名和当前位置的字段名
376
+ chainParts.length < 2 || !chainParts.every(
377
+ (part, index) => (
378
+ // 如果是最后一个部分,则可以为空(表示当前位置的字段名),否则必须是合法的标识符
379
+ (index === chainParts.length - 1 ? !part : false) || REG_IDENTIFIER_FULL.test(part) || REG_ORDINAL_FULL.test(part)
380
+ )
381
+ )
382
+ ) {
383
+ return void 0;
384
+ }
385
+ return { def: prevDef, fields: chainParts.slice(1) };
386
+ }
387
+ /** 获取指定位置的字段访问信息 */
388
+ accessAt(model, position) {
389
+ const v = this.variableAccessAt(model, position);
390
+ if (v) return { def: v, fields: [] };
391
+ return this.fieldAccessAt(model, position);
392
+ }
393
+ };
394
+
395
+ // src/lsp/diagnostics.ts
396
+ import { DiagnosticCode as DiagnosticCode3, getDiagnosticMessage } from "@mirascript/mirascript/subtle";
397
+
398
+ // src/lsp/utils.ts
399
+ import { DiagnosticCode as DiagnosticCode2 } from "@mirascript/constants";
400
+ import {
401
+ getVmFunctionInfo,
402
+ isVmArray,
403
+ isVmExtern,
404
+ isVmFunction,
405
+ isVmModule,
406
+ isVmPrimitive,
407
+ isVmRecord,
408
+ isVmWrapper,
409
+ serialize
410
+ } from "@mirascript/mirascript";
411
+ import { lib, operations, serializeRecordKey, serializeString } from "@mirascript/mirascript/subtle";
412
+ var UNKNOWN_REPR = "/* .. */";
413
+ function globalParamsSignature(info) {
414
+ if (info == null || !info.params && !info.paramsType) return [["..", "..", ""]];
415
+ const paramItems = [];
416
+ const params = Object.keys(info.paramsType ?? {});
417
+ for (const key of Object.keys(info.params ?? {})) {
418
+ if (params.includes(key)) continue;
419
+ params.push(key);
420
+ }
421
+ for (const key of params) {
422
+ const type = info.paramsType?.[key] ?? "";
423
+ const doc = info.params?.[key] ?? "";
424
+ paramItems.push([key, `${key}: ${type || "any"}`, doc ? `\`${key}\`: ${doc}` : ""]);
425
+ }
426
+ return paramItems;
427
+ }
428
+ var SIG_WIDTH = 60;
429
+ function fnSignature(id, info) {
430
+ const prefix = id ? `fn ${id}` : "fn";
431
+ const params = globalParamsSignature(info);
432
+ const returns = info.returnsType ? ` -> ${info.returnsType}` : "";
433
+ return {
434
+ params,
435
+ returns,
436
+ toString() {
437
+ let p;
438
+ if (this.params.length >= 1 && (prefix.length + this.returns.length > SIG_WIDTH || prefix.length + this.returns.length + params.reduce((a, b) => a + b[1].length, 0) > SIG_WIDTH)) {
439
+ p = `(
440
+ ${params.map((item) => ` ${item[1]},`).join("\n")}
441
+ )`;
442
+ } else {
443
+ p = `(${params.map((item) => item[1]).join(", ")})`;
444
+ }
445
+ return `${prefix}${p}${this.returns}`;
446
+ }
447
+ };
448
+ }
449
+ function localParamSignature(model, info) {
450
+ const {
451
+ args,
452
+ scope: { params }
453
+ } = info;
454
+ if (params[0]?.code === DiagnosticCode2.ParameterIt) {
455
+ return params[0].references.length ? [["it", "it", ""]] : [];
456
+ }
457
+ return params.map((a, i) => {
458
+ const rest = a.code === DiagnosticCode2.ParameterRestPattern || a.code === DiagnosticCode2.ParameterMutableRest || a.code === DiagnosticCode2.ParameterImmutableRest;
459
+ const argsInParam = args.filter((arg) => Range.containsRange(a.range, arg.definition.range));
460
+ let argName;
461
+ if (argsInParam.length > 0) {
462
+ argName = argsInParam.map((arg) => model.getValueInRange(arg.definition.range)).join("_");
463
+ } else if (rest) {
464
+ argName = "args";
465
+ } else {
466
+ argName = `arg${i}`;
467
+ }
468
+ if (rest) return [`..${argName}`, `..${argName}`, ""];
469
+ return [argName, argName, ""];
470
+ });
471
+ }
472
+ function paramsList(model, info) {
473
+ if (!info) return "(..)";
474
+ if ("scope" in info) {
475
+ return `(${localParamSignature(model, info).map((p) => p[1]).join(", ")})`;
476
+ } else {
477
+ if (!info.params) return "(..)";
478
+ const paramItems = Object.keys(info.params).join(", ");
479
+ return `(${paramItems})`;
480
+ }
481
+ }
482
+ function globalFnDoc(info) {
483
+ const doc = [];
484
+ if (info.summary) {
485
+ doc.push(info.summary);
486
+ }
487
+ const paramDoc = [];
488
+ if (info.params) {
489
+ for (const [key, value] of Object.entries(info.params)) {
490
+ if (!value) continue;
491
+ paramDoc.push(`- \`${key}\`: ${value}`);
492
+ }
493
+ }
494
+ if (info.returns) {
495
+ paramDoc.push(`- **返回值**: ${info.returns}`);
496
+ }
497
+ if (paramDoc.length) {
498
+ doc.push("", paramDoc.join("\n"));
499
+ }
500
+ if (info.examples?.length) {
501
+ let exp = `### 示例`;
502
+ for (const example of info.examples) {
503
+ exp += codeblock(example);
504
+ }
505
+ doc.push("", exp);
506
+ }
507
+ return doc;
508
+ }
509
+ function codeblock(value) {
510
+ const lang = value.startsWith("\0") ? "mirascript-doc" : "mirascript";
511
+ const includeFences = /`{3,}/.exec(value);
512
+ const CODEBLOCK_FENCE = includeFences ? "`".repeat(includeFences[0].length + 1) : "```";
513
+ return `
514
+ ${CODEBLOCK_FENCE}${lang}
515
+ ${value}
516
+ ${CODEBLOCK_FENCE}
517
+ `;
518
+ }
519
+ function serializeForDisplayInner(value, maxWidth) {
520
+ if (maxWidth < 10) maxWidth = 10;
521
+ if (typeof value === "string") {
522
+ if (value.length < maxWidth) {
523
+ return serializeString(value);
524
+ }
525
+ return `${serializeString(value.slice(0, maxWidth))}..`;
526
+ }
527
+ if (isVmPrimitive(value)) {
528
+ return serialize(value);
529
+ }
530
+ if (isVmArray(value)) {
531
+ const len = value.length;
532
+ if (!len) return "[]";
533
+ return `[../* x${len} */]`;
534
+ }
535
+ if (isVmRecord(value)) {
536
+ const len = Object.keys(value).length;
537
+ if (!len) return "()";
538
+ return `(../* x${len} */)`;
539
+ }
540
+ if (isVmExtern(value)) {
541
+ return `/* <extern ${value.tag}> */`;
542
+ }
543
+ return `/* ${operations.$ToString(value)} */`;
544
+ }
545
+ function serializeField(obj, key, maxWidth) {
546
+ const value = getField(obj, key);
547
+ if (value === void 0) {
548
+ return UNKNOWN_REPR;
549
+ }
550
+ return serializeForDisplayInner(value, maxWidth);
551
+ }
552
+ function serializeForDisplay(value, maxEntries = 100, maxWidth = 40) {
553
+ if (isVmPrimitive(value) || isVmFunction(value)) {
554
+ return serializeForDisplayInner(value, maxWidth);
555
+ }
556
+ let begin, end;
557
+ const entries = [];
558
+ let resultLength = 0;
559
+ if (isVmArray(value)) {
560
+ begin = "[";
561
+ end = "]";
562
+ const len = value.length;
563
+ if (len === 0) return "[]";
564
+ for (let i = 0; i < len; i++) {
565
+ if (entries.length > maxEntries) {
566
+ entries.push(`../* x${value.length - entries.length} */`);
567
+ break;
568
+ }
569
+ const entry = serializeField(value, i, maxWidth - 2);
570
+ entries.push(entry);
571
+ resultLength += entry.length;
572
+ }
573
+ } else if (isVmRecord(value)) {
574
+ const keys = Object.keys(value);
575
+ if (keys.length === 0) return "()";
576
+ begin = "(";
577
+ end = ")";
578
+ for (const key of keys) {
579
+ if (entries.length > maxEntries) {
580
+ entries.push(`../* x${keys.length - entries.length} */`);
581
+ break;
582
+ }
583
+ const sk = serializeRecordKey(key);
584
+ const sv = serializeField(value, key, maxWidth - sk.length - 4);
585
+ const entry = `${sk}: ${sv}`;
586
+ entries.push(entry);
587
+ resultLength += entry.length;
588
+ }
589
+ } else {
590
+ const hint = serializeForDisplayInner(value, 100);
591
+ const isArray = value.isArrayLike();
592
+ begin = `${hint} ${isArray ? "[" : "("}`;
593
+ end = isArray ? "]" : ")";
594
+ const keys = value.keys();
595
+ if (keys.length === 0 && !isArray) {
596
+ if (typeof value.value == "object") {
597
+ for (const key of Object.getOwnPropertyNames(value.value)) {
598
+ if (value.has(key)) keys.push(key);
599
+ }
600
+ } else {
601
+ begin = hint;
602
+ end = "";
603
+ }
604
+ }
605
+ for (const [index, key] of keys.entries()) {
606
+ if (entries.length > maxEntries) {
607
+ entries.push(`../* x${keys.length - entries.length} */`);
608
+ break;
609
+ }
610
+ let entry;
611
+ if (isArray && String(index) === key) {
612
+ entry = serializeForDisplayInner(value.get(key) ?? null, maxWidth - 2);
613
+ } else {
614
+ const sk = serializeRecordKey(key);
615
+ entry = `${sk}: ${serializeForDisplayInner(value.get(key) ?? null, maxWidth - sk.length - 4)}`;
616
+ }
617
+ entries.push(entry);
618
+ resultLength += entry.length;
619
+ }
687
620
  }
688
- /** 获取定义所在作用域 */
689
- scopeOf(model, def) {
690
- if (!this._scopeMap) {
691
- this.scopes(model);
621
+ if (resultLength >= maxWidth) {
622
+ return `${begin}
623
+ ${entries.join(",\n ")}
624
+ ${end}`;
625
+ }
626
+ return `${begin}${entries.join(", ")}${end}`;
627
+ }
628
+ function docComment(doc) {
629
+ const lines = doc.flatMap((sec) => sec.split("\n").map((s) => s.trimEnd()));
630
+ const firstLine = lines.findIndex((line) => line.length > 0);
631
+ const lastLine = lines.findLastIndex((line) => line.length > 0);
632
+ if (firstLine < 0 || lastLine < 0) return [];
633
+ return [`/**`, ...lines.slice(firstLine, lastLine + 1).map((line) => ` * ${line}`), ` */`];
634
+ }
635
+ function valueDoc(name, value, type, parent) {
636
+ const info = getVmFunctionInfo(value);
637
+ const describe = parent?.describe?.(name);
638
+ if (info) {
639
+ const doc = globalFnDoc(info);
640
+ if (describe && doc[0] !== describe) {
641
+ doc.unshift(describe);
692
642
  }
693
- return this._scopeMap.get(def);
643
+ return {
644
+ script: fnSignature(name, info).toString() + (type === "declare" ? ";" : ""),
645
+ doc
646
+ };
694
647
  }
695
- /** 获取位置所在作用域 */
696
- scopeAt(model, position) {
697
- const scopes = this.scopes(model);
698
- let scope = scopes.findLast((s) => Range.containsPosition(s.range, position)) ?? scopes[0];
699
- while (scope.children.length > 0) {
700
- const inner = scope.children.find((s) => Range.containsPosition(s.range, position));
701
- if (!inner) break;
702
- scope = inner;
648
+ let prefix;
649
+ let suffix = "";
650
+ if (type === "hint") {
651
+ prefix = `${serializeRecordKey(name)} = `;
652
+ } else if (type === "declare") {
653
+ if (name.startsWith("@")) {
654
+ prefix = `const ${name} = `;
655
+ } else {
656
+ prefix = `let ${name} = `;
703
657
  }
704
- return scope;
658
+ suffix = ";";
659
+ } else if (/^\d/.test(name)) {
660
+ prefix = `[${name}]: `;
661
+ } else {
662
+ prefix = `${name}: `;
705
663
  }
706
- /** 获取指定位置的字段访问信息 */
707
- fieldAccessAt(model, position) {
708
- let prevDef;
709
- const { globals } = this.groupedTags(model);
710
- for (const d of globals) {
711
- for (const [refIndex, ref] of d.references.entries()) {
712
- if (!Position.isBefore(Range.getEndPosition(ref.range), position)) continue;
713
- if (prevDef && Position.isBefore(Range.getEndPosition(ref.range), Range.getEndPosition(prevDef.range)))
714
- continue;
715
- prevDef = { def: d, ref: refIndex, range: ref.range };
664
+ if (isVmModule(value)) {
665
+ const doc = `模块 \`${value.name}\``;
666
+ let script;
667
+ if (type === "declare") {
668
+ const exports = value.keys();
669
+ script = "\n";
670
+ for (const k of exports) {
671
+ const v = value.get(k);
672
+ const vDoc = valueDoc(k, v, isVmModule(v) ? "field" : "declare", value);
673
+ const code = [...docComment(vDoc.doc), "pub " + vDoc.script, "", ""];
674
+ script += code.join("\n");
716
675
  }
717
- }
718
- this.scopes(model);
719
- const { locals } = this.groupedTags(model);
720
- for (const d of locals) {
721
- for (const [refIndex, ref] of d.references.entries()) {
722
- if (!Position.isBefore(Range.getEndPosition(ref.range), position)) continue;
723
- if (prevDef && Position.isBefore(Range.getEndPosition(ref.range), Range.getEndPosition(prevDef.range)))
724
- continue;
725
- prevDef = { def: d, ref: refIndex, range: ref.range };
676
+ script = script.trimEnd();
677
+ } else {
678
+ script = `(module) ${value.name}`;
679
+ if (value.name !== name) {
680
+ script = `${prefix}${script}`;
726
681
  }
727
682
  }
728
- if (!prevDef) return void 0;
729
- const chain = model.getValueInRange(Range.fromPositions(Range.getStartPosition(prevDef.range), position));
730
- const chainParts = chain.split(/\s*(?:!\.|\.)\s*/);
731
- if (
732
- // 至少包含变量名和当前位置的字段名
733
- chainParts.length < 2 || !chainParts.every(
734
- (part, index) => (
735
- // 如果是最后一个部分,则可以为空(表示当前位置的字段名),否则必须是合法的标识符
736
- (index === chainParts.length - 1 ? !part : false) || REG_IDENTIFIER_FULL.test(part) || REG_ORDINAL_FULL.test(part)
737
- )
738
- )
739
- ) {
740
- return void 0;
683
+ return { script, doc: doc ? [doc] : [] };
684
+ }
685
+ let valueStr = UNKNOWN_REPR;
686
+ if (value !== void 0) {
687
+ try {
688
+ valueStr = serializeForDisplay(value, type === "declare" ? 1e3 : 100, type === "declare" ? 80 : 40);
689
+ } catch (ex) {
741
690
  }
742
- return { def: prevDef, fields: chainParts.slice(1) };
743
691
  }
744
- /** 获取指定位置的字段访问信息 */
745
- accessAt(model, position) {
746
- const v = this.variableAccessAt(model, position);
747
- if (v) return { def: v, fields: [] };
748
- return this.fieldAccessAt(model, position);
692
+ return {
693
+ script: `${prefix}${valueStr}${suffix}`,
694
+ doc: describe ? [describe] : []
695
+ };
696
+ }
697
+ function getDeep(globals, name, path) {
698
+ if (!globals.has(name)) return [null, void 0];
699
+ let current = globals.get(name);
700
+ if (!path.length) {
701
+ return [globals, current];
749
702
  }
750
- };
703
+ let parent = null;
704
+ for (const key of path) {
705
+ if (current == null) return [null, void 0];
706
+ if (!operations.$Has(current, key)) return [null, void 0];
707
+ parent = current;
708
+ current = operations.$Get(parent, key);
709
+ }
710
+ return [isVmWrapper(parent) ? parent : null, current];
711
+ }
712
+ function getField(obj, key) {
713
+ if (obj == null) return void 0;
714
+ try {
715
+ if (!operations.$Has(obj, key)) return void 0;
716
+ } catch {
717
+ return void 0;
718
+ }
719
+ try {
720
+ return operations.$Get(obj, key);
721
+ } catch {
722
+ return void 0;
723
+ }
724
+ }
725
+ function listFields(obj, includeNonEnumerable) {
726
+ if (obj == null || typeof obj != "object") return [];
727
+ if (isVmWrapper(obj)) {
728
+ try {
729
+ return obj.keys(includeNonEnumerable);
730
+ } catch {
731
+ return [];
732
+ }
733
+ }
734
+ return lib.keys(obj);
735
+ }
736
+ function isDeprecatedGlobal(globals, name) {
737
+ if (!globals.has(name)) {
738
+ return void 0;
739
+ }
740
+ const value = globals.get(name);
741
+ const funcInfo = getVmFunctionInfo(value);
742
+ if (funcInfo) {
743
+ return funcInfo.deprecated;
744
+ }
745
+ const info = lib[name];
746
+ if (!info?.deprecated) return void 0;
747
+ if (info.value !== value) return void 0;
748
+ const { use } = info.deprecated;
749
+ if (use) {
750
+ if (!globals.has(use)) return void 0;
751
+ const replacement = globals.get(use);
752
+ if (replacement !== info.value) return void 0;
753
+ }
754
+ return info.deprecated;
755
+ }
751
756
 
752
757
  // src/lsp/diagnostics.ts
753
- import { DiagnosticCode as DiagnosticCode3, getDiagnosticMessage } from "@mirascript/mirascript/subtle";
754
758
  var formatMessage = (model, template, $0) => {
755
759
  if (template.includes(`$0`)) {
756
760
  const replacement = typeof $0 == "string" ? $0 : $0 ? model.getValueInRange($0) : "";
@@ -1433,6 +1437,7 @@ import {
1433
1437
  serialize as serialize2
1434
1438
  } from "@mirascript/mirascript";
1435
1439
  import { DiagnosticCode as DiagnosticCode6 } from "@mirascript/mirascript/subtle";
1440
+ import { KEYWORDS as HELP_KEYWORDS } from "@mirascript/help";
1436
1441
  var DESC_GLOBAL = "(global)";
1437
1442
  var DESC_LOCAL = "(local)";
1438
1443
  var DESC_FIELD = "(field)";
@@ -1452,9 +1457,7 @@ var COMMON_GLOBAL_SUGGESTIONS = (range, extension) => {
1452
1457
  kind: languages.CompletionItemKind.Keyword,
1453
1458
  insertText: "type",
1454
1459
  commitCharacters: ["("],
1455
- documentation: {
1456
- value: `使用 \`type()\` 调用获取表达式的类型。${codeblock("type(expression);\nexpression::type();")}`
1457
- },
1460
+ documentation: { value: HELP_KEYWORDS.type },
1458
1461
  range
1459
1462
  },
1460
1463
  {
@@ -1462,9 +1465,7 @@ var COMMON_GLOBAL_SUGGESTIONS = (range, extension) => {
1462
1465
  kind: languages.CompletionItemKind.Keyword,
1463
1466
  insertText: "global",
1464
1467
  commitCharacters: [".", "["],
1465
- documentation: {
1466
- value: `使用 \`global\` 获取全局变量。${codeblock('global.variableName;\nglobal["variableName"];\n"variableName" in global;')}`
1467
- },
1468
+ documentation: { value: HELP_KEYWORDS.global },
1468
1469
  range
1469
1470
  }
1470
1471
  ];
@@ -1572,10 +1573,12 @@ var COMMON_GLOBAL_SUGGESTIONS = (range, extension) => {
1572
1573
  return suggestions;
1573
1574
  };
1574
1575
  function kwSuggestion(kw, range) {
1576
+ const doc = HELP_KEYWORDS[kw];
1575
1577
  return {
1576
1578
  label: kw,
1577
1579
  kind: languages.CompletionItemKind.Keyword,
1578
1580
  insertText: kw,
1581
+ documentation: doc ? { value: doc } : void 0,
1579
1582
  range
1580
1583
  };
1581
1584
  }
@@ -2065,6 +2068,70 @@ var FormatterProvider = class extends Provider {
2065
2068
 
2066
2069
  // src/lsp/providers/hover-provider.ts
2067
2070
  import { DiagnosticCode as DiagnosticCode9 } from "@mirascript/constants";
2071
+
2072
+ // src/lsp/monaco-private.js
2073
+ function fromStandardTokenType(tokenType) {
2074
+ switch (tokenType) {
2075
+ case 1:
2076
+ return "comment";
2077
+ case 2:
2078
+ return "string";
2079
+ case 3:
2080
+ return "regex";
2081
+ default:
2082
+ return "other";
2083
+ }
2084
+ }
2085
+ function tokenAt(model, position) {
2086
+ try {
2087
+ let tryGetTokenProp2 = function(method, fallback) {
2088
+ try {
2089
+ return lineTokens[method](tokenIndex);
2090
+ } catch {
2091
+ return fallback;
2092
+ }
2093
+ };
2094
+ var tryGetTokenProp = tryGetTokenProp2;
2095
+ const lineTokens = model.tokenization.getLineTokens(position.lineNumber);
2096
+ const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
2097
+ if (tokenIndex < 0) return void 0;
2098
+ return {
2099
+ type: fromStandardTokenType(tryGetTokenProp2("getStandardTokenType", 0)),
2100
+ text: tryGetTokenProp2("getTokenText", null),
2101
+ startColumn: tryGetTokenProp2("getStartOffset", 0) + 1,
2102
+ endColumn: tryGetTokenProp2("getEndOffset", 0) + 1
2103
+ };
2104
+ } catch {
2105
+ return void 0;
2106
+ }
2107
+ }
2108
+
2109
+ // src/lsp/providers/hover-provider.ts
2110
+ import { KEYWORDS as HELP_KEYWORDS2, OPERATORS as HELP_OPERATORS } from "@mirascript/help";
2111
+ var OPERATOR_TOKENS_DESC = Object.keys(HELP_OPERATORS).sort((a, b) => b.length - a.length);
2112
+ function operatorAt(lineContent, column) {
2113
+ const index = Math.max(0, column - 1);
2114
+ for (const token of OPERATOR_TOKENS_DESC) {
2115
+ for (let offset = 0; offset < token.length; offset++) {
2116
+ const start = index - offset;
2117
+ if (start < 0) continue;
2118
+ const end = start + token.length;
2119
+ if (end > lineContent.length) continue;
2120
+ if (lineContent.slice(start, end) !== token) continue;
2121
+ if (index < start || index >= end) continue;
2122
+ return {
2123
+ token,
2124
+ range: {
2125
+ startLineNumber: 0,
2126
+ startColumn: start + 1,
2127
+ endLineNumber: 0,
2128
+ endColumn: end + 1
2129
+ }
2130
+ };
2131
+ }
2132
+ }
2133
+ return void 0;
2134
+ }
2068
2135
  var HoverProvider = class extends Provider {
2069
2136
  /** 变量提示 */
2070
2137
  async provideVariableHover(model, { def, ref }) {
@@ -2171,11 +2238,59 @@ var HoverProvider = class extends Provider {
2171
2238
  range
2172
2239
  };
2173
2240
  }
2241
+ /** 语法元素提示 */
2242
+ provideSyntaxHover(model, position) {
2243
+ const token = tokenAt(model, position);
2244
+ if (token?.type && token.type !== "other") {
2245
+ return void 0;
2246
+ }
2247
+ if (token?.text && (token.text in HELP_KEYWORDS2 || token.text in HELP_OPERATORS)) {
2248
+ const doc = HELP_KEYWORDS2[token.text] ?? HELP_OPERATORS[token.text];
2249
+ return {
2250
+ contents: [{ value: doc }],
2251
+ range: {
2252
+ startLineNumber: position.lineNumber,
2253
+ endLineNumber: position.lineNumber,
2254
+ startColumn: token.startColumn,
2255
+ endColumn: token.endColumn
2256
+ }
2257
+ };
2258
+ }
2259
+ const word = model.getWordAtPosition(position);
2260
+ if (word?.word && word.word in HELP_KEYWORDS2) {
2261
+ const doc = HELP_KEYWORDS2[word.word];
2262
+ return {
2263
+ contents: [{ value: doc }],
2264
+ range: {
2265
+ startLineNumber: position.lineNumber,
2266
+ endLineNumber: position.lineNumber,
2267
+ startColumn: word.startColumn,
2268
+ endColumn: word.endColumn
2269
+ }
2270
+ };
2271
+ }
2272
+ const lineContent = model.getLineContent(position.lineNumber);
2273
+ const hit = operatorAt(lineContent, position.column);
2274
+ if (hit && hit.token in HELP_OPERATORS) {
2275
+ const doc = HELP_OPERATORS[hit.token];
2276
+ return {
2277
+ contents: [{ value: doc }],
2278
+ range: {
2279
+ startLineNumber: position.lineNumber,
2280
+ endLineNumber: position.lineNumber,
2281
+ startColumn: hit.range.startColumn,
2282
+ endColumn: hit.range.endColumn
2283
+ }
2284
+ };
2285
+ }
2286
+ return void 0;
2287
+ }
2174
2288
  /** @inheritdoc */
2175
2289
  async provideHover(model, position, token, context) {
2176
2290
  const value = await this.getValueAt(model, position);
2177
- if (!value) return void 0;
2178
- if ("fields" in value) {
2291
+ if (!value) {
2292
+ return this.provideSyntaxHover(model, position);
2293
+ } else if ("fields" in value) {
2179
2294
  return this.provideFieldHover(model, value.range, value.fields);
2180
2295
  } else {
2181
2296
  return this.provideVariableHover(model, value.variable);