@mirascript/monaco 0.1.39 → 0.1.41
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/basic/index.js +1 -1
- package/dist/{chunk-SFU27XXU.js → chunk-KZW3KCZF.js} +5 -1
- package/dist/lsp/index.js +738 -514
- package/dist/lsp/index.js.map +3 -3
- package/dist/lsp/monaco-private.d.ts +19 -0
- package/dist/lsp/monaco-private.d.ts.map +1 -0
- package/dist/lsp/monaco-utils.d.ts +20 -0
- package/dist/lsp/monaco-utils.d.ts.map +1 -0
- package/dist/lsp/providers/completion-item-provider.d.ts.map +1 -1
- package/dist/lsp/providers/hover-provider.d.ts +3 -1
- package/dist/lsp/providers/hover-provider.d.ts.map +1 -1
- package/dist/lsp/providers/signature-help-provider.d.ts.map +1 -1
- package/dist/lsp/utils.d.ts +5 -8
- package/dist/lsp/utils.d.ts.map +1 -1
- package/package.json +6 -5
- package/src/lsp/compile-result.ts +1 -1
- package/src/lsp/monaco-private.js +55 -0
- package/src/lsp/monaco-utils.ts +30 -0
- package/src/lsp/providers/base.ts +1 -1
- package/src/lsp/providers/completion-item-provider.ts +7 -17
- package/src/lsp/providers/hover-provider.ts +119 -5
- package/src/lsp/providers/signature-help-provider.ts +3 -2
- package/src/lsp/utils.ts +72 -10
- /package/dist/{chunk-SFU27XXU.js.map → chunk-KZW3KCZF.js.map} +0 -0
package/dist/lsp/index.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
KEYWORDS,
|
|
3
|
+
REG_BIN,
|
|
4
|
+
REG_HEX,
|
|
3
5
|
REG_IDENTIFIER_FULL,
|
|
6
|
+
REG_NUMBER,
|
|
7
|
+
REG_OCT,
|
|
4
8
|
REG_ORDINAL_FULL,
|
|
5
9
|
RESERVED_KEYWORDS,
|
|
6
10
|
isKeyword
|
|
7
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-KZW3KCZF.js";
|
|
8
12
|
import {
|
|
9
13
|
Emitter,
|
|
10
14
|
MarkerSeverity,
|
|
@@ -19,127 +23,7 @@ import {
|
|
|
19
23
|
// src/lsp/providers/base.ts
|
|
20
24
|
import { DefaultVmContext } from "@mirascript/mirascript/subtle";
|
|
21
25
|
|
|
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
|
-
}
|
|
26
|
+
// src/lsp/monaco-utils.ts
|
|
143
27
|
function strictContainsPosition(range, position) {
|
|
144
28
|
return !Range.isEmpty(range) && Range.containsPosition(range, position);
|
|
145
29
|
}
|
|
@@ -149,334 +33,107 @@ function wordAt(model, position) {
|
|
|
149
33
|
const range = new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn);
|
|
150
34
|
return { word: word.word, range };
|
|
151
35
|
}
|
|
152
|
-
function
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (isVmPrimitive(value)) {
|
|
161
|
-
return serialize(value);
|
|
36
|
+
function rangeAt(...args) {
|
|
37
|
+
if (args.length === 1 || args[1] == null) {
|
|
38
|
+
const { lineNumber, startColumn, endColumn } = args[0];
|
|
39
|
+
return new Range(lineNumber, startColumn, lineNumber, endColumn);
|
|
40
|
+
} else {
|
|
41
|
+
const { lineNumber } = args[0];
|
|
42
|
+
const { startColumn, endColumn } = args[1];
|
|
43
|
+
return new Range(lineNumber, startColumn, lineNumber, endColumn);
|
|
162
44
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/lsp/compile-result.ts
|
|
48
|
+
import {
|
|
49
|
+
parseDiagnostics,
|
|
50
|
+
DiagnosticCode
|
|
51
|
+
} from "@mirascript/mirascript/subtle";
|
|
52
|
+
var LocalFunctionType = [DiagnosticCode.LocalFunction];
|
|
53
|
+
var LocalVariableType = [
|
|
54
|
+
DiagnosticCode.LocalMutable,
|
|
55
|
+
DiagnosticCode.LocalImmutable,
|
|
56
|
+
DiagnosticCode.LocalConst
|
|
57
|
+
];
|
|
58
|
+
var ParameterExplicitType = [
|
|
59
|
+
DiagnosticCode.ParameterMutable,
|
|
60
|
+
DiagnosticCode.ParameterImmutable,
|
|
61
|
+
DiagnosticCode.ParameterMutableRest,
|
|
62
|
+
DiagnosticCode.ParameterImmutableRest
|
|
63
|
+
];
|
|
64
|
+
var ParameterSubPatternType = [
|
|
65
|
+
DiagnosticCode.ParameterSubPatternImmutable,
|
|
66
|
+
DiagnosticCode.ParameterSubPatternMutable
|
|
67
|
+
];
|
|
68
|
+
var ParameterPatternType = [DiagnosticCode.ParameterPattern, DiagnosticCode.ParameterRestPattern];
|
|
69
|
+
var ParameterItType = [DiagnosticCode.ParameterIt];
|
|
70
|
+
var ParameterDefinitionType = [
|
|
71
|
+
...ParameterExplicitType,
|
|
72
|
+
...ParameterSubPatternType,
|
|
73
|
+
...ParameterItType
|
|
74
|
+
];
|
|
75
|
+
var ParameterPlaceholderType = [
|
|
76
|
+
...ParameterExplicitType,
|
|
77
|
+
...ParameterPatternType,
|
|
78
|
+
...ParameterItType
|
|
79
|
+
];
|
|
80
|
+
var LocalDefinitionType = [...LocalVariableType, ...LocalFunctionType, ...ParameterDefinitionType];
|
|
81
|
+
var CompileResult = class {
|
|
82
|
+
constructor(cacheKey, version, source, result) {
|
|
83
|
+
this.cacheKey = cacheKey;
|
|
84
|
+
this.version = version;
|
|
85
|
+
this.source = source;
|
|
86
|
+
this.result = result;
|
|
87
|
+
this.diagnosticsReady = false;
|
|
88
|
+
this._errors = [];
|
|
89
|
+
this._warnings = [];
|
|
90
|
+
this._infos = [];
|
|
91
|
+
this._hints = [];
|
|
92
|
+
this._references = [];
|
|
93
|
+
this._tags = [];
|
|
94
|
+
this._tagsReferences = [];
|
|
95
|
+
this.diagnostics = result.diagnostics;
|
|
96
|
+
this.chunk = result.chunk;
|
|
167
97
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (!
|
|
171
|
-
|
|
98
|
+
/** 源代码诊断信息 */
|
|
99
|
+
get errors() {
|
|
100
|
+
if (!this.diagnosticsReady) {
|
|
101
|
+
this.readDiagnostics();
|
|
102
|
+
}
|
|
103
|
+
return this._errors;
|
|
172
104
|
}
|
|
173
|
-
|
|
174
|
-
|
|
105
|
+
/** 源代码诊断信息 */
|
|
106
|
+
get warnings() {
|
|
107
|
+
if (!this.diagnosticsReady) {
|
|
108
|
+
this.readDiagnostics();
|
|
109
|
+
}
|
|
110
|
+
return this._warnings;
|
|
175
111
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
return
|
|
112
|
+
/** 源代码诊断信息 */
|
|
113
|
+
get infos() {
|
|
114
|
+
if (!this.diagnosticsReady) {
|
|
115
|
+
this.readDiagnostics();
|
|
116
|
+
}
|
|
117
|
+
return this._infos;
|
|
182
118
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
119
|
+
/** 源代码诊断信息 */
|
|
120
|
+
get hints() {
|
|
121
|
+
if (!this.diagnosticsReady) {
|
|
122
|
+
this.readDiagnostics();
|
|
123
|
+
}
|
|
124
|
+
return this._hints;
|
|
188
125
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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;
|
|
126
|
+
/** 源代码诊断信息 */
|
|
127
|
+
get references() {
|
|
128
|
+
if (!this.diagnosticsReady) {
|
|
129
|
+
this.readDiagnostics();
|
|
205
130
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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();
|
|
131
|
+
return this._references;
|
|
132
|
+
}
|
|
133
|
+
/** 源代码诊断信息 */
|
|
134
|
+
get tags() {
|
|
135
|
+
if (!this.diagnosticsReady) {
|
|
136
|
+
this.readDiagnostics();
|
|
480
137
|
}
|
|
481
138
|
return this._tags;
|
|
482
139
|
}
|
|
@@ -489,7 +146,7 @@ var CompileResult = class {
|
|
|
489
146
|
}
|
|
490
147
|
/** 分析诊断信息 */
|
|
491
148
|
readDiagnostics() {
|
|
492
|
-
const parsed = parseDiagnostics(this.source, this.diagnostics, (c) => c !==
|
|
149
|
+
const parsed = parseDiagnostics(this.source, this.diagnostics, (c) => c !== DiagnosticCode.SourceMap);
|
|
493
150
|
this._errors = parsed.errors;
|
|
494
151
|
this._warnings = parsed.warnings;
|
|
495
152
|
this._infos = parsed.infos;
|
|
@@ -524,7 +181,7 @@ var CompileResult = class {
|
|
|
524
181
|
definition: tag,
|
|
525
182
|
references: tag.references
|
|
526
183
|
});
|
|
527
|
-
} else if (tag.code ===
|
|
184
|
+
} else if (tag.code === DiagnosticCode.GlobalVariable) {
|
|
528
185
|
const name = getText(tag.range);
|
|
529
186
|
let def = globals.find((def2) => name === def2.name);
|
|
530
187
|
if (!def) {
|
|
@@ -535,9 +192,9 @@ var CompileResult = class {
|
|
|
535
192
|
globals.push(def);
|
|
536
193
|
}
|
|
537
194
|
def.references.push(tag);
|
|
538
|
-
} else if (tag.code ===
|
|
195
|
+
} else if (tag.code === DiagnosticCode.Scope || tag.code === DiagnosticCode.String || tag.code === DiagnosticCode.Interpolation || tag.code === DiagnosticCode.FunctionCall || tag.code === DiagnosticCode.ExtensionCall) {
|
|
539
196
|
ranges.push(tag);
|
|
540
|
-
} else if (tag.code ===
|
|
197
|
+
} else if (tag.code === DiagnosticCode.OmitNamedRecordField) {
|
|
541
198
|
omitNameFields.push(tag);
|
|
542
199
|
}
|
|
543
200
|
}
|
|
@@ -584,7 +241,7 @@ var CompileResult = class {
|
|
|
584
241
|
return this._scopes;
|
|
585
242
|
}
|
|
586
243
|
const { locals, params, ranges } = this.groupedTags(model);
|
|
587
|
-
const scopes = ranges.filter((r) => r.code ===
|
|
244
|
+
const scopes = ranges.filter((r) => r.code === DiagnosticCode.Scope).map((r) => {
|
|
588
245
|
return {
|
|
589
246
|
range: r.range,
|
|
590
247
|
locals: [],
|
|
@@ -665,7 +322,7 @@ var CompileResult = class {
|
|
|
665
322
|
);
|
|
666
323
|
for (const local of scope.locals) {
|
|
667
324
|
scopeMap.set(local, scope);
|
|
668
|
-
if (local.definition.code ===
|
|
325
|
+
if (local.definition.code === DiagnosticCode.LocalFunction) {
|
|
669
326
|
const funcScope = scope.children.find(
|
|
670
327
|
(s) => Range.compareRangesUsingStarts(s.range, local.definition.range) > 0
|
|
671
328
|
);
|
|
@@ -681,76 +338,506 @@ var CompileResult = class {
|
|
|
681
338
|
}
|
|
682
339
|
}
|
|
683
340
|
}
|
|
684
|
-
this._scopeMap = scopeMap;
|
|
685
|
-
this._scopes = sortedScopes;
|
|
686
|
-
return this._scopes;
|
|
341
|
+
this._scopeMap = scopeMap;
|
|
342
|
+
this._scopes = sortedScopes;
|
|
343
|
+
return this._scopes;
|
|
344
|
+
}
|
|
345
|
+
/** 获取定义所在作用域 */
|
|
346
|
+
scopeOf(model, def) {
|
|
347
|
+
if (!this._scopeMap) {
|
|
348
|
+
this.scopes(model);
|
|
349
|
+
}
|
|
350
|
+
return this._scopeMap.get(def);
|
|
351
|
+
}
|
|
352
|
+
/** 获取位置所在作用域 */
|
|
353
|
+
scopeAt(model, position) {
|
|
354
|
+
const scopes = this.scopes(model);
|
|
355
|
+
let scope = scopes.findLast((s) => Range.containsPosition(s.range, position)) ?? scopes[0];
|
|
356
|
+
while (scope.children.length > 0) {
|
|
357
|
+
const inner = scope.children.find((s) => Range.containsPosition(s.range, position));
|
|
358
|
+
if (!inner) break;
|
|
359
|
+
scope = inner;
|
|
360
|
+
}
|
|
361
|
+
return scope;
|
|
362
|
+
}
|
|
363
|
+
/** 获取指定位置的字段访问信息 */
|
|
364
|
+
fieldAccessAt(model, position) {
|
|
365
|
+
let prevDef;
|
|
366
|
+
const { globals } = this.groupedTags(model);
|
|
367
|
+
for (const d of globals) {
|
|
368
|
+
for (const [refIndex, ref] of d.references.entries()) {
|
|
369
|
+
if (!Position.isBefore(Range.getEndPosition(ref.range), position)) continue;
|
|
370
|
+
if (prevDef && Position.isBefore(Range.getEndPosition(ref.range), Range.getEndPosition(prevDef.range)))
|
|
371
|
+
continue;
|
|
372
|
+
prevDef = { def: d, ref: refIndex, range: ref.range };
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
this.scopes(model);
|
|
376
|
+
const { locals } = this.groupedTags(model);
|
|
377
|
+
for (const d of locals) {
|
|
378
|
+
for (const [refIndex, ref] of d.references.entries()) {
|
|
379
|
+
if (!Position.isBefore(Range.getEndPosition(ref.range), position)) continue;
|
|
380
|
+
if (prevDef && Position.isBefore(Range.getEndPosition(ref.range), Range.getEndPosition(prevDef.range)))
|
|
381
|
+
continue;
|
|
382
|
+
prevDef = { def: d, ref: refIndex, range: ref.range };
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
if (!prevDef) return void 0;
|
|
386
|
+
const chain = model.getValueInRange(Range.fromPositions(Range.getStartPosition(prevDef.range), position));
|
|
387
|
+
const chainParts = chain.split(/\s*(?:!\.|\.)\s*/);
|
|
388
|
+
if (
|
|
389
|
+
// 至少包含变量名和当前位置的字段名
|
|
390
|
+
chainParts.length < 2 || !chainParts.every(
|
|
391
|
+
(part, index) => (
|
|
392
|
+
// 如果是最后一个部分,则可以为空(表示当前位置的字段名),否则必须是合法的标识符
|
|
393
|
+
(index === chainParts.length - 1 ? !part : false) || REG_IDENTIFIER_FULL.test(part) || REG_ORDINAL_FULL.test(part)
|
|
394
|
+
)
|
|
395
|
+
)
|
|
396
|
+
) {
|
|
397
|
+
return void 0;
|
|
398
|
+
}
|
|
399
|
+
return { def: prevDef, fields: chainParts.slice(1) };
|
|
400
|
+
}
|
|
401
|
+
/** 获取指定位置的字段访问信息 */
|
|
402
|
+
accessAt(model, position) {
|
|
403
|
+
const v = this.variableAccessAt(model, position);
|
|
404
|
+
if (v) return { def: v, fields: [] };
|
|
405
|
+
return this.fieldAccessAt(model, position);
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
// src/lsp/diagnostics.ts
|
|
410
|
+
import { DiagnosticCode as DiagnosticCode3, getDiagnosticMessage } from "@mirascript/mirascript/subtle";
|
|
411
|
+
|
|
412
|
+
// src/lsp/utils.ts
|
|
413
|
+
import { DiagnosticCode as DiagnosticCode2 } from "@mirascript/constants";
|
|
414
|
+
import {
|
|
415
|
+
getVmFunctionInfo,
|
|
416
|
+
isVmArray,
|
|
417
|
+
isVmExtern,
|
|
418
|
+
isVmFunction,
|
|
419
|
+
isVmModule,
|
|
420
|
+
isVmPrimitive,
|
|
421
|
+
isVmRecord,
|
|
422
|
+
isVmWrapper,
|
|
423
|
+
serialize
|
|
424
|
+
} from "@mirascript/mirascript";
|
|
425
|
+
import { lib, operations, serializeRecordKey, serializeString } from "@mirascript/mirascript/subtle";
|
|
426
|
+
var UNKNOWN_REPR = "/* .. */";
|
|
427
|
+
function globalParamsSignature(info) {
|
|
428
|
+
if (info == null || !info.params && !info.paramsType) return [["..", "..", ""]];
|
|
429
|
+
const paramItems = [];
|
|
430
|
+
const params = Object.keys(info.paramsType ?? {});
|
|
431
|
+
for (const key of Object.keys(info.params ?? {})) {
|
|
432
|
+
if (params.includes(key)) continue;
|
|
433
|
+
params.push(key);
|
|
434
|
+
}
|
|
435
|
+
for (const key of params) {
|
|
436
|
+
const type = info.paramsType?.[key] ?? "";
|
|
437
|
+
const doc = info.params?.[key] ?? "";
|
|
438
|
+
paramItems.push([key, `${key}: ${type || "any"}`, doc ? `\`${key}\`: ${doc}` : ""]);
|
|
439
|
+
}
|
|
440
|
+
return paramItems;
|
|
441
|
+
}
|
|
442
|
+
var SIG_WIDTH = 60;
|
|
443
|
+
function fnSignature(id, info) {
|
|
444
|
+
const prefix = id ? `fn ${id}` : "fn";
|
|
445
|
+
const params = globalParamsSignature(info);
|
|
446
|
+
const returns = info.returnsType ? ` -> ${info.returnsType}` : "";
|
|
447
|
+
return {
|
|
448
|
+
params,
|
|
449
|
+
returns,
|
|
450
|
+
toString() {
|
|
451
|
+
let p;
|
|
452
|
+
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)) {
|
|
453
|
+
p = `(
|
|
454
|
+
${params.map((item) => ` ${item[1]},`).join("\n")}
|
|
455
|
+
)`;
|
|
456
|
+
} else {
|
|
457
|
+
p = `(${params.map((item) => item[1]).join(", ")})`;
|
|
458
|
+
}
|
|
459
|
+
return `${prefix}${p}${this.returns}`;
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
function localParamSignature(model, info) {
|
|
464
|
+
const {
|
|
465
|
+
args,
|
|
466
|
+
scope: { params }
|
|
467
|
+
} = info;
|
|
468
|
+
if (params[0]?.code === DiagnosticCode2.ParameterIt) {
|
|
469
|
+
return params[0].references.length ? [["it", "it", ""]] : [];
|
|
470
|
+
}
|
|
471
|
+
return params.map((a, i) => {
|
|
472
|
+
const rest = a.code === DiagnosticCode2.ParameterRestPattern || a.code === DiagnosticCode2.ParameterMutableRest || a.code === DiagnosticCode2.ParameterImmutableRest;
|
|
473
|
+
const argsInParam = args.filter((arg) => Range.containsRange(a.range, arg.definition.range));
|
|
474
|
+
let argName;
|
|
475
|
+
if (argsInParam.length > 0) {
|
|
476
|
+
argName = argsInParam.map((arg) => model.getValueInRange(arg.definition.range)).join("_");
|
|
477
|
+
} else if (rest) {
|
|
478
|
+
argName = "args";
|
|
479
|
+
} else {
|
|
480
|
+
argName = `arg${i}`;
|
|
481
|
+
}
|
|
482
|
+
if (rest) return [`..${argName}`, `..${argName}`, ""];
|
|
483
|
+
return [argName, argName, ""];
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
function paramsList(model, info) {
|
|
487
|
+
if (!info) return "(..)";
|
|
488
|
+
if ("scope" in info) {
|
|
489
|
+
return `(${localParamSignature(model, info).map((p) => p[1]).join(", ")})`;
|
|
490
|
+
} else {
|
|
491
|
+
if (!info.params) return "(..)";
|
|
492
|
+
const paramItems = Object.keys(info.params).join(", ");
|
|
493
|
+
return `(${paramItems})`;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
function globalFnDoc(info) {
|
|
497
|
+
const doc = [];
|
|
498
|
+
if (info.summary) {
|
|
499
|
+
doc.push(info.summary);
|
|
500
|
+
}
|
|
501
|
+
const paramDoc = [];
|
|
502
|
+
if (info.params) {
|
|
503
|
+
for (const [key, value] of Object.entries(info.params)) {
|
|
504
|
+
if (!value) continue;
|
|
505
|
+
paramDoc.push(`- \`${key}\`: ${value}`);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
if (info.returns) {
|
|
509
|
+
paramDoc.push(`- **返回值**: ${info.returns}`);
|
|
510
|
+
}
|
|
511
|
+
if (paramDoc.length) {
|
|
512
|
+
doc.push("", paramDoc.join("\n"));
|
|
513
|
+
}
|
|
514
|
+
if (info.examples?.length) {
|
|
515
|
+
let exp = `### 示例`;
|
|
516
|
+
for (const example of info.examples) {
|
|
517
|
+
exp += codeblock(example);
|
|
518
|
+
}
|
|
519
|
+
doc.push("", exp);
|
|
520
|
+
}
|
|
521
|
+
return doc;
|
|
522
|
+
}
|
|
523
|
+
function codeblock(value) {
|
|
524
|
+
const lang = value.startsWith("\0") ? "mirascript-doc" : "mirascript";
|
|
525
|
+
const includeFences = /`{3,}/.exec(value);
|
|
526
|
+
const CODEBLOCK_FENCE = includeFences ? "`".repeat(includeFences[0].length + 1) : "```";
|
|
527
|
+
return `
|
|
528
|
+
${CODEBLOCK_FENCE}${lang}
|
|
529
|
+
${value}
|
|
530
|
+
${CODEBLOCK_FENCE}
|
|
531
|
+
`;
|
|
532
|
+
}
|
|
533
|
+
function serializeIntegerImpl(num, base, prefix, sep) {
|
|
534
|
+
let str = Math.abs(num).toString(base);
|
|
535
|
+
if (base > 10) str = str.toUpperCase();
|
|
536
|
+
const sepSize = Math.abs(sep);
|
|
537
|
+
if (sep !== 0 && str.length > sepSize) {
|
|
538
|
+
const seg = [];
|
|
539
|
+
if (sep > 0) {
|
|
540
|
+
while (str.length > sepSize) {
|
|
541
|
+
seg.unshift(str.slice(-sepSize));
|
|
542
|
+
str = str.slice(0, -sepSize);
|
|
543
|
+
}
|
|
544
|
+
if (str.length > 0) {
|
|
545
|
+
seg.unshift(str);
|
|
546
|
+
}
|
|
547
|
+
} else {
|
|
548
|
+
while (str.length > sepSize) {
|
|
549
|
+
seg.push(str.slice(0, sepSize));
|
|
550
|
+
str = str.slice(sepSize);
|
|
551
|
+
}
|
|
552
|
+
if (str.length > 0) {
|
|
553
|
+
seg.push(str);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
str = seg.join("_");
|
|
557
|
+
}
|
|
558
|
+
return (num < 0 ? "-" : "") + prefix + str;
|
|
559
|
+
}
|
|
560
|
+
function serializeInteger(num, base, sep = true) {
|
|
561
|
+
const prefix = base === 2 ? "0b" : base === 8 ? "0o" : "0x";
|
|
562
|
+
const sepSize = sep ? base === 2 ? 8 : base === 8 ? 6 : 4 : 0;
|
|
563
|
+
return serializeIntegerImpl(num, base, prefix, sepSize);
|
|
564
|
+
}
|
|
565
|
+
function serializeNumber(num) {
|
|
566
|
+
if (!Number.isFinite(num)) {
|
|
567
|
+
return serialize(num);
|
|
568
|
+
}
|
|
569
|
+
const str = String(num);
|
|
570
|
+
const dot = str.indexOf(".");
|
|
571
|
+
const exp = str.indexOf("e");
|
|
572
|
+
let intPart;
|
|
573
|
+
let fracPart;
|
|
574
|
+
let expPart;
|
|
575
|
+
if (dot >= 0) {
|
|
576
|
+
intPart = str.slice(0, dot);
|
|
577
|
+
if (exp >= 0) {
|
|
578
|
+
fracPart = str.slice(dot + 1, exp);
|
|
579
|
+
expPart = str.slice(exp);
|
|
580
|
+
} else {
|
|
581
|
+
fracPart = str.slice(dot + 1);
|
|
582
|
+
expPart = "";
|
|
583
|
+
}
|
|
584
|
+
} else {
|
|
585
|
+
if (exp >= 0) {
|
|
586
|
+
intPart = str.slice(0, exp);
|
|
587
|
+
fracPart = "";
|
|
588
|
+
expPart = str.slice(exp);
|
|
589
|
+
} else {
|
|
590
|
+
intPart = str;
|
|
591
|
+
fracPart = "";
|
|
592
|
+
expPart = "";
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
if (intPart.length > 5) intPart = serializeIntegerImpl(Number(intPart), 10, "", 3);
|
|
596
|
+
if (fracPart.length > 5) fracPart = serializeIntegerImpl(Number(fracPart), 10, "", -3);
|
|
597
|
+
return intPart + (fracPart ? "." + fracPart : "") + expPart;
|
|
598
|
+
}
|
|
599
|
+
function serializeForDisplayInner(value, maxWidth) {
|
|
600
|
+
if (maxWidth < 10) maxWidth = 10;
|
|
601
|
+
if (typeof value === "string") {
|
|
602
|
+
if (value.length < maxWidth) {
|
|
603
|
+
return serializeString(value);
|
|
604
|
+
}
|
|
605
|
+
return `${serializeString(value.slice(0, maxWidth))}..`;
|
|
606
|
+
}
|
|
607
|
+
if (typeof value === "number") {
|
|
608
|
+
return serializeNumber(value);
|
|
609
|
+
}
|
|
610
|
+
if (isVmPrimitive(value)) {
|
|
611
|
+
return serialize(value);
|
|
612
|
+
}
|
|
613
|
+
if (isVmArray(value)) {
|
|
614
|
+
const len = value.length;
|
|
615
|
+
if (!len) return "[]";
|
|
616
|
+
return `[../* x${len} */]`;
|
|
617
|
+
}
|
|
618
|
+
if (isVmRecord(value)) {
|
|
619
|
+
const len = Object.keys(value).length;
|
|
620
|
+
if (!len) return "()";
|
|
621
|
+
return `(../* x${len} */)`;
|
|
622
|
+
}
|
|
623
|
+
if (isVmExtern(value)) {
|
|
624
|
+
return `/* <extern ${value.tag}> */`;
|
|
625
|
+
}
|
|
626
|
+
return `/* ${operations.$ToString(value)} */`;
|
|
627
|
+
}
|
|
628
|
+
function serializeField(obj, key, maxWidth) {
|
|
629
|
+
const value = getField(obj, key);
|
|
630
|
+
if (value === void 0) {
|
|
631
|
+
return UNKNOWN_REPR;
|
|
632
|
+
}
|
|
633
|
+
return serializeForDisplayInner(value, maxWidth);
|
|
634
|
+
}
|
|
635
|
+
function serializeForDisplay(value, maxEntries = 100, maxWidth = 40) {
|
|
636
|
+
if (isVmPrimitive(value) || isVmFunction(value)) {
|
|
637
|
+
return serializeForDisplayInner(value, maxWidth);
|
|
638
|
+
}
|
|
639
|
+
let begin, end;
|
|
640
|
+
const entries = [];
|
|
641
|
+
let resultLength = 0;
|
|
642
|
+
if (isVmArray(value)) {
|
|
643
|
+
begin = "[";
|
|
644
|
+
end = "]";
|
|
645
|
+
const len = value.length;
|
|
646
|
+
if (len === 0) return "[]";
|
|
647
|
+
for (let i = 0; i < len; i++) {
|
|
648
|
+
if (entries.length > maxEntries) {
|
|
649
|
+
entries.push(`../* x${value.length - entries.length} */`);
|
|
650
|
+
break;
|
|
651
|
+
}
|
|
652
|
+
const entry = serializeField(value, i, maxWidth - 2);
|
|
653
|
+
entries.push(entry);
|
|
654
|
+
resultLength += entry.length;
|
|
655
|
+
}
|
|
656
|
+
} else if (isVmRecord(value)) {
|
|
657
|
+
const keys = Object.keys(value);
|
|
658
|
+
if (keys.length === 0) return "()";
|
|
659
|
+
begin = "(";
|
|
660
|
+
end = ")";
|
|
661
|
+
for (const key of keys) {
|
|
662
|
+
if (entries.length > maxEntries) {
|
|
663
|
+
entries.push(`../* x${keys.length - entries.length} */`);
|
|
664
|
+
break;
|
|
665
|
+
}
|
|
666
|
+
const sk = serializeRecordKey(key);
|
|
667
|
+
const sv = serializeField(value, key, maxWidth - sk.length - 4);
|
|
668
|
+
const entry = `${sk}: ${sv}`;
|
|
669
|
+
entries.push(entry);
|
|
670
|
+
resultLength += entry.length;
|
|
671
|
+
}
|
|
672
|
+
} else {
|
|
673
|
+
const hint = serializeForDisplayInner(value, 100);
|
|
674
|
+
const isArray = value.isArrayLike();
|
|
675
|
+
begin = `${hint} ${isArray ? "[" : "("}`;
|
|
676
|
+
end = isArray ? "]" : ")";
|
|
677
|
+
const keys = value.keys();
|
|
678
|
+
if (keys.length === 0 && !isArray) {
|
|
679
|
+
if (typeof value.value == "object") {
|
|
680
|
+
for (const key of Object.getOwnPropertyNames(value.value)) {
|
|
681
|
+
if (value.has(key)) keys.push(key);
|
|
682
|
+
}
|
|
683
|
+
} else {
|
|
684
|
+
begin = hint;
|
|
685
|
+
end = "";
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
for (const [index, key] of keys.entries()) {
|
|
689
|
+
if (entries.length > maxEntries) {
|
|
690
|
+
entries.push(`../* x${keys.length - entries.length} */`);
|
|
691
|
+
break;
|
|
692
|
+
}
|
|
693
|
+
let entry;
|
|
694
|
+
if (isArray && String(index) === key) {
|
|
695
|
+
entry = serializeForDisplayInner(value.get(key) ?? null, maxWidth - 2);
|
|
696
|
+
} else {
|
|
697
|
+
const sk = serializeRecordKey(key);
|
|
698
|
+
entry = `${sk}: ${serializeForDisplayInner(value.get(key) ?? null, maxWidth - sk.length - 4)}`;
|
|
699
|
+
}
|
|
700
|
+
entries.push(entry);
|
|
701
|
+
resultLength += entry.length;
|
|
702
|
+
}
|
|
687
703
|
}
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
704
|
+
if (resultLength >= maxWidth) {
|
|
705
|
+
return `${begin}
|
|
706
|
+
${entries.join(",\n ")}
|
|
707
|
+
${end}`;
|
|
708
|
+
}
|
|
709
|
+
return `${begin}${entries.join(", ")}${end}`;
|
|
710
|
+
}
|
|
711
|
+
function docComment(doc) {
|
|
712
|
+
const lines = doc.flatMap((sec) => sec.split("\n").map((s) => s.trimEnd()));
|
|
713
|
+
const firstLine = lines.findIndex((line) => line.length > 0);
|
|
714
|
+
const lastLine = lines.findLastIndex((line) => line.length > 0);
|
|
715
|
+
if (firstLine < 0 || lastLine < 0) return [];
|
|
716
|
+
return [`/**`, ...lines.slice(firstLine, lastLine + 1).map((line) => ` * ${line}`), ` */`];
|
|
717
|
+
}
|
|
718
|
+
function valueDoc(name, value, type, parent) {
|
|
719
|
+
const info = getVmFunctionInfo(value);
|
|
720
|
+
const describe = parent?.describe?.(name);
|
|
721
|
+
if (info) {
|
|
722
|
+
const doc = globalFnDoc(info);
|
|
723
|
+
if (describe && doc[0] !== describe) {
|
|
724
|
+
doc.unshift(describe);
|
|
692
725
|
}
|
|
693
|
-
return
|
|
726
|
+
return {
|
|
727
|
+
script: fnSignature(name, info).toString() + (type === "declare" ? ";" : ""),
|
|
728
|
+
doc
|
|
729
|
+
};
|
|
694
730
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
731
|
+
let prefix;
|
|
732
|
+
let suffix = "";
|
|
733
|
+
if (type === "hint") {
|
|
734
|
+
prefix = `${serializeRecordKey(name)} = `;
|
|
735
|
+
} else if (type === "declare") {
|
|
736
|
+
if (name.startsWith("@")) {
|
|
737
|
+
prefix = `const ${name} = `;
|
|
738
|
+
} else {
|
|
739
|
+
prefix = `let ${name} = `;
|
|
703
740
|
}
|
|
704
|
-
|
|
741
|
+
suffix = ";";
|
|
742
|
+
} else if (/^\d/.test(name)) {
|
|
743
|
+
prefix = `[${name}]: `;
|
|
744
|
+
} else {
|
|
745
|
+
prefix = `${name}: `;
|
|
705
746
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
let
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
747
|
+
if (isVmModule(value)) {
|
|
748
|
+
const doc = `模块 \`${value.name}\``;
|
|
749
|
+
let script;
|
|
750
|
+
if (type === "declare") {
|
|
751
|
+
const exports = value.keys();
|
|
752
|
+
script = "\n";
|
|
753
|
+
for (const k of exports) {
|
|
754
|
+
const v = value.get(k);
|
|
755
|
+
const vDoc = valueDoc(k, v, isVmModule(v) ? "field" : "declare", value);
|
|
756
|
+
const code = [...docComment(vDoc.doc), "pub " + vDoc.script, "", ""];
|
|
757
|
+
script += code.join("\n");
|
|
716
758
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
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 };
|
|
759
|
+
script = script.trimEnd();
|
|
760
|
+
} else {
|
|
761
|
+
script = `(module) ${value.name}`;
|
|
762
|
+
if (value.name !== name) {
|
|
763
|
+
script = `${prefix}${script}`;
|
|
726
764
|
}
|
|
727
765
|
}
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
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;
|
|
766
|
+
return { script, doc: doc ? [doc] : [] };
|
|
767
|
+
}
|
|
768
|
+
let valueStr = UNKNOWN_REPR;
|
|
769
|
+
if (value !== void 0) {
|
|
770
|
+
try {
|
|
771
|
+
valueStr = serializeForDisplay(value, type === "declare" ? 1e3 : 100, type === "declare" ? 80 : 40);
|
|
772
|
+
} catch (ex) {
|
|
741
773
|
}
|
|
742
|
-
return { def: prevDef, fields: chainParts.slice(1) };
|
|
743
774
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
775
|
+
return {
|
|
776
|
+
script: `${prefix}${valueStr}${suffix}`,
|
|
777
|
+
doc: describe ? [describe] : []
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
function getDeep(globals, name, path) {
|
|
781
|
+
if (!globals.has(name)) return [null, void 0];
|
|
782
|
+
let current = globals.get(name);
|
|
783
|
+
if (!path.length) {
|
|
784
|
+
return [globals, current];
|
|
749
785
|
}
|
|
750
|
-
|
|
786
|
+
let parent = null;
|
|
787
|
+
for (const key of path) {
|
|
788
|
+
if (current == null) return [null, void 0];
|
|
789
|
+
if (!operations.$Has(current, key)) return [null, void 0];
|
|
790
|
+
parent = current;
|
|
791
|
+
current = operations.$Get(parent, key);
|
|
792
|
+
}
|
|
793
|
+
return [isVmWrapper(parent) ? parent : null, current];
|
|
794
|
+
}
|
|
795
|
+
function getField(obj, key) {
|
|
796
|
+
if (obj == null) return void 0;
|
|
797
|
+
try {
|
|
798
|
+
if (!operations.$Has(obj, key)) return void 0;
|
|
799
|
+
} catch {
|
|
800
|
+
return void 0;
|
|
801
|
+
}
|
|
802
|
+
try {
|
|
803
|
+
return operations.$Get(obj, key);
|
|
804
|
+
} catch {
|
|
805
|
+
return void 0;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
function listFields(obj, includeNonEnumerable) {
|
|
809
|
+
if (obj == null || typeof obj != "object") return [];
|
|
810
|
+
if (isVmWrapper(obj)) {
|
|
811
|
+
try {
|
|
812
|
+
return obj.keys(includeNonEnumerable);
|
|
813
|
+
} catch {
|
|
814
|
+
return [];
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
return lib.keys(obj);
|
|
818
|
+
}
|
|
819
|
+
function isDeprecatedGlobal(globals, name) {
|
|
820
|
+
if (!globals.has(name)) {
|
|
821
|
+
return void 0;
|
|
822
|
+
}
|
|
823
|
+
const value = globals.get(name);
|
|
824
|
+
const funcInfo = getVmFunctionInfo(value);
|
|
825
|
+
if (funcInfo) {
|
|
826
|
+
return funcInfo.deprecated;
|
|
827
|
+
}
|
|
828
|
+
const info = lib[name];
|
|
829
|
+
if (!info?.deprecated) return void 0;
|
|
830
|
+
if (info.value !== value) return void 0;
|
|
831
|
+
const { use } = info.deprecated;
|
|
832
|
+
if (use) {
|
|
833
|
+
if (!globals.has(use)) return void 0;
|
|
834
|
+
const replacement = globals.get(use);
|
|
835
|
+
if (replacement !== info.value) return void 0;
|
|
836
|
+
}
|
|
837
|
+
return info.deprecated;
|
|
838
|
+
}
|
|
751
839
|
|
|
752
840
|
// src/lsp/diagnostics.ts
|
|
753
|
-
import { DiagnosticCode as DiagnosticCode3, getDiagnosticMessage } from "@mirascript/mirascript/subtle";
|
|
754
841
|
var formatMessage = (model, template, $0) => {
|
|
755
842
|
if (template.includes(`$0`)) {
|
|
756
843
|
const replacement = typeof $0 == "string" ? $0 : $0 ? model.getValueInRange($0) : "";
|
|
@@ -1433,6 +1520,7 @@ import {
|
|
|
1433
1520
|
serialize as serialize2
|
|
1434
1521
|
} from "@mirascript/mirascript";
|
|
1435
1522
|
import { DiagnosticCode as DiagnosticCode6 } from "@mirascript/mirascript/subtle";
|
|
1523
|
+
import { KEYWORDS as HELP_KEYWORDS } from "@mirascript/help";
|
|
1436
1524
|
var DESC_GLOBAL = "(global)";
|
|
1437
1525
|
var DESC_LOCAL = "(local)";
|
|
1438
1526
|
var DESC_FIELD = "(field)";
|
|
@@ -1452,9 +1540,7 @@ var COMMON_GLOBAL_SUGGESTIONS = (range, extension) => {
|
|
|
1452
1540
|
kind: languages.CompletionItemKind.Keyword,
|
|
1453
1541
|
insertText: "type",
|
|
1454
1542
|
commitCharacters: ["("],
|
|
1455
|
-
documentation: {
|
|
1456
|
-
value: `使用 \`type()\` 调用获取表达式的类型。${codeblock("type(expression);\nexpression::type();")}`
|
|
1457
|
-
},
|
|
1543
|
+
documentation: { value: HELP_KEYWORDS.type },
|
|
1458
1544
|
range
|
|
1459
1545
|
},
|
|
1460
1546
|
{
|
|
@@ -1462,9 +1548,7 @@ var COMMON_GLOBAL_SUGGESTIONS = (range, extension) => {
|
|
|
1462
1548
|
kind: languages.CompletionItemKind.Keyword,
|
|
1463
1549
|
insertText: "global",
|
|
1464
1550
|
commitCharacters: [".", "["],
|
|
1465
|
-
documentation: {
|
|
1466
|
-
value: `使用 \`global\` 获取全局变量。${codeblock('global.variableName;\nglobal["variableName"];\n"variableName" in global;')}`
|
|
1467
|
-
},
|
|
1551
|
+
documentation: { value: HELP_KEYWORDS.global },
|
|
1468
1552
|
range
|
|
1469
1553
|
}
|
|
1470
1554
|
];
|
|
@@ -1572,10 +1656,12 @@ var COMMON_GLOBAL_SUGGESTIONS = (range, extension) => {
|
|
|
1572
1656
|
return suggestions;
|
|
1573
1657
|
};
|
|
1574
1658
|
function kwSuggestion(kw, range) {
|
|
1659
|
+
const doc = HELP_KEYWORDS[kw];
|
|
1575
1660
|
return {
|
|
1576
1661
|
label: kw,
|
|
1577
1662
|
kind: languages.CompletionItemKind.Keyword,
|
|
1578
1663
|
insertText: kw,
|
|
1664
|
+
documentation: doc ? { value: doc } : void 0,
|
|
1579
1665
|
range
|
|
1580
1666
|
};
|
|
1581
1667
|
}
|
|
@@ -2065,6 +2151,78 @@ var FormatterProvider = class extends Provider {
|
|
|
2065
2151
|
|
|
2066
2152
|
// src/lsp/providers/hover-provider.ts
|
|
2067
2153
|
import { DiagnosticCode as DiagnosticCode9 } from "@mirascript/constants";
|
|
2154
|
+
import { convert } from "@mirascript/mirascript/subtle";
|
|
2155
|
+
import { KEYWORDS as HELP_KEYWORDS2, OPERATORS as HELP_OPERATORS } from "@mirascript/help";
|
|
2156
|
+
|
|
2157
|
+
// src/lsp/monaco-private.js
|
|
2158
|
+
function fromStandardTokenType(tokenType) {
|
|
2159
|
+
switch (tokenType) {
|
|
2160
|
+
case 1:
|
|
2161
|
+
return "comment";
|
|
2162
|
+
case 2:
|
|
2163
|
+
return "string";
|
|
2164
|
+
case 3:
|
|
2165
|
+
return "regex";
|
|
2166
|
+
default:
|
|
2167
|
+
return "other";
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
function tokenAt(model, position) {
|
|
2171
|
+
try {
|
|
2172
|
+
let tryGetTokenProp2 = function(method, fallback) {
|
|
2173
|
+
try {
|
|
2174
|
+
return lineTokens[method](tokenIndex);
|
|
2175
|
+
} catch {
|
|
2176
|
+
return fallback;
|
|
2177
|
+
}
|
|
2178
|
+
};
|
|
2179
|
+
var tryGetTokenProp = tryGetTokenProp2;
|
|
2180
|
+
const lineTokens = model.tokenization.getLineTokens(position.lineNumber);
|
|
2181
|
+
const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
|
|
2182
|
+
if (tokenIndex < 0) return void 0;
|
|
2183
|
+
return {
|
|
2184
|
+
type: fromStandardTokenType(tryGetTokenProp2("getStandardTokenType", 0)),
|
|
2185
|
+
text: tryGetTokenProp2("getTokenText", null),
|
|
2186
|
+
startColumn: tryGetTokenProp2("getStartOffset", 0) + 1,
|
|
2187
|
+
endColumn: tryGetTokenProp2("getEndOffset", 0) + 1
|
|
2188
|
+
};
|
|
2189
|
+
} catch {
|
|
2190
|
+
return void 0;
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
// src/lsp/providers/hover-provider.ts
|
|
2195
|
+
var OPERATOR_TOKENS_DESC = Object.keys(HELP_OPERATORS).sort((a, b) => b.length - a.length);
|
|
2196
|
+
var REG_NUMBER_ALL_FULL = new RegExp(
|
|
2197
|
+
`^(?:${REG_BIN.source}|${REG_OCT.source}|${REG_HEX.source}|${REG_NUMBER.source})$`,
|
|
2198
|
+
REG_NUMBER.flags
|
|
2199
|
+
);
|
|
2200
|
+
var BIN_MAX = 2 ** 32 - 1;
|
|
2201
|
+
var OCT_MAX = 8 ** 18 - 1;
|
|
2202
|
+
var HEX_MAX = 16 ** 16 - 1;
|
|
2203
|
+
function operatorAt(lineContent, column) {
|
|
2204
|
+
const index = Math.max(0, column - 1);
|
|
2205
|
+
for (const token of OPERATOR_TOKENS_DESC) {
|
|
2206
|
+
for (let offset = 0; offset < token.length; offset++) {
|
|
2207
|
+
const start = index - offset;
|
|
2208
|
+
if (start < 0) continue;
|
|
2209
|
+
const end = start + token.length;
|
|
2210
|
+
if (end > lineContent.length) continue;
|
|
2211
|
+
if (lineContent.slice(start, end) !== token) continue;
|
|
2212
|
+
if (index < start || index >= end) continue;
|
|
2213
|
+
return {
|
|
2214
|
+
token,
|
|
2215
|
+
range: {
|
|
2216
|
+
startLineNumber: 0,
|
|
2217
|
+
startColumn: start + 1,
|
|
2218
|
+
endLineNumber: 0,
|
|
2219
|
+
endColumn: end + 1
|
|
2220
|
+
}
|
|
2221
|
+
};
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
return void 0;
|
|
2225
|
+
}
|
|
2068
2226
|
var HoverProvider = class extends Provider {
|
|
2069
2227
|
/** 变量提示 */
|
|
2070
2228
|
async provideVariableHover(model, { def, ref }) {
|
|
@@ -2171,11 +2329,77 @@ var HoverProvider = class extends Provider {
|
|
|
2171
2329
|
range
|
|
2172
2330
|
};
|
|
2173
2331
|
}
|
|
2332
|
+
/** 语法元素提示 */
|
|
2333
|
+
provideSyntaxHover(model, position) {
|
|
2334
|
+
const token = tokenAt(model, position);
|
|
2335
|
+
if (token?.type && token.type !== "other") {
|
|
2336
|
+
return void 0;
|
|
2337
|
+
}
|
|
2338
|
+
if (token?.text) {
|
|
2339
|
+
if (token.text in HELP_KEYWORDS2) {
|
|
2340
|
+
const doc = HELP_KEYWORDS2[token.text];
|
|
2341
|
+
return {
|
|
2342
|
+
contents: [{ value: doc }],
|
|
2343
|
+
range: rangeAt(position, token)
|
|
2344
|
+
};
|
|
2345
|
+
}
|
|
2346
|
+
if (token.text in HELP_OPERATORS) {
|
|
2347
|
+
const doc = HELP_OPERATORS[token.text];
|
|
2348
|
+
return {
|
|
2349
|
+
contents: [{ value: doc }],
|
|
2350
|
+
range: rangeAt(position, token)
|
|
2351
|
+
};
|
|
2352
|
+
}
|
|
2353
|
+
if (REG_NUMBER_ALL_FULL.test(token.text)) {
|
|
2354
|
+
const num = convert.toNumber(token.text.replaceAll("_", ""), null);
|
|
2355
|
+
if (num == null) return void 0;
|
|
2356
|
+
const contents = [
|
|
2357
|
+
{ value: `数字字面量` },
|
|
2358
|
+
{ value: codeblock("val: " + serializeNumber(num)) }
|
|
2359
|
+
];
|
|
2360
|
+
if (Number.isInteger(num)) {
|
|
2361
|
+
const abs = Math.abs(num);
|
|
2362
|
+
if (abs <= BIN_MAX) {
|
|
2363
|
+
contents.push({ value: codeblock("bin: " + serializeInteger(num, 2)) });
|
|
2364
|
+
}
|
|
2365
|
+
if (abs <= OCT_MAX) {
|
|
2366
|
+
contents.push({ value: codeblock("oct: " + serializeInteger(num, 8)) });
|
|
2367
|
+
}
|
|
2368
|
+
if (abs <= HEX_MAX) {
|
|
2369
|
+
contents.push({ value: codeblock("hex: " + serializeInteger(num, 16)) });
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
return {
|
|
2373
|
+
contents,
|
|
2374
|
+
range: rangeAt(position, token)
|
|
2375
|
+
};
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
const word = model.getWordAtPosition(position);
|
|
2379
|
+
if (word?.word && word.word in HELP_KEYWORDS2) {
|
|
2380
|
+
const doc = HELP_KEYWORDS2[word.word];
|
|
2381
|
+
return {
|
|
2382
|
+
contents: [{ value: doc }],
|
|
2383
|
+
range: rangeAt(position, word)
|
|
2384
|
+
};
|
|
2385
|
+
}
|
|
2386
|
+
const lineContent = model.getLineContent(position.lineNumber);
|
|
2387
|
+
const hit = operatorAt(lineContent, position.column);
|
|
2388
|
+
if (hit && hit.token in HELP_OPERATORS) {
|
|
2389
|
+
const doc = HELP_OPERATORS[hit.token];
|
|
2390
|
+
return {
|
|
2391
|
+
contents: [{ value: doc }],
|
|
2392
|
+
range: rangeAt(position, hit.range)
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2395
|
+
return void 0;
|
|
2396
|
+
}
|
|
2174
2397
|
/** @inheritdoc */
|
|
2175
2398
|
async provideHover(model, position, token, context) {
|
|
2176
2399
|
const value = await this.getValueAt(model, position);
|
|
2177
|
-
if (!value)
|
|
2178
|
-
|
|
2400
|
+
if (!value) {
|
|
2401
|
+
return this.provideSyntaxHover(model, position);
|
|
2402
|
+
} else if ("fields" in value) {
|
|
2179
2403
|
return this.provideFieldHover(model, value.range, value.fields);
|
|
2180
2404
|
} else {
|
|
2181
2405
|
return this.provideVariableHover(model, value.variable);
|