@mirascript/monaco 0.1.61 → 0.1.62-alpha.7
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/LICENSE +21 -0
- package/package.json +5 -5
- package/dist/basic/index.d.ts +0 -6
- package/dist/basic/index.d.ts.map +0 -1
- package/dist/basic/index.js +0 -10
- package/dist/basic/index.js.map +0 -6
- package/dist/basic/language-configuration.d.ts +0 -5
- package/dist/basic/language-configuration.d.ts.map +0 -1
- package/dist/basic/tokens-provider.d.ts +0 -4
- package/dist/basic/tokens-provider.d.ts.map +0 -1
- package/dist/chunk-NAOKM25O.js +0 -63
- package/dist/chunk-NAOKM25O.js.map +0 -6
- package/dist/chunk-SCSO2D5U.js +0 -570
- package/dist/chunk-SCSO2D5U.js.map +0 -6
- package/dist/constants.d.ts +0 -5
- package/dist/constants.d.ts.map +0 -1
- package/dist/contribute.d.ts +0 -3
- package/dist/contribute.d.ts.map +0 -1
- package/dist/index.d.ts +0 -27
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -89
- package/dist/index.js.map +0 -6
- package/dist/lsp/compile-result.d.ts +0 -147
- package/dist/lsp/compile-result.d.ts.map +0 -1
- package/dist/lsp/diagnostics.d.ts +0 -8
- package/dist/lsp/diagnostics.d.ts.map +0 -1
- package/dist/lsp/index.d.ts +0 -43
- package/dist/lsp/index.d.ts.map +0 -1
- package/dist/lsp/index.js +0 -3097
- package/dist/lsp/index.js.map +0 -6
- package/dist/lsp/monaco-private.d.ts +0 -19
- package/dist/lsp/monaco-private.d.ts.map +0 -1
- package/dist/lsp/monaco-utils.d.ts +0 -20
- package/dist/lsp/monaco-utils.d.ts.map +0 -1
- package/dist/lsp/providers/base.d.ts +0 -43
- package/dist/lsp/providers/base.d.ts.map +0 -1
- package/dist/lsp/providers/code-action-provider.d.ts +0 -12
- package/dist/lsp/providers/code-action-provider.d.ts.map +0 -1
- package/dist/lsp/providers/code-lens-provider.d.ts +0 -12
- package/dist/lsp/providers/code-lens-provider.d.ts.map +0 -1
- package/dist/lsp/providers/color-provider.d.ts +0 -10
- package/dist/lsp/providers/color-provider.d.ts.map +0 -1
- package/dist/lsp/providers/completion-item-provider.d.ts +0 -21
- package/dist/lsp/providers/completion-item-provider.d.ts.map +0 -1
- package/dist/lsp/providers/definition-reference-provider.d.ts +0 -19
- package/dist/lsp/providers/definition-reference-provider.d.ts.map +0 -1
- package/dist/lsp/providers/document-highlight-provider.d.ts +0 -12
- package/dist/lsp/providers/document-highlight-provider.d.ts.map +0 -1
- package/dist/lsp/providers/document-symbol-provider.d.ts +0 -10
- package/dist/lsp/providers/document-symbol-provider.d.ts.map +0 -1
- package/dist/lsp/providers/formatter-provider.d.ts +0 -18
- package/dist/lsp/providers/formatter-provider.d.ts.map +0 -1
- package/dist/lsp/providers/hover-provider.d.ts +0 -14
- package/dist/lsp/providers/hover-provider.d.ts.map +0 -1
- package/dist/lsp/providers/inlay-hints-provider.d.ts +0 -10
- package/dist/lsp/providers/inlay-hints-provider.d.ts.map +0 -1
- package/dist/lsp/providers/range-provider.d.ts +0 -10
- package/dist/lsp/providers/range-provider.d.ts.map +0 -1
- package/dist/lsp/providers/rename-provider.d.ts +0 -12
- package/dist/lsp/providers/rename-provider.d.ts.map +0 -1
- package/dist/lsp/providers/semantic-tokens-provider.d.ts +0 -12
- package/dist/lsp/providers/semantic-tokens-provider.d.ts.map +0 -1
- package/dist/lsp/providers/signature-help-provider.d.ts +0 -12
- package/dist/lsp/providers/signature-help-provider.d.ts.map +0 -1
- package/dist/lsp/utils.d.ts +0 -41
- package/dist/lsp/utils.d.ts.map +0 -1
- package/dist/lsp/worker-helper.d.ts +0 -5
- package/dist/lsp/worker-helper.d.ts.map +0 -1
- package/dist/lsp/worker.d.ts +0 -23
- package/dist/lsp/worker.d.ts.map +0 -1
- package/dist/lsp/worker.js +0 -63
- package/dist/lsp/worker.js.map +0 -6
- package/dist/monaco-api.d.ts +0 -16
- package/dist/monaco-api.d.ts.map +0 -1
package/dist/lsp/index.js
DELETED
|
@@ -1,3097 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
KEYWORDS,
|
|
3
|
-
REG_BIN,
|
|
4
|
-
REG_HEX,
|
|
5
|
-
REG_IDENTIFIER_FULL,
|
|
6
|
-
REG_NUMBER,
|
|
7
|
-
REG_OCT,
|
|
8
|
-
REG_ORDINAL_FULL,
|
|
9
|
-
RESERVED_KEYWORDS,
|
|
10
|
-
isKeyword
|
|
11
|
-
} from "../chunk-SCSO2D5U.js";
|
|
12
|
-
import {
|
|
13
|
-
Emitter,
|
|
14
|
-
MarkerSeverity,
|
|
15
|
-
MarkerTag,
|
|
16
|
-
Position,
|
|
17
|
-
Range,
|
|
18
|
-
Uri,
|
|
19
|
-
editor,
|
|
20
|
-
languages
|
|
21
|
-
} from "../chunk-NAOKM25O.js";
|
|
22
|
-
|
|
23
|
-
// src/lsp/providers/base.ts
|
|
24
|
-
import { DefaultVmContext } from "@mirascript/mirascript/subtle";
|
|
25
|
-
|
|
26
|
-
// src/lsp/monaco-utils.ts
|
|
27
|
-
function strictContainsPosition(range, position) {
|
|
28
|
-
return !Range.isEmpty(range) && Range.containsPosition(range, position);
|
|
29
|
-
}
|
|
30
|
-
function wordAt(model, position) {
|
|
31
|
-
const word = model.getWordAtPosition(position);
|
|
32
|
-
if (!word) return void 0;
|
|
33
|
-
const range = new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn);
|
|
34
|
-
return { word: word.word, range };
|
|
35
|
-
}
|
|
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);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// src/lsp/compile-result.ts
|
|
48
|
-
import {
|
|
49
|
-
parseDiagnostics,
|
|
50
|
-
DiagnosticCode
|
|
51
|
-
} from "@mirascript/mirascript/subtle";
|
|
52
|
-
var LocalVariableType = [
|
|
53
|
-
DiagnosticCode.LocalMutable,
|
|
54
|
-
DiagnosticCode.LocalImmutable,
|
|
55
|
-
DiagnosticCode.LocalConst,
|
|
56
|
-
DiagnosticCode.LocalFunction,
|
|
57
|
-
DiagnosticCode.LocalModule
|
|
58
|
-
];
|
|
59
|
-
var ParameterExplicitType = [
|
|
60
|
-
DiagnosticCode.ParameterMutable,
|
|
61
|
-
DiagnosticCode.ParameterImmutable,
|
|
62
|
-
DiagnosticCode.ParameterMutableRest,
|
|
63
|
-
DiagnosticCode.ParameterImmutableRest
|
|
64
|
-
];
|
|
65
|
-
var ParameterSubPatternType = [
|
|
66
|
-
DiagnosticCode.ParameterSubPatternImmutable,
|
|
67
|
-
DiagnosticCode.ParameterSubPatternMutable
|
|
68
|
-
];
|
|
69
|
-
var ParameterPatternType = [DiagnosticCode.ParameterPattern, DiagnosticCode.ParameterRestPattern];
|
|
70
|
-
var ParameterItType = [DiagnosticCode.ParameterIt];
|
|
71
|
-
var ParameterDefinitionType = [
|
|
72
|
-
...ParameterExplicitType,
|
|
73
|
-
...ParameterSubPatternType,
|
|
74
|
-
...ParameterItType
|
|
75
|
-
];
|
|
76
|
-
var ParameterPlaceholderType = [
|
|
77
|
-
...ParameterExplicitType,
|
|
78
|
-
...ParameterPatternType,
|
|
79
|
-
...ParameterItType
|
|
80
|
-
];
|
|
81
|
-
var LocalDefinitionType = [...LocalVariableType, ...ParameterDefinitionType];
|
|
82
|
-
var CompileResult = class {
|
|
83
|
-
constructor(cacheKey, version, source, result) {
|
|
84
|
-
this.cacheKey = cacheKey;
|
|
85
|
-
this.version = version;
|
|
86
|
-
this.source = source;
|
|
87
|
-
this.result = result;
|
|
88
|
-
this.diagnosticsReady = false;
|
|
89
|
-
this._errors = [];
|
|
90
|
-
this._warnings = [];
|
|
91
|
-
this._infos = [];
|
|
92
|
-
this._hints = [];
|
|
93
|
-
this._references = [];
|
|
94
|
-
this._tags = [];
|
|
95
|
-
this._tagsReferences = [];
|
|
96
|
-
this.diagnostics = result.diagnostics;
|
|
97
|
-
this.chunk = result.chunk;
|
|
98
|
-
}
|
|
99
|
-
/** 源代码诊断信息 */
|
|
100
|
-
get errors() {
|
|
101
|
-
if (!this.diagnosticsReady) {
|
|
102
|
-
this.readDiagnostics();
|
|
103
|
-
}
|
|
104
|
-
return this._errors;
|
|
105
|
-
}
|
|
106
|
-
/** 源代码诊断信息 */
|
|
107
|
-
get warnings() {
|
|
108
|
-
if (!this.diagnosticsReady) {
|
|
109
|
-
this.readDiagnostics();
|
|
110
|
-
}
|
|
111
|
-
return this._warnings;
|
|
112
|
-
}
|
|
113
|
-
/** 源代码诊断信息 */
|
|
114
|
-
get infos() {
|
|
115
|
-
if (!this.diagnosticsReady) {
|
|
116
|
-
this.readDiagnostics();
|
|
117
|
-
}
|
|
118
|
-
return this._infos;
|
|
119
|
-
}
|
|
120
|
-
/** 源代码诊断信息 */
|
|
121
|
-
get hints() {
|
|
122
|
-
if (!this.diagnosticsReady) {
|
|
123
|
-
this.readDiagnostics();
|
|
124
|
-
}
|
|
125
|
-
return this._hints;
|
|
126
|
-
}
|
|
127
|
-
/** 源代码诊断信息 */
|
|
128
|
-
get references() {
|
|
129
|
-
if (!this.diagnosticsReady) {
|
|
130
|
-
this.readDiagnostics();
|
|
131
|
-
}
|
|
132
|
-
return this._references;
|
|
133
|
-
}
|
|
134
|
-
/** 源代码诊断信息 */
|
|
135
|
-
get tags() {
|
|
136
|
-
if (!this.diagnosticsReady) {
|
|
137
|
-
this.readDiagnostics();
|
|
138
|
-
}
|
|
139
|
-
return this._tags;
|
|
140
|
-
}
|
|
141
|
-
/** 源代码诊断信息 */
|
|
142
|
-
get tagsReferences() {
|
|
143
|
-
if (!this.diagnosticsReady) {
|
|
144
|
-
this.readDiagnostics();
|
|
145
|
-
}
|
|
146
|
-
return this._tagsReferences;
|
|
147
|
-
}
|
|
148
|
-
/** 分析诊断信息 */
|
|
149
|
-
readDiagnostics() {
|
|
150
|
-
const parsed = parseDiagnostics(this.source, this.diagnostics, (c) => c !== DiagnosticCode.SourceMap);
|
|
151
|
-
this._errors = parsed.errors;
|
|
152
|
-
this._warnings = parsed.warnings;
|
|
153
|
-
this._infos = parsed.infos;
|
|
154
|
-
this._hints = parsed.hints;
|
|
155
|
-
this._tags = parsed.tags;
|
|
156
|
-
this._references = parsed.references;
|
|
157
|
-
this._tagsReferences = parsed.tagsReferences;
|
|
158
|
-
this.diagnosticsReady = true;
|
|
159
|
-
}
|
|
160
|
-
/** 获取源代码定义 */
|
|
161
|
-
groupedTags(model) {
|
|
162
|
-
if (this._groupedTags) {
|
|
163
|
-
return this._groupedTags;
|
|
164
|
-
}
|
|
165
|
-
const getText = (range) => {
|
|
166
|
-
if (model.getVersionId() !== this.version) {
|
|
167
|
-
return void 0;
|
|
168
|
-
}
|
|
169
|
-
return model.getValueInRange(range);
|
|
170
|
-
};
|
|
171
|
-
const locals = [];
|
|
172
|
-
const params = [];
|
|
173
|
-
const globals = [];
|
|
174
|
-
const ranges = [];
|
|
175
|
-
const omitNameFields = [];
|
|
176
|
-
for (const tag of this.tags) {
|
|
177
|
-
if (ParameterPlaceholderType.includes(tag.code)) {
|
|
178
|
-
params.push(tag);
|
|
179
|
-
}
|
|
180
|
-
if (LocalDefinitionType.includes(tag.code)) {
|
|
181
|
-
locals.push({
|
|
182
|
-
definition: tag,
|
|
183
|
-
references: tag.references
|
|
184
|
-
});
|
|
185
|
-
} else if (tag.code === DiagnosticCode.GlobalVariable) {
|
|
186
|
-
const name = getText(tag.range);
|
|
187
|
-
let def = globals.find((def2) => name === def2.name);
|
|
188
|
-
if (!def) {
|
|
189
|
-
def = {
|
|
190
|
-
name: name ?? "",
|
|
191
|
-
references: []
|
|
192
|
-
};
|
|
193
|
-
globals.push(def);
|
|
194
|
-
}
|
|
195
|
-
def.references.push(tag);
|
|
196
|
-
} else if (tag.code === DiagnosticCode.Scope || tag.code === DiagnosticCode.String || tag.code === DiagnosticCode.Interpolation || tag.code === DiagnosticCode.FunctionCall || tag.code === DiagnosticCode.ExtensionCall) {
|
|
197
|
-
ranges.push(tag);
|
|
198
|
-
} else if (tag.code === DiagnosticCode.OmitNamedRecordField) {
|
|
199
|
-
omitNameFields.push(tag);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
locals.sort(
|
|
203
|
-
(a, b) => Range.compareRangesUsingStarts(a.definition.range, b.definition.range)
|
|
204
|
-
);
|
|
205
|
-
params.sort((a, b) => Range.compareRangesUsingStarts(a.range, b.range));
|
|
206
|
-
globals.sort((a, b) => a.name.localeCompare(b.name));
|
|
207
|
-
ranges.sort((a, b) => Range.compareRangesUsingStarts(a.range, b.range));
|
|
208
|
-
this._groupedTags = {
|
|
209
|
-
locals,
|
|
210
|
-
params,
|
|
211
|
-
globals,
|
|
212
|
-
ranges,
|
|
213
|
-
omitNameFields
|
|
214
|
-
};
|
|
215
|
-
return this._groupedTags;
|
|
216
|
-
}
|
|
217
|
-
/** 获取指定位置的变量访问信息 */
|
|
218
|
-
variableAccessAt(model, position) {
|
|
219
|
-
const { globals } = this.groupedTags(model);
|
|
220
|
-
for (const d of globals) {
|
|
221
|
-
const refIndex = d.references.findIndex((u) => strictContainsPosition(u.range, position));
|
|
222
|
-
if (refIndex >= 0) {
|
|
223
|
-
return { def: d, ref: refIndex, range: d.references[refIndex].range };
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
this.scopes(model);
|
|
227
|
-
const { locals } = this.groupedTags(model);
|
|
228
|
-
for (const d of locals) {
|
|
229
|
-
if (strictContainsPosition(d.definition.range, position)) {
|
|
230
|
-
return { def: d, ref: void 0, range: d.definition.range };
|
|
231
|
-
}
|
|
232
|
-
const refIndex = d.references.findIndex((u) => strictContainsPosition(u.range, position));
|
|
233
|
-
if (refIndex >= 0) {
|
|
234
|
-
return { def: d, ref: refIndex, range: d.references[refIndex].range };
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
return void 0;
|
|
238
|
-
}
|
|
239
|
-
/** 获取作用域信息 */
|
|
240
|
-
scopes(model) {
|
|
241
|
-
if (this._scopes) {
|
|
242
|
-
return this._scopes;
|
|
243
|
-
}
|
|
244
|
-
const { locals, params, ranges } = this.groupedTags(model);
|
|
245
|
-
const scopes = ranges.filter((r) => r.code === DiagnosticCode.Scope).map((r) => {
|
|
246
|
-
return {
|
|
247
|
-
range: r.range,
|
|
248
|
-
locals: [],
|
|
249
|
-
params: [],
|
|
250
|
-
parent: void 0,
|
|
251
|
-
children: []
|
|
252
|
-
};
|
|
253
|
-
});
|
|
254
|
-
for (let i = 0; i < scopes.length; i++) {
|
|
255
|
-
const scopeA = scopes[i];
|
|
256
|
-
let parent;
|
|
257
|
-
for (let j = 0; j < scopes.length; j++) {
|
|
258
|
-
if (i === j) continue;
|
|
259
|
-
const scopeB = scopes[j];
|
|
260
|
-
const aRange = scopeA.range;
|
|
261
|
-
const bRange = scopeB.range;
|
|
262
|
-
const isContained = Range.containsRange(bRange, aRange);
|
|
263
|
-
if (isContained) {
|
|
264
|
-
if (!parent || Range.containsRange(parent.range, bRange)) {
|
|
265
|
-
parent = scopeB;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
if (parent) {
|
|
270
|
-
if (parent.parent === scopeA) {
|
|
271
|
-
continue;
|
|
272
|
-
}
|
|
273
|
-
scopeA.parent = parent;
|
|
274
|
-
parent.children.push(scopeA);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
const root = scopes.find((s) => !s.parent);
|
|
278
|
-
if (!root) {
|
|
279
|
-
this._scopes = [
|
|
280
|
-
{
|
|
281
|
-
range: model.getFullModelRange(),
|
|
282
|
-
locals: [],
|
|
283
|
-
params: [],
|
|
284
|
-
parent: void 0,
|
|
285
|
-
children: []
|
|
286
|
-
}
|
|
287
|
-
];
|
|
288
|
-
return this._scopes;
|
|
289
|
-
}
|
|
290
|
-
const queue = [root];
|
|
291
|
-
const sortedScopes = [];
|
|
292
|
-
while (queue.length > 0) {
|
|
293
|
-
const scope = queue.shift();
|
|
294
|
-
sortedScopes.push(scope);
|
|
295
|
-
scope.children.sort(
|
|
296
|
-
(a, b) => Range.compareRangesUsingStarts(a.range, b.range)
|
|
297
|
-
);
|
|
298
|
-
for (const child of scope.children) {
|
|
299
|
-
queue.push(child);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
for (const local of locals) {
|
|
303
|
-
const { range } = local.definition;
|
|
304
|
-
const scope = sortedScopes.findLast((s) => Range.containsRange(s.range, range));
|
|
305
|
-
if (scope) {
|
|
306
|
-
scope.locals.push(local);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
for (const param of params) {
|
|
310
|
-
const { range } = param;
|
|
311
|
-
const scope = sortedScopes.findLast((s) => Range.containsRange(s.range, range));
|
|
312
|
-
if (scope) {
|
|
313
|
-
scope.params.push(param);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
const scopeMap = /* @__PURE__ */ new Map();
|
|
317
|
-
for (const scope of sortedScopes) {
|
|
318
|
-
scope.locals.sort(
|
|
319
|
-
(a, b) => Range.compareRangesUsingStarts(a.definition.range, b.definition.range)
|
|
320
|
-
);
|
|
321
|
-
scope.params.sort(
|
|
322
|
-
(a, b) => Range.compareRangesUsingStarts(a.range, b.range)
|
|
323
|
-
);
|
|
324
|
-
for (const local of scope.locals) {
|
|
325
|
-
scopeMap.set(local, scope);
|
|
326
|
-
if (local.definition.code === DiagnosticCode.LocalFunction) {
|
|
327
|
-
const funcScope = scope.children.find(
|
|
328
|
-
(s) => Range.compareRangesUsingStarts(s.range, local.definition.range) > 0
|
|
329
|
-
);
|
|
330
|
-
if (funcScope) {
|
|
331
|
-
const args = funcScope.locals.filter(
|
|
332
|
-
(l) => ParameterDefinitionType.includes(l.definition.code)
|
|
333
|
-
);
|
|
334
|
-
local.fn = {
|
|
335
|
-
scope: funcScope,
|
|
336
|
-
args
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
this._scopeMap = scopeMap;
|
|
343
|
-
this._scopes = sortedScopes;
|
|
344
|
-
return this._scopes;
|
|
345
|
-
}
|
|
346
|
-
/** 获取定义所在作用域 */
|
|
347
|
-
scopeOf(model, def) {
|
|
348
|
-
if (!this._scopeMap) {
|
|
349
|
-
this.scopes(model);
|
|
350
|
-
}
|
|
351
|
-
return this._scopeMap.get(def);
|
|
352
|
-
}
|
|
353
|
-
/** 获取位置所在作用域 */
|
|
354
|
-
scopeAt(model, position) {
|
|
355
|
-
const scopes = this.scopes(model);
|
|
356
|
-
let scope = scopes.findLast((s) => Range.containsPosition(s.range, position)) ?? scopes[0];
|
|
357
|
-
while (scope.children.length > 0) {
|
|
358
|
-
const inner = scope.children.find((s) => Range.containsPosition(s.range, position));
|
|
359
|
-
if (!inner) break;
|
|
360
|
-
scope = inner;
|
|
361
|
-
}
|
|
362
|
-
return scope;
|
|
363
|
-
}
|
|
364
|
-
/** 获取指定位置的字段访问信息 */
|
|
365
|
-
fieldAccessAt(model, position) {
|
|
366
|
-
let prevDef;
|
|
367
|
-
const { globals } = this.groupedTags(model);
|
|
368
|
-
for (const d of globals) {
|
|
369
|
-
for (const [refIndex, ref] of d.references.entries()) {
|
|
370
|
-
if (!Position.isBefore(Range.getEndPosition(ref.range), position)) continue;
|
|
371
|
-
if (prevDef && Position.isBefore(Range.getEndPosition(ref.range), Range.getEndPosition(prevDef.range)))
|
|
372
|
-
continue;
|
|
373
|
-
prevDef = { def: d, ref: refIndex, range: ref.range };
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
this.scopes(model);
|
|
377
|
-
const { locals } = this.groupedTags(model);
|
|
378
|
-
for (const d of locals) {
|
|
379
|
-
for (const [refIndex, ref] of d.references.entries()) {
|
|
380
|
-
if (!Position.isBefore(Range.getEndPosition(ref.range), position)) continue;
|
|
381
|
-
if (prevDef && Position.isBefore(Range.getEndPosition(ref.range), Range.getEndPosition(prevDef.range)))
|
|
382
|
-
continue;
|
|
383
|
-
prevDef = { def: d, ref: refIndex, range: ref.range };
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
if (!prevDef) return void 0;
|
|
387
|
-
const chain = model.getValueInRange(Range.fromPositions(Range.getStartPosition(prevDef.range), position));
|
|
388
|
-
const chainParts = chain.split(/\s*(?:!\.|\.)\s*/);
|
|
389
|
-
if (
|
|
390
|
-
// 至少包含变量名和当前位置的字段名
|
|
391
|
-
chainParts.length < 2 || !chainParts.every(
|
|
392
|
-
(part, index) => (
|
|
393
|
-
// 如果是最后一个部分,则可以为空(表示当前位置的字段名),否则必须是合法的标识符
|
|
394
|
-
(index === chainParts.length - 1 ? !part : false) || REG_IDENTIFIER_FULL.test(part) || REG_ORDINAL_FULL.test(part)
|
|
395
|
-
)
|
|
396
|
-
)
|
|
397
|
-
) {
|
|
398
|
-
return void 0;
|
|
399
|
-
}
|
|
400
|
-
return { def: prevDef, fields: chainParts.slice(1) };
|
|
401
|
-
}
|
|
402
|
-
/** 获取指定位置的字段访问信息 */
|
|
403
|
-
accessAt(model, position) {
|
|
404
|
-
const v = this.variableAccessAt(model, position);
|
|
405
|
-
if (v) return { def: v, fields: [] };
|
|
406
|
-
return this.fieldAccessAt(model, position);
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
// src/lsp/diagnostics.ts
|
|
411
|
-
import { DiagnosticCode as DiagnosticCode3, getDiagnosticMessage, formatDiagnosticMessage } from "@mirascript/mirascript/subtle";
|
|
412
|
-
|
|
413
|
-
// src/lsp/utils.ts
|
|
414
|
-
import { DiagnosticCode as DiagnosticCode2 } from "@mirascript/constants";
|
|
415
|
-
import {
|
|
416
|
-
getVmFunctionInfo,
|
|
417
|
-
isVmArray,
|
|
418
|
-
isVmExtern,
|
|
419
|
-
isVmFunction,
|
|
420
|
-
isVmModule,
|
|
421
|
-
isVmPrimitive,
|
|
422
|
-
isVmRecord,
|
|
423
|
-
isVmWrapper,
|
|
424
|
-
serialize
|
|
425
|
-
} from "@mirascript/mirascript";
|
|
426
|
-
import { lib, operations, serializeRecordKey, serializeString } from "@mirascript/mirascript/subtle";
|
|
427
|
-
var UNKNOWN_REPR = "/* .. */";
|
|
428
|
-
function globalParamsSignature(info) {
|
|
429
|
-
if (info == null || !info.params && !info.paramsType) return [["..", "..", ""]];
|
|
430
|
-
const paramItems = [];
|
|
431
|
-
const params = Object.keys(info.paramsType ?? {});
|
|
432
|
-
for (const key of Object.keys(info.params ?? {})) {
|
|
433
|
-
if (params.includes(key)) continue;
|
|
434
|
-
params.push(key);
|
|
435
|
-
}
|
|
436
|
-
for (const key of params) {
|
|
437
|
-
const type = info.paramsType?.[key] ?? "";
|
|
438
|
-
const doc = info.params?.[key] ?? "";
|
|
439
|
-
paramItems.push([key, `${key}: ${type || "any"}`, doc ? `\`${key}\`: ${doc}` : ""]);
|
|
440
|
-
}
|
|
441
|
-
return paramItems;
|
|
442
|
-
}
|
|
443
|
-
var SIG_WIDTH = 60;
|
|
444
|
-
function fnSignature(id, info) {
|
|
445
|
-
const prefix = id ? `fn ${id}` : "fn";
|
|
446
|
-
const params = globalParamsSignature(info);
|
|
447
|
-
const returns = info.returnsType ? ` -> ${info.returnsType}` : "";
|
|
448
|
-
return {
|
|
449
|
-
params,
|
|
450
|
-
returns,
|
|
451
|
-
toString() {
|
|
452
|
-
let p;
|
|
453
|
-
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)) {
|
|
454
|
-
p = `(
|
|
455
|
-
${params.map((item) => ` ${item[1]},`).join("\n")}
|
|
456
|
-
)`;
|
|
457
|
-
} else {
|
|
458
|
-
p = `(${params.map((item) => item[1]).join(", ")})`;
|
|
459
|
-
}
|
|
460
|
-
return `${prefix}${p}${this.returns}`;
|
|
461
|
-
}
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
function localParamSignature(model, info) {
|
|
465
|
-
const {
|
|
466
|
-
args,
|
|
467
|
-
scope: { params }
|
|
468
|
-
} = info;
|
|
469
|
-
if (params[0]?.code === DiagnosticCode2.ParameterIt) {
|
|
470
|
-
return params[0].references.length ? [["it", "it", ""]] : [];
|
|
471
|
-
}
|
|
472
|
-
return params.map((a, i) => {
|
|
473
|
-
const rest = a.code === DiagnosticCode2.ParameterRestPattern || a.code === DiagnosticCode2.ParameterMutableRest || a.code === DiagnosticCode2.ParameterImmutableRest;
|
|
474
|
-
const argsInParam = args.filter((arg) => Range.containsRange(a.range, arg.definition.range));
|
|
475
|
-
let argName;
|
|
476
|
-
if (argsInParam.length > 0) {
|
|
477
|
-
argName = argsInParam.map((arg) => model.getValueInRange(arg.definition.range)).join("_");
|
|
478
|
-
} else if (rest) {
|
|
479
|
-
argName = "args";
|
|
480
|
-
} else {
|
|
481
|
-
argName = `arg${i}`;
|
|
482
|
-
}
|
|
483
|
-
if (rest) return [`..${argName}`, `..${argName}`, ""];
|
|
484
|
-
return [argName, argName, ""];
|
|
485
|
-
});
|
|
486
|
-
}
|
|
487
|
-
function paramsList(model, info) {
|
|
488
|
-
if (!info) return "(..)";
|
|
489
|
-
if ("scope" in info) {
|
|
490
|
-
return `(${localParamSignature(model, info).map((p) => p[1]).join(", ")})`;
|
|
491
|
-
} else {
|
|
492
|
-
if (!info.params) return "(..)";
|
|
493
|
-
const paramItems = Object.keys(info.params).join(", ");
|
|
494
|
-
return `(${paramItems})`;
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
function globalFnDoc(info) {
|
|
498
|
-
const doc = [];
|
|
499
|
-
if (info.summary) {
|
|
500
|
-
doc.push(info.summary);
|
|
501
|
-
}
|
|
502
|
-
const paramDoc = [];
|
|
503
|
-
if (info.params) {
|
|
504
|
-
for (const [key, value] of Object.entries(info.params)) {
|
|
505
|
-
if (!value) continue;
|
|
506
|
-
paramDoc.push(`- \`${key}\`: ${value}`);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
if (info.returns) {
|
|
510
|
-
paramDoc.push(`- **返回值**: ${info.returns}`);
|
|
511
|
-
}
|
|
512
|
-
if (paramDoc.length) {
|
|
513
|
-
doc.push("", paramDoc.join("\n"));
|
|
514
|
-
}
|
|
515
|
-
if (info.examples?.length) {
|
|
516
|
-
let exp = `### 示例`;
|
|
517
|
-
for (const example of info.examples) {
|
|
518
|
-
exp += codeblock(example);
|
|
519
|
-
}
|
|
520
|
-
doc.push("", exp);
|
|
521
|
-
}
|
|
522
|
-
return doc;
|
|
523
|
-
}
|
|
524
|
-
function codeblock(value) {
|
|
525
|
-
const lang = value.startsWith("\0") ? "mirascript-doc" : "mirascript";
|
|
526
|
-
const includeFences = /`{3,}/.exec(value);
|
|
527
|
-
const CODEBLOCK_FENCE = includeFences ? "`".repeat(includeFences[0].length + 1) : "```";
|
|
528
|
-
return `
|
|
529
|
-
${CODEBLOCK_FENCE}${lang}
|
|
530
|
-
${value}
|
|
531
|
-
${CODEBLOCK_FENCE}
|
|
532
|
-
`;
|
|
533
|
-
}
|
|
534
|
-
function serializeIntegerImpl(num, base, prefix, sep) {
|
|
535
|
-
let str = Math.abs(num).toString(base);
|
|
536
|
-
if (base > 10) str = str.toUpperCase();
|
|
537
|
-
const sepSize = Math.abs(sep);
|
|
538
|
-
if (sep !== 0 && str.length > sepSize) {
|
|
539
|
-
const seg = [];
|
|
540
|
-
if (sep > 0) {
|
|
541
|
-
while (str.length > sepSize) {
|
|
542
|
-
seg.unshift(str.slice(-sepSize));
|
|
543
|
-
str = str.slice(0, -sepSize);
|
|
544
|
-
}
|
|
545
|
-
if (str.length > 0) {
|
|
546
|
-
seg.unshift(str);
|
|
547
|
-
}
|
|
548
|
-
} else {
|
|
549
|
-
while (str.length > sepSize) {
|
|
550
|
-
seg.push(str.slice(0, sepSize));
|
|
551
|
-
str = str.slice(sepSize);
|
|
552
|
-
}
|
|
553
|
-
if (str.length > 0) {
|
|
554
|
-
seg.push(str);
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
str = seg.join("_");
|
|
558
|
-
}
|
|
559
|
-
return (num < 0 ? "-" : "") + prefix + str;
|
|
560
|
-
}
|
|
561
|
-
function serializeInteger(num, base, sep = true) {
|
|
562
|
-
const prefix = base === 2 ? "0b" : base === 8 ? "0o" : "0x";
|
|
563
|
-
const sepSize = sep ? base === 2 ? 8 : base === 8 ? 6 : 4 : 0;
|
|
564
|
-
return serializeIntegerImpl(num, base, prefix, sepSize);
|
|
565
|
-
}
|
|
566
|
-
function serializeNumber(num) {
|
|
567
|
-
if (!Number.isFinite(num)) {
|
|
568
|
-
return serialize(num);
|
|
569
|
-
}
|
|
570
|
-
const str = String(num);
|
|
571
|
-
const dot = str.indexOf(".");
|
|
572
|
-
const exp = str.indexOf("e");
|
|
573
|
-
let intPart;
|
|
574
|
-
let fracPart;
|
|
575
|
-
let expPart;
|
|
576
|
-
if (dot >= 0) {
|
|
577
|
-
intPart = str.slice(0, dot);
|
|
578
|
-
if (exp >= 0) {
|
|
579
|
-
fracPart = str.slice(dot + 1, exp);
|
|
580
|
-
expPart = str.slice(exp);
|
|
581
|
-
} else {
|
|
582
|
-
fracPart = str.slice(dot + 1);
|
|
583
|
-
expPart = "";
|
|
584
|
-
}
|
|
585
|
-
} else {
|
|
586
|
-
if (exp >= 0) {
|
|
587
|
-
intPart = str.slice(0, exp);
|
|
588
|
-
fracPart = "";
|
|
589
|
-
expPart = str.slice(exp);
|
|
590
|
-
} else {
|
|
591
|
-
intPart = str;
|
|
592
|
-
fracPart = "";
|
|
593
|
-
expPart = "";
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
if (intPart.length > 5) intPart = serializeIntegerImpl(Number(intPart), 10, "", 3);
|
|
597
|
-
if (fracPart.length > 5) fracPart = serializeIntegerImpl(Number(fracPart), 10, "", -3);
|
|
598
|
-
return intPart + (fracPart ? "." + fracPart : "") + expPart;
|
|
599
|
-
}
|
|
600
|
-
function serializeForDisplayInner(value, maxWidth) {
|
|
601
|
-
if (maxWidth < 10) maxWidth = 10;
|
|
602
|
-
if (typeof value === "string") {
|
|
603
|
-
if (value.length < maxWidth) {
|
|
604
|
-
return serializeString(value);
|
|
605
|
-
}
|
|
606
|
-
return `${serializeString(value.slice(0, maxWidth))}..`;
|
|
607
|
-
}
|
|
608
|
-
if (typeof value === "number") {
|
|
609
|
-
return serializeNumber(value);
|
|
610
|
-
}
|
|
611
|
-
if (isVmPrimitive(value)) {
|
|
612
|
-
return serialize(value);
|
|
613
|
-
}
|
|
614
|
-
if (isVmArray(value)) {
|
|
615
|
-
const len = value.length;
|
|
616
|
-
if (!len) return "[]";
|
|
617
|
-
return `[../* x${len} */]`;
|
|
618
|
-
}
|
|
619
|
-
if (isVmRecord(value)) {
|
|
620
|
-
const len = Object.keys(value).length;
|
|
621
|
-
if (!len) return "()";
|
|
622
|
-
return `(../* x${len} */)`;
|
|
623
|
-
}
|
|
624
|
-
if (isVmExtern(value)) {
|
|
625
|
-
return `/* <extern ${value.tag}> */`;
|
|
626
|
-
}
|
|
627
|
-
return `/* ${operations.$ToString(value)} */`;
|
|
628
|
-
}
|
|
629
|
-
function serializeField(obj, key, maxWidth) {
|
|
630
|
-
const value = getField(obj, key);
|
|
631
|
-
if (value === void 0) {
|
|
632
|
-
return UNKNOWN_REPR;
|
|
633
|
-
}
|
|
634
|
-
return serializeForDisplayInner(value, maxWidth);
|
|
635
|
-
}
|
|
636
|
-
function serializeForDisplay(value, maxEntries = 100, maxWidth = 40) {
|
|
637
|
-
if (isVmPrimitive(value) || isVmFunction(value)) {
|
|
638
|
-
return serializeForDisplayInner(value, maxWidth);
|
|
639
|
-
}
|
|
640
|
-
let begin, end;
|
|
641
|
-
const entries = [];
|
|
642
|
-
let resultLength = 0;
|
|
643
|
-
if (isVmArray(value)) {
|
|
644
|
-
begin = "[";
|
|
645
|
-
end = "]";
|
|
646
|
-
const len = value.length;
|
|
647
|
-
if (len === 0) return "[]";
|
|
648
|
-
for (let i = 0; i < len; i++) {
|
|
649
|
-
if (entries.length > maxEntries) {
|
|
650
|
-
entries.push(`../* x${value.length - entries.length} */`);
|
|
651
|
-
break;
|
|
652
|
-
}
|
|
653
|
-
const entry = serializeField(value, i, maxWidth - 2);
|
|
654
|
-
entries.push(entry);
|
|
655
|
-
resultLength += entry.length;
|
|
656
|
-
}
|
|
657
|
-
} else if (isVmRecord(value)) {
|
|
658
|
-
const keys = Object.keys(value);
|
|
659
|
-
if (keys.length === 0) return "()";
|
|
660
|
-
begin = "(";
|
|
661
|
-
end = ")";
|
|
662
|
-
for (const key of keys) {
|
|
663
|
-
if (entries.length > maxEntries) {
|
|
664
|
-
entries.push(`../* x${keys.length - entries.length} */`);
|
|
665
|
-
break;
|
|
666
|
-
}
|
|
667
|
-
const sk = serializeRecordKey(key);
|
|
668
|
-
const sv = serializeField(value, key, maxWidth - sk.length - 4);
|
|
669
|
-
const entry = `${sk}: ${sv}`;
|
|
670
|
-
entries.push(entry);
|
|
671
|
-
resultLength += entry.length;
|
|
672
|
-
}
|
|
673
|
-
} else {
|
|
674
|
-
const hint = serializeForDisplayInner(value, 100);
|
|
675
|
-
const isArray = value.isArrayLike();
|
|
676
|
-
begin = `${hint} ${isArray ? "[" : "("}`;
|
|
677
|
-
end = isArray ? "]" : ")";
|
|
678
|
-
const keys = value.keys();
|
|
679
|
-
if (keys.length === 0 && !isArray) {
|
|
680
|
-
if (typeof value.value == "object") {
|
|
681
|
-
for (const key of Object.getOwnPropertyNames(value.value)) {
|
|
682
|
-
if (value.has(key)) keys.push(key);
|
|
683
|
-
}
|
|
684
|
-
} else {
|
|
685
|
-
begin = hint;
|
|
686
|
-
end = "";
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
for (const [index, key] of keys.entries()) {
|
|
690
|
-
if (entries.length > maxEntries) {
|
|
691
|
-
entries.push(`../* x${keys.length - entries.length} */`);
|
|
692
|
-
break;
|
|
693
|
-
}
|
|
694
|
-
let entry;
|
|
695
|
-
if (isArray && String(index) === key) {
|
|
696
|
-
entry = serializeForDisplayInner(value.get(key) ?? null, maxWidth - 2);
|
|
697
|
-
} else {
|
|
698
|
-
const sk = serializeRecordKey(key);
|
|
699
|
-
entry = `${sk}: ${serializeForDisplayInner(value.get(key) ?? null, maxWidth - sk.length - 4)}`;
|
|
700
|
-
}
|
|
701
|
-
entries.push(entry);
|
|
702
|
-
resultLength += entry.length;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
if (resultLength >= maxWidth) {
|
|
706
|
-
return `${begin}
|
|
707
|
-
${entries.join(",\n ")}
|
|
708
|
-
${end}`;
|
|
709
|
-
}
|
|
710
|
-
return `${begin}${entries.join(", ")}${end}`;
|
|
711
|
-
}
|
|
712
|
-
function docComment(doc) {
|
|
713
|
-
const lines = doc.flatMap((sec) => sec.split("\n").map((s) => s.trimEnd()));
|
|
714
|
-
const firstLine = lines.findIndex((line) => line.length > 0);
|
|
715
|
-
const lastLine = lines.findLastIndex((line) => line.length > 0);
|
|
716
|
-
if (firstLine < 0 || lastLine < 0) return [];
|
|
717
|
-
return [`/**`, ...lines.slice(firstLine, lastLine + 1).map((line) => ` * ${line}`), ` */`];
|
|
718
|
-
}
|
|
719
|
-
function valueDoc(name, value, type, parent) {
|
|
720
|
-
const info = getVmFunctionInfo(value);
|
|
721
|
-
const describe = parent?.describe?.(name);
|
|
722
|
-
if (info) {
|
|
723
|
-
const doc = globalFnDoc(info);
|
|
724
|
-
if (describe && doc[0] !== describe) {
|
|
725
|
-
doc.unshift(describe);
|
|
726
|
-
}
|
|
727
|
-
return {
|
|
728
|
-
script: fnSignature(name, info).toString() + (type === "declare" ? ";" : ""),
|
|
729
|
-
doc
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
let prefix;
|
|
733
|
-
let suffix = "";
|
|
734
|
-
if (type === "hint") {
|
|
735
|
-
prefix = `${serializeRecordKey(name)} = `;
|
|
736
|
-
} else if (type === "declare") {
|
|
737
|
-
if (name.startsWith("@")) {
|
|
738
|
-
prefix = `const ${name} = `;
|
|
739
|
-
} else {
|
|
740
|
-
prefix = `let ${name} = `;
|
|
741
|
-
}
|
|
742
|
-
suffix = ";";
|
|
743
|
-
} else if (/^\d/.test(name)) {
|
|
744
|
-
prefix = `[${name}]: `;
|
|
745
|
-
} else {
|
|
746
|
-
prefix = `${name}: `;
|
|
747
|
-
}
|
|
748
|
-
if (isVmModule(value)) {
|
|
749
|
-
let script;
|
|
750
|
-
if (type === "declare") {
|
|
751
|
-
const exports = value.keys();
|
|
752
|
-
if (!exports.length) {
|
|
753
|
-
script = `mod ${value.name} { }`;
|
|
754
|
-
} else {
|
|
755
|
-
script = `mod ${value.name} {
|
|
756
|
-
`;
|
|
757
|
-
for (const k of exports) {
|
|
758
|
-
const v = value.get(k);
|
|
759
|
-
const vDoc = valueDoc(k, v, "declare", value);
|
|
760
|
-
const code = [...docComment(vDoc.doc), "pub " + vDoc.script];
|
|
761
|
-
const lines = code.flatMap((line) => line.split("\n"));
|
|
762
|
-
for (const line of lines) {
|
|
763
|
-
script += line ? " " + line + "\n" : "\n";
|
|
764
|
-
}
|
|
765
|
-
script += "\n";
|
|
766
|
-
}
|
|
767
|
-
script = script.trimEnd() + "\n}";
|
|
768
|
-
}
|
|
769
|
-
} else {
|
|
770
|
-
script = `mod ${value.name}`;
|
|
771
|
-
if (value.name !== name) {
|
|
772
|
-
script = `${prefix}${script}`;
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
return { script, doc: [`模块 \`${value.name}\``] };
|
|
776
|
-
}
|
|
777
|
-
let valueStr = UNKNOWN_REPR;
|
|
778
|
-
if (value !== void 0) {
|
|
779
|
-
try {
|
|
780
|
-
valueStr = serializeForDisplay(value, type === "declare" ? 1e3 : 100, type === "declare" ? 80 : 40);
|
|
781
|
-
} catch (ex) {
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
return {
|
|
785
|
-
script: `${prefix}${valueStr}${suffix}`,
|
|
786
|
-
doc: describe ? [describe] : []
|
|
787
|
-
};
|
|
788
|
-
}
|
|
789
|
-
function getDeep(globals, name, path) {
|
|
790
|
-
if (!globals.has(name)) return [null, void 0];
|
|
791
|
-
let current = globals.get(name);
|
|
792
|
-
if (!path.length) {
|
|
793
|
-
return [globals, current];
|
|
794
|
-
}
|
|
795
|
-
let parent = null;
|
|
796
|
-
for (const key of path) {
|
|
797
|
-
if (current == null) return [null, void 0];
|
|
798
|
-
if (!operations.$Has(current, key)) return [null, void 0];
|
|
799
|
-
parent = current;
|
|
800
|
-
current = operations.$Get(parent, key);
|
|
801
|
-
}
|
|
802
|
-
return [isVmWrapper(parent) ? parent : null, current];
|
|
803
|
-
}
|
|
804
|
-
function getField(obj, key) {
|
|
805
|
-
if (obj == null) return void 0;
|
|
806
|
-
try {
|
|
807
|
-
if (!operations.$Has(obj, key)) return void 0;
|
|
808
|
-
} catch {
|
|
809
|
-
return void 0;
|
|
810
|
-
}
|
|
811
|
-
try {
|
|
812
|
-
return operations.$Get(obj, key);
|
|
813
|
-
} catch {
|
|
814
|
-
return void 0;
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
function listFields(obj, includeNonEnumerable) {
|
|
818
|
-
if (obj == null || typeof obj != "object") return [];
|
|
819
|
-
if (isVmWrapper(obj)) {
|
|
820
|
-
try {
|
|
821
|
-
return obj.keys(includeNonEnumerable);
|
|
822
|
-
} catch {
|
|
823
|
-
return [];
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
return lib.keys(obj);
|
|
827
|
-
}
|
|
828
|
-
function isDeprecatedGlobal(globals, name) {
|
|
829
|
-
if (!globals.has(name)) {
|
|
830
|
-
return void 0;
|
|
831
|
-
}
|
|
832
|
-
const value = globals.get(name);
|
|
833
|
-
const funcInfo = getVmFunctionInfo(value);
|
|
834
|
-
if (funcInfo) {
|
|
835
|
-
return funcInfo.deprecated;
|
|
836
|
-
}
|
|
837
|
-
const info = lib[name];
|
|
838
|
-
if (!info?.deprecated) return void 0;
|
|
839
|
-
if (info.value !== value) return void 0;
|
|
840
|
-
const { use } = info.deprecated;
|
|
841
|
-
if (use) {
|
|
842
|
-
if (!globals.has(use)) return void 0;
|
|
843
|
-
const replacement = globals.get(use);
|
|
844
|
-
if (replacement !== info.value) return void 0;
|
|
845
|
-
}
|
|
846
|
-
return info.deprecated;
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
// src/lsp/diagnostics.ts
|
|
850
|
-
var formatMessage = (model, code, $0) => {
|
|
851
|
-
return formatDiagnosticMessage(code, () => {
|
|
852
|
-
if (!$0) return void 0;
|
|
853
|
-
if (typeof $0 == "string") return $0;
|
|
854
|
-
return model.getValueInRange($0);
|
|
855
|
-
});
|
|
856
|
-
};
|
|
857
|
-
var makeMarkerData = (model, range, code, message, severity, tags) => {
|
|
858
|
-
const { startLineNumber, startColumn, endLineNumber, endColumn } = range;
|
|
859
|
-
if (!message) {
|
|
860
|
-
if (typeof code != "number") {
|
|
861
|
-
message = "";
|
|
862
|
-
} else {
|
|
863
|
-
message = formatMessage(model, code, range);
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
const marker = {
|
|
867
|
-
startLineNumber,
|
|
868
|
-
startColumn,
|
|
869
|
-
endLineNumber,
|
|
870
|
-
endColumn,
|
|
871
|
-
message,
|
|
872
|
-
severity,
|
|
873
|
-
modelVersionId: model.getVersionId(),
|
|
874
|
-
source: "MiraScript",
|
|
875
|
-
tags
|
|
876
|
-
};
|
|
877
|
-
const codeName = typeof code == "number" ? DiagnosticCode3[code] : void 0;
|
|
878
|
-
if (codeName) {
|
|
879
|
-
marker.code = {
|
|
880
|
-
value: codeName,
|
|
881
|
-
target: Uri.parse(`https://mira.cloudpss.net/code/${codeName}`)
|
|
882
|
-
};
|
|
883
|
-
} else {
|
|
884
|
-
marker.code = `${code}`;
|
|
885
|
-
}
|
|
886
|
-
return marker;
|
|
887
|
-
};
|
|
888
|
-
function getDiagnosticCode(marker) {
|
|
889
|
-
if (!marker) return void 0;
|
|
890
|
-
const { code } = marker;
|
|
891
|
-
if (typeof code == "object") {
|
|
892
|
-
const codeName = code.value;
|
|
893
|
-
if (codeName in DiagnosticCode3) {
|
|
894
|
-
return DiagnosticCode3[codeName];
|
|
895
|
-
}
|
|
896
|
-
} else if (typeof code == "string") {
|
|
897
|
-
if (code in DiagnosticCode3) {
|
|
898
|
-
return DiagnosticCode3[code];
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
return void 0;
|
|
902
|
-
}
|
|
903
|
-
var makeMarker = (model, diagnostic, severity) => {
|
|
904
|
-
const { range, code } = diagnostic;
|
|
905
|
-
let unnecessary = false;
|
|
906
|
-
const deprecated = false;
|
|
907
|
-
if (code === DiagnosticCode3.UnusedLocalVariable || code === DiagnosticCode3.UnusedLocalFunction) {
|
|
908
|
-
unnecessary = true;
|
|
909
|
-
severity = MarkerSeverity.Hint;
|
|
910
|
-
}
|
|
911
|
-
const marker = makeMarkerData(model, range, code, void 0, severity);
|
|
912
|
-
if (unnecessary) {
|
|
913
|
-
marker.tags ??= [];
|
|
914
|
-
marker.tags.push(MarkerTag.Unnecessary);
|
|
915
|
-
}
|
|
916
|
-
if (deprecated) {
|
|
917
|
-
marker.tags ??= [];
|
|
918
|
-
marker.tags.push(MarkerTag.Deprecated);
|
|
919
|
-
}
|
|
920
|
-
if (diagnostic.references.length) {
|
|
921
|
-
marker.relatedInformation = [];
|
|
922
|
-
for (const ref of diagnostic.references) {
|
|
923
|
-
const { range: range2, code: code2 } = ref;
|
|
924
|
-
const { startLineNumber, startColumn, endLineNumber, endColumn } = range2;
|
|
925
|
-
const message = getDiagnosticMessage(code2) ?? "...here";
|
|
926
|
-
marker.relatedInformation.push({
|
|
927
|
-
message,
|
|
928
|
-
resource: model.uri,
|
|
929
|
-
startLineNumber,
|
|
930
|
-
startColumn,
|
|
931
|
-
endLineNumber,
|
|
932
|
-
endColumn
|
|
933
|
-
});
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
return marker;
|
|
937
|
-
};
|
|
938
|
-
async function makeModelMarkers(model, result) {
|
|
939
|
-
const { version } = result;
|
|
940
|
-
if (version !== model.getVersionId()) return null;
|
|
941
|
-
const errors = result.errors.map((d) => makeMarker(model, d, MarkerSeverity.Error));
|
|
942
|
-
const warnings = result.warnings.map((d) => makeMarker(model, d, MarkerSeverity.Warning));
|
|
943
|
-
const infos = result.infos.map((d) => makeMarker(model, d, MarkerSeverity.Info));
|
|
944
|
-
const hints = result.hints.map((d) => makeMarker(model, d, MarkerSeverity.Hint));
|
|
945
|
-
const markers = [...errors, ...warnings, ...infos, ...hints];
|
|
946
|
-
const { globals } = result.groupedTags(model);
|
|
947
|
-
if (globals.length) {
|
|
948
|
-
const context = await Provider.getContext(model);
|
|
949
|
-
for (const g of globals) {
|
|
950
|
-
const { name } = g;
|
|
951
|
-
if (!context.has(name)) {
|
|
952
|
-
const message = formatMessage(model, DiagnosticCode3.GlobalVariableNotDeclared, name);
|
|
953
|
-
for (const ref of g.references) {
|
|
954
|
-
markers.push(
|
|
955
|
-
makeMarkerData(
|
|
956
|
-
model,
|
|
957
|
-
ref.range,
|
|
958
|
-
DiagnosticCode3.GlobalVariableNotDeclared,
|
|
959
|
-
message,
|
|
960
|
-
MarkerSeverity.Warning
|
|
961
|
-
)
|
|
962
|
-
);
|
|
963
|
-
}
|
|
964
|
-
continue;
|
|
965
|
-
}
|
|
966
|
-
const deprecated = isDeprecatedGlobal(context, name);
|
|
967
|
-
if (deprecated) {
|
|
968
|
-
const replacement = deprecated.use;
|
|
969
|
-
if (replacement) {
|
|
970
|
-
const message = formatMessage(model, deprecated.message, replacement);
|
|
971
|
-
for (const ref of g.references) {
|
|
972
|
-
markers.push(
|
|
973
|
-
makeMarkerData(model, ref.range, deprecated.message, message, MarkerSeverity.Hint, [
|
|
974
|
-
MarkerTag.Deprecated
|
|
975
|
-
])
|
|
976
|
-
);
|
|
977
|
-
}
|
|
978
|
-
} else {
|
|
979
|
-
for (const ref of g.references) {
|
|
980
|
-
markers.push(
|
|
981
|
-
makeMarkerData(model, ref.range, deprecated.message, void 0, MarkerSeverity.Hint, [
|
|
982
|
-
MarkerTag.Deprecated
|
|
983
|
-
])
|
|
984
|
-
);
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
return markers;
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
// src/lsp/worker-helper.ts
|
|
994
|
-
var cache = /* @__PURE__ */ new Map();
|
|
995
|
-
var worker = void 0;
|
|
996
|
-
var CACHE_MAX_AGE = 3e4;
|
|
997
|
-
setInterval(() => {
|
|
998
|
-
const now = Date.now();
|
|
999
|
-
for (const [key, { lastAccess }] of cache) {
|
|
1000
|
-
if (now - lastAccess > CACHE_MAX_AGE) {
|
|
1001
|
-
cache.delete(key);
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
1004
|
-
}, CACHE_MAX_AGE);
|
|
1005
|
-
async function compileWorker(req) {
|
|
1006
|
-
if (!worker) {
|
|
1007
|
-
const w = new Worker(new URL("#lsp/worker", import.meta.url), {
|
|
1008
|
-
type: "module",
|
|
1009
|
-
name: "@mirascript/lsp-server"
|
|
1010
|
-
});
|
|
1011
|
-
worker = new Promise((resolve, reject) => {
|
|
1012
|
-
const onError = (e) => {
|
|
1013
|
-
cleanUp();
|
|
1014
|
-
reject(new Error(`Worker failed to start: ${e.message}`));
|
|
1015
|
-
};
|
|
1016
|
-
const onMessage = (e) => {
|
|
1017
|
-
if (e.data === "mirascript lsp ready") {
|
|
1018
|
-
cleanUp();
|
|
1019
|
-
resolve(w);
|
|
1020
|
-
} else if (e.data instanceof Error) {
|
|
1021
|
-
cleanUp();
|
|
1022
|
-
reject(e.data);
|
|
1023
|
-
}
|
|
1024
|
-
};
|
|
1025
|
-
w.addEventListener("error", onError);
|
|
1026
|
-
w.addEventListener("message", onMessage);
|
|
1027
|
-
const cleanUp = () => {
|
|
1028
|
-
w.removeEventListener("error", onError);
|
|
1029
|
-
w.removeEventListener("message", onMessage);
|
|
1030
|
-
};
|
|
1031
|
-
setTimeout(() => {
|
|
1032
|
-
onError(new ErrorEvent("error", { message: "Worker did not respond in time" }));
|
|
1033
|
-
}, 3e4);
|
|
1034
|
-
});
|
|
1035
|
-
}
|
|
1036
|
-
try {
|
|
1037
|
-
await worker;
|
|
1038
|
-
} catch (ex) {
|
|
1039
|
-
console.error("Failed to initialize worker, use sync compile:", ex);
|
|
1040
|
-
USE_WORKER = false;
|
|
1041
|
-
return compileSync(req);
|
|
1042
|
-
}
|
|
1043
|
-
const instance = await worker;
|
|
1044
|
-
instance.postMessage(req);
|
|
1045
|
-
const [key, version, source] = req;
|
|
1046
|
-
const [_key, _version, result] = await new Promise((resolve, reject) => {
|
|
1047
|
-
const onMessage = (e) => {
|
|
1048
|
-
if (e.data[0] === key && e.data[1] === version) {
|
|
1049
|
-
instance.removeEventListener("message", onMessage);
|
|
1050
|
-
if (e.data[2] instanceof Error) {
|
|
1051
|
-
reject(e.data[2]);
|
|
1052
|
-
} else {
|
|
1053
|
-
resolve(e.data);
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
};
|
|
1057
|
-
instance.addEventListener("message", onMessage);
|
|
1058
|
-
});
|
|
1059
|
-
return new CompileResult(key, version, source, result);
|
|
1060
|
-
}
|
|
1061
|
-
var compileImpl;
|
|
1062
|
-
async function compileSync(req) {
|
|
1063
|
-
const [key, version, script, mode] = req;
|
|
1064
|
-
if (compileImpl == null) {
|
|
1065
|
-
const mod = await import("./worker.js");
|
|
1066
|
-
compileImpl = mod.compile;
|
|
1067
|
-
}
|
|
1068
|
-
const result = compileImpl(script, mode);
|
|
1069
|
-
return new CompileResult(key, version, script, result);
|
|
1070
|
-
}
|
|
1071
|
-
var USE_WORKER = typeof Worker === "function";
|
|
1072
|
-
async function compile(model) {
|
|
1073
|
-
const version = model.getVersionId();
|
|
1074
|
-
const mode = model.getLanguageId() === "mirascript-template" ? "Template" : "Script";
|
|
1075
|
-
const cacheKey = model.id;
|
|
1076
|
-
const cached = cache.get(cacheKey);
|
|
1077
|
-
if (cached?.version === version && cached.mode === mode) {
|
|
1078
|
-
cached.lastAccess = Date.now();
|
|
1079
|
-
return cached.result;
|
|
1080
|
-
}
|
|
1081
|
-
const value = model.getValue();
|
|
1082
|
-
const req = [cacheKey, version, value, mode];
|
|
1083
|
-
const res = USE_WORKER ? compileWorker(req) : compileSync(req);
|
|
1084
|
-
void res.then(async (result) => {
|
|
1085
|
-
if (model.isDisposed()) return;
|
|
1086
|
-
const setModelMarkers = editor?.setModelMarkers;
|
|
1087
|
-
if (typeof setModelMarkers != "function") return;
|
|
1088
|
-
const markers = await makeModelMarkers(model, result);
|
|
1089
|
-
if (!markers) return;
|
|
1090
|
-
setModelMarkers(model, "mirascript", markers);
|
|
1091
|
-
});
|
|
1092
|
-
const item = {
|
|
1093
|
-
version,
|
|
1094
|
-
lastAccess: Date.now(),
|
|
1095
|
-
mode,
|
|
1096
|
-
result: res
|
|
1097
|
-
};
|
|
1098
|
-
cache.set(cacheKey, item);
|
|
1099
|
-
res.catch(() => {
|
|
1100
|
-
const current = cache.get(cacheKey);
|
|
1101
|
-
if (current === item) {
|
|
1102
|
-
cache.delete(cacheKey);
|
|
1103
|
-
}
|
|
1104
|
-
});
|
|
1105
|
-
return res;
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
// src/lsp/providers/base.ts
|
|
1109
|
-
var contextProvider;
|
|
1110
|
-
var DEFAULT_MONACO_CONTEXT = Object.freeze({
|
|
1111
|
-
get(key) {
|
|
1112
|
-
return DefaultVmContext.get(key);
|
|
1113
|
-
},
|
|
1114
|
-
getOrUndefined(key) {
|
|
1115
|
-
return DefaultVmContext.has(key) ? DefaultVmContext.get(key) : void 0;
|
|
1116
|
-
},
|
|
1117
|
-
has(key) {
|
|
1118
|
-
return DefaultVmContext.has(key);
|
|
1119
|
-
},
|
|
1120
|
-
keys() {
|
|
1121
|
-
return DefaultVmContext.keys();
|
|
1122
|
-
},
|
|
1123
|
-
describe(key) {
|
|
1124
|
-
return void 0;
|
|
1125
|
-
}
|
|
1126
|
-
});
|
|
1127
|
-
async function getContextImpl(model, clearCache) {
|
|
1128
|
-
try {
|
|
1129
|
-
const context = await contextProvider?.(model);
|
|
1130
|
-
if (!context) {
|
|
1131
|
-
return DEFAULT_MONACO_CONTEXT;
|
|
1132
|
-
}
|
|
1133
|
-
const monacoContext = Object.freeze({
|
|
1134
|
-
get(key) {
|
|
1135
|
-
try {
|
|
1136
|
-
return context.get(key);
|
|
1137
|
-
} catch {
|
|
1138
|
-
clearCache();
|
|
1139
|
-
return DEFAULT_MONACO_CONTEXT.get(key);
|
|
1140
|
-
}
|
|
1141
|
-
},
|
|
1142
|
-
getOrUndefined(key) {
|
|
1143
|
-
try {
|
|
1144
|
-
return context.has(key) ? context.get(key) : void 0;
|
|
1145
|
-
} catch {
|
|
1146
|
-
clearCache();
|
|
1147
|
-
return DEFAULT_MONACO_CONTEXT.getOrUndefined(key);
|
|
1148
|
-
}
|
|
1149
|
-
},
|
|
1150
|
-
has(key) {
|
|
1151
|
-
try {
|
|
1152
|
-
return context.has(key);
|
|
1153
|
-
} catch {
|
|
1154
|
-
clearCache();
|
|
1155
|
-
return DEFAULT_MONACO_CONTEXT.has(key);
|
|
1156
|
-
}
|
|
1157
|
-
},
|
|
1158
|
-
keys() {
|
|
1159
|
-
try {
|
|
1160
|
-
return context.keys();
|
|
1161
|
-
} catch {
|
|
1162
|
-
clearCache();
|
|
1163
|
-
return DEFAULT_MONACO_CONTEXT.keys();
|
|
1164
|
-
}
|
|
1165
|
-
},
|
|
1166
|
-
describe(key) {
|
|
1167
|
-
try {
|
|
1168
|
-
return context.describe?.(key) || void 0;
|
|
1169
|
-
} catch {
|
|
1170
|
-
clearCache();
|
|
1171
|
-
return DEFAULT_MONACO_CONTEXT.describe(key);
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
});
|
|
1175
|
-
return monacoContext;
|
|
1176
|
-
} catch (ex) {
|
|
1177
|
-
console.error("Error getting MiraScript Monaco context:", ex);
|
|
1178
|
-
return DEFAULT_MONACO_CONTEXT;
|
|
1179
|
-
}
|
|
1180
|
-
}
|
|
1181
|
-
var cachedContext = null;
|
|
1182
|
-
var Provider = class _Provider {
|
|
1183
|
-
constructor(enabled = () => true) {
|
|
1184
|
-
this.enabled = enabled;
|
|
1185
|
-
this.displayName = "MiraScript LSP";
|
|
1186
|
-
this._debugDisplayName = "MiraScript LSP";
|
|
1187
|
-
this._onDidChange = null;
|
|
1188
|
-
}
|
|
1189
|
-
/** 是否启用 */
|
|
1190
|
-
get isEnabled() {
|
|
1191
|
-
return this.enabled();
|
|
1192
|
-
}
|
|
1193
|
-
/** 设置全局变量提供者 */
|
|
1194
|
-
static setContextProvider(provider) {
|
|
1195
|
-
contextProvider = provider;
|
|
1196
|
-
cachedContext = null;
|
|
1197
|
-
}
|
|
1198
|
-
/** 获取编译结果 */
|
|
1199
|
-
static async getCompileResult(model) {
|
|
1200
|
-
if (model.uri.scheme === "mirascript") {
|
|
1201
|
-
return void 0;
|
|
1202
|
-
}
|
|
1203
|
-
return await compile(model);
|
|
1204
|
-
}
|
|
1205
|
-
/** 获取编译结果 */
|
|
1206
|
-
async getCompileResult(model) {
|
|
1207
|
-
if (!this.isEnabled) return void 0;
|
|
1208
|
-
return _Provider.getCompileResult(model);
|
|
1209
|
-
}
|
|
1210
|
-
/** 获取执行上下文(全局变量) */
|
|
1211
|
-
static async getContext(model) {
|
|
1212
|
-
if (cachedContext?.[0] === model) {
|
|
1213
|
-
return cachedContext[1];
|
|
1214
|
-
}
|
|
1215
|
-
const clearCache = () => {
|
|
1216
|
-
if (cachedContext === cache2) {
|
|
1217
|
-
cachedContext = null;
|
|
1218
|
-
}
|
|
1219
|
-
};
|
|
1220
|
-
const context = getContextImpl(model, clearCache);
|
|
1221
|
-
const cache2 = [model, context];
|
|
1222
|
-
cachedContext = cache2;
|
|
1223
|
-
setTimeout(clearCache, 100);
|
|
1224
|
-
return context;
|
|
1225
|
-
}
|
|
1226
|
-
/** 获取执行上下文(全局变量) */
|
|
1227
|
-
async getContext(model) {
|
|
1228
|
-
return _Provider.getContext(model);
|
|
1229
|
-
}
|
|
1230
|
-
/** 获取当前位置的值 */
|
|
1231
|
-
async getValueAt(model, position) {
|
|
1232
|
-
const compiled = await this.getCompileResult(model);
|
|
1233
|
-
if (!compiled) return void 0;
|
|
1234
|
-
const d = compiled.variableAccessAt(model, position);
|
|
1235
|
-
if (d) return { range: d.range, variable: d };
|
|
1236
|
-
const word = wordAt(model, position);
|
|
1237
|
-
if (word) {
|
|
1238
|
-
const a = compiled.fieldAccessAt(model, {
|
|
1239
|
-
lineNumber: position.lineNumber,
|
|
1240
|
-
column: word.range.endColumn
|
|
1241
|
-
});
|
|
1242
|
-
if (a) return { range: word.range, fields: a };
|
|
1243
|
-
}
|
|
1244
|
-
return void 0;
|
|
1245
|
-
}
|
|
1246
|
-
/** @inheritdoc */
|
|
1247
|
-
get onDidChange() {
|
|
1248
|
-
this._onDidChange ??= new Emitter();
|
|
1249
|
-
return this._onDidChange.event;
|
|
1250
|
-
}
|
|
1251
|
-
/** 触发 onDidChange */
|
|
1252
|
-
emitDidChange() {
|
|
1253
|
-
this._onDidChange?.fire(this);
|
|
1254
|
-
}
|
|
1255
|
-
};
|
|
1256
|
-
|
|
1257
|
-
// src/lsp/providers/code-action-provider.ts
|
|
1258
|
-
import { DiagnosticCode as DiagnosticCode4 } from "@mirascript/constants";
|
|
1259
|
-
function createCodeAction(result, context, model, marker) {
|
|
1260
|
-
const code = getDiagnosticCode(marker);
|
|
1261
|
-
if (!code) return void 0;
|
|
1262
|
-
const range = Range.lift(marker);
|
|
1263
|
-
const action = {
|
|
1264
|
-
title: "",
|
|
1265
|
-
diagnostics: [marker]
|
|
1266
|
-
};
|
|
1267
|
-
const edits = (...textEdits) => {
|
|
1268
|
-
const edits2 = [];
|
|
1269
|
-
for (const textEdit of textEdits) {
|
|
1270
|
-
if (textEdit == null) continue;
|
|
1271
|
-
edits2.push({
|
|
1272
|
-
resource: model.uri,
|
|
1273
|
-
versionId: result.version,
|
|
1274
|
-
textEdit
|
|
1275
|
-
});
|
|
1276
|
-
}
|
|
1277
|
-
return { edits: edits2 };
|
|
1278
|
-
};
|
|
1279
|
-
if (code === DiagnosticCode4.PreferUppercaseConstant) {
|
|
1280
|
-
const current = model.getValueInRange(range);
|
|
1281
|
-
const uppercase = current.toUpperCase();
|
|
1282
|
-
if (current === uppercase || !Object.is(context.getOrUndefined(current), context.getOrUndefined(uppercase))) {
|
|
1283
|
-
return void 0;
|
|
1284
|
-
}
|
|
1285
|
-
action.title = "转换为大写常量";
|
|
1286
|
-
action.kind = "quickfix";
|
|
1287
|
-
action.edit = edits({
|
|
1288
|
-
range,
|
|
1289
|
-
text: uppercase
|
|
1290
|
-
});
|
|
1291
|
-
} else if (code === DiagnosticCode4.PreferParenthesesForRecordLiteral) {
|
|
1292
|
-
const current = model.getValueInRange(range);
|
|
1293
|
-
let fixed = current;
|
|
1294
|
-
if (current.startsWith("{ ")) {
|
|
1295
|
-
fixed = `(${fixed.slice(2)}`;
|
|
1296
|
-
} else if (current.startsWith("{")) {
|
|
1297
|
-
fixed = `(${fixed.slice(1)}`;
|
|
1298
|
-
}
|
|
1299
|
-
if (current.endsWith(" }")) {
|
|
1300
|
-
fixed = `${fixed.slice(0, -2)})`;
|
|
1301
|
-
} else if (current.endsWith("}")) {
|
|
1302
|
-
fixed = `${fixed.slice(0, -1)})`;
|
|
1303
|
-
}
|
|
1304
|
-
if (fixed === current) {
|
|
1305
|
-
return void 0;
|
|
1306
|
-
}
|
|
1307
|
-
const prefix = model.getValueInRange({
|
|
1308
|
-
startLineNumber: range.startLineNumber,
|
|
1309
|
-
startColumn: range.startColumn - 1,
|
|
1310
|
-
endLineNumber: range.startLineNumber,
|
|
1311
|
-
endColumn: range.startColumn
|
|
1312
|
-
});
|
|
1313
|
-
if (prefix === "$") {
|
|
1314
|
-
fixed = `(${fixed})`;
|
|
1315
|
-
}
|
|
1316
|
-
action.title = `转换为使用圆括号的记录字面量`;
|
|
1317
|
-
action.kind = "quickfix";
|
|
1318
|
-
action.edit = edits({
|
|
1319
|
-
range,
|
|
1320
|
-
text: fixed
|
|
1321
|
-
});
|
|
1322
|
-
} else if (code === DiagnosticCode4.PreferLogicalOperatorAnd || code === DiagnosticCode4.PreferLogicalOperatorOr || code === DiagnosticCode4.PreferLogicalOperatorNot) {
|
|
1323
|
-
let range0 = range;
|
|
1324
|
-
const current = model.getValueInRange(range);
|
|
1325
|
-
let fixed;
|
|
1326
|
-
if (current === "and") {
|
|
1327
|
-
fixed = "&&";
|
|
1328
|
-
} else if (current === "or") {
|
|
1329
|
-
fixed = "||";
|
|
1330
|
-
} else if (current === "not") {
|
|
1331
|
-
const range1 = range.setEndPosition(range.endLineNumber, range.endColumn + 1);
|
|
1332
|
-
const current1 = model.getValueInRange(range1);
|
|
1333
|
-
if (current1.trim() === "not") {
|
|
1334
|
-
range0 = range1;
|
|
1335
|
-
}
|
|
1336
|
-
fixed = "!";
|
|
1337
|
-
}
|
|
1338
|
-
if (!fixed) {
|
|
1339
|
-
return void 0;
|
|
1340
|
-
}
|
|
1341
|
-
action.title = `转换为 '${fixed}' 运算符`;
|
|
1342
|
-
action.kind = "quickfix";
|
|
1343
|
-
action.edit = edits({
|
|
1344
|
-
range: range0,
|
|
1345
|
-
text: fixed
|
|
1346
|
-
});
|
|
1347
|
-
} else if (code === DiagnosticCode4.UnnecessaryParentheses) {
|
|
1348
|
-
const current = model.getValueInRange(range);
|
|
1349
|
-
let fixed = current;
|
|
1350
|
-
if (current.startsWith("(")) {
|
|
1351
|
-
fixed = fixed.slice(1);
|
|
1352
|
-
}
|
|
1353
|
-
if (current.endsWith(")")) {
|
|
1354
|
-
fixed = fixed.slice(0, -1);
|
|
1355
|
-
}
|
|
1356
|
-
if (fixed === current) {
|
|
1357
|
-
return void 0;
|
|
1358
|
-
}
|
|
1359
|
-
action.title = "移除不必要的括号";
|
|
1360
|
-
action.kind = "quickfix";
|
|
1361
|
-
action.edit = edits({
|
|
1362
|
-
range,
|
|
1363
|
-
text: fixed
|
|
1364
|
-
});
|
|
1365
|
-
} else if (code === DiagnosticCode4.PreferIfExpression) {
|
|
1366
|
-
const tag = result.tags.find(
|
|
1367
|
-
(tag2) => tag2.code === DiagnosticCode4.IfExpression && Range.equalsRange(tag2.range, range)
|
|
1368
|
-
);
|
|
1369
|
-
if (!tag) return void 0;
|
|
1370
|
-
const questionMark = tag.references.find((ref) => ref.code === DiagnosticCode4.KeywordIf);
|
|
1371
|
-
const colon = tag.references.find((ref) => ref.code === DiagnosticCode4.KeywordElse);
|
|
1372
|
-
if (!questionMark || !colon) return void 0;
|
|
1373
|
-
const condRange = Range.fromPositions(
|
|
1374
|
-
range.getStartPosition(),
|
|
1375
|
-
model.getPositionAt(model.getOffsetAt(Range.getStartPosition(questionMark.range)))
|
|
1376
|
-
);
|
|
1377
|
-
const thenRange = Range.fromPositions(
|
|
1378
|
-
model.getPositionAt(model.getOffsetAt(Range.getEndPosition(questionMark.range))),
|
|
1379
|
-
model.getPositionAt(model.getOffsetAt(Range.getStartPosition(colon.range)))
|
|
1380
|
-
);
|
|
1381
|
-
const elseRange = Range.fromPositions(
|
|
1382
|
-
model.getPositionAt(model.getOffsetAt(Range.getEndPosition(colon.range))),
|
|
1383
|
-
range.getEndPosition()
|
|
1384
|
-
);
|
|
1385
|
-
const cond = model.getValueInRange(condRange).trim();
|
|
1386
|
-
const thenExpr = model.getValueInRange(thenRange).trim();
|
|
1387
|
-
const elseExpr = model.getValueInRange(elseRange).trim();
|
|
1388
|
-
const wrapIfNeeded = (expr, elseBranch) => {
|
|
1389
|
-
if (elseBranch && expr.startsWith("if ") && expr.endsWith("}")) {
|
|
1390
|
-
return expr;
|
|
1391
|
-
}
|
|
1392
|
-
if (expr.startsWith("{") && expr.endsWith("}") && !expr.includes(":")) {
|
|
1393
|
-
return expr;
|
|
1394
|
-
}
|
|
1395
|
-
if (expr.includes("\n")) {
|
|
1396
|
-
return `{
|
|
1397
|
-
${expr}
|
|
1398
|
-
}`;
|
|
1399
|
-
}
|
|
1400
|
-
return `{ ${expr} }`;
|
|
1401
|
-
};
|
|
1402
|
-
const fixed = `if ${cond} ${wrapIfNeeded(thenExpr, false)} else ${wrapIfNeeded(elseExpr, true)}`;
|
|
1403
|
-
action.title = "转换为 if 表达式";
|
|
1404
|
-
action.kind = "quickfix";
|
|
1405
|
-
action.edit = edits({
|
|
1406
|
-
range,
|
|
1407
|
-
text: fixed
|
|
1408
|
-
});
|
|
1409
|
-
}
|
|
1410
|
-
if (action.title) return action;
|
|
1411
|
-
return void 0;
|
|
1412
|
-
}
|
|
1413
|
-
var CodeActionProvider = class extends Provider {
|
|
1414
|
-
/** @inheritdoc */
|
|
1415
|
-
async provideCodeActions(model, range, { markers, only, trigger }, token) {
|
|
1416
|
-
const result = await this.getCompileResult(model);
|
|
1417
|
-
if (!result) return void 0;
|
|
1418
|
-
const context = await this.getContext(model);
|
|
1419
|
-
const actions = [];
|
|
1420
|
-
for (const marker of markers) {
|
|
1421
|
-
const action = createCodeAction(result, context, model, marker);
|
|
1422
|
-
if (action == null || (only && action.kind ? action.kind !== only : false)) {
|
|
1423
|
-
continue;
|
|
1424
|
-
}
|
|
1425
|
-
actions.push(action);
|
|
1426
|
-
}
|
|
1427
|
-
return {
|
|
1428
|
-
actions,
|
|
1429
|
-
dispose: () => void 0
|
|
1430
|
-
};
|
|
1431
|
-
}
|
|
1432
|
-
};
|
|
1433
|
-
|
|
1434
|
-
// src/lsp/providers/code-lens-provider.ts
|
|
1435
|
-
import { DiagnosticCode as DiagnosticCode5 } from "@mirascript/constants";
|
|
1436
|
-
var CodeLensProvider = class extends Provider {
|
|
1437
|
-
/** @inheritdoc */
|
|
1438
|
-
async provideCodeLenses(model, token) {
|
|
1439
|
-
const result = await this.getCompileResult(model);
|
|
1440
|
-
if (!result) return void 0;
|
|
1441
|
-
const lenses = [];
|
|
1442
|
-
for (const { definition, references } of result.groupedTags(model).locals) {
|
|
1443
|
-
if (definition.code === DiagnosticCode5.LocalFunction || definition.code === DiagnosticCode5.LocalModule) {
|
|
1444
|
-
lenses.push({
|
|
1445
|
-
range: definition.range,
|
|
1446
|
-
command: {
|
|
1447
|
-
id: "editor.action.findReferences",
|
|
1448
|
-
title: `${references.length} 个引用`,
|
|
1449
|
-
arguments: [model.uri, Range.getStartPosition(definition.range)]
|
|
1450
|
-
}
|
|
1451
|
-
});
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
return { lenses };
|
|
1455
|
-
}
|
|
1456
|
-
};
|
|
1457
|
-
|
|
1458
|
-
// src/lsp/providers/color-provider.ts
|
|
1459
|
-
import { DiagnosticCode as DiagnosticCode6 } from "@mirascript/constants";
|
|
1460
|
-
var REG_COLOR_STR = /^(@*)(['"`])(#(?:[0-9a-f]{6}|[0-9a-f]{3}|[0-9a-f]{8}|[0-9a-f]{4}))\2\1$/iu;
|
|
1461
|
-
var { parseInt } = Number;
|
|
1462
|
-
function parseColorString(text) {
|
|
1463
|
-
const colorMatch = REG_COLOR_STR.exec(text);
|
|
1464
|
-
if (!colorMatch) {
|
|
1465
|
-
return void 0;
|
|
1466
|
-
}
|
|
1467
|
-
const ats = colorMatch[1] || "";
|
|
1468
|
-
const quote = colorMatch[2] || "";
|
|
1469
|
-
const colorString = colorMatch[3];
|
|
1470
|
-
let color;
|
|
1471
|
-
if (colorString.startsWith("#")) {
|
|
1472
|
-
const colorCode = colorString.slice(1);
|
|
1473
|
-
if (colorCode.length === 3) {
|
|
1474
|
-
color = {
|
|
1475
|
-
red: parseInt(colorCode[0] + colorCode[0], 16) / 255,
|
|
1476
|
-
green: parseInt(colorCode[1] + colorCode[1], 16) / 255,
|
|
1477
|
-
blue: parseInt(colorCode[2] + colorCode[2], 16) / 255,
|
|
1478
|
-
alpha: 1
|
|
1479
|
-
};
|
|
1480
|
-
} else if (colorCode.length === 6) {
|
|
1481
|
-
color = {
|
|
1482
|
-
red: parseInt(colorCode.slice(0, 2), 16) / 255,
|
|
1483
|
-
green: parseInt(colorCode.slice(2, 4), 16) / 255,
|
|
1484
|
-
blue: parseInt(colorCode.slice(4, 6), 16) / 255,
|
|
1485
|
-
alpha: 1
|
|
1486
|
-
// 假设不透明
|
|
1487
|
-
};
|
|
1488
|
-
} else if (colorCode.length === 8) {
|
|
1489
|
-
color = {
|
|
1490
|
-
red: parseInt(colorCode.slice(0, 2), 16) / 255,
|
|
1491
|
-
green: parseInt(colorCode.slice(2, 4), 16) / 255,
|
|
1492
|
-
blue: parseInt(colorCode.slice(4, 6), 16) / 255,
|
|
1493
|
-
alpha: parseInt(colorCode.slice(6, 8), 16) / 255
|
|
1494
|
-
};
|
|
1495
|
-
} else if (colorCode.length === 4) {
|
|
1496
|
-
color = {
|
|
1497
|
-
red: parseInt(colorCode[0] + colorCode[0], 16) / 255,
|
|
1498
|
-
green: parseInt(colorCode[1] + colorCode[1], 16) / 255,
|
|
1499
|
-
blue: parseInt(colorCode[2] + colorCode[2], 16) / 255,
|
|
1500
|
-
alpha: parseInt(colorCode[3] + colorCode[3], 16) / 255
|
|
1501
|
-
};
|
|
1502
|
-
} else {
|
|
1503
|
-
return void 0;
|
|
1504
|
-
}
|
|
1505
|
-
} else {
|
|
1506
|
-
return void 0;
|
|
1507
|
-
}
|
|
1508
|
-
return {
|
|
1509
|
-
ats,
|
|
1510
|
-
quote,
|
|
1511
|
-
colorString,
|
|
1512
|
-
color
|
|
1513
|
-
};
|
|
1514
|
-
}
|
|
1515
|
-
var ColorProvider = class extends Provider {
|
|
1516
|
-
/** @inheritdoc */
|
|
1517
|
-
async provideDocumentColors(model, token) {
|
|
1518
|
-
const compiled = await this.getCompileResult(model);
|
|
1519
|
-
if (!compiled) return void 0;
|
|
1520
|
-
const info = [];
|
|
1521
|
-
for (const { range, code } of compiled.groupedTags(model).ranges) {
|
|
1522
|
-
if (code !== DiagnosticCode6.String) continue;
|
|
1523
|
-
if (range.startLineNumber !== range.endLineNumber) {
|
|
1524
|
-
continue;
|
|
1525
|
-
}
|
|
1526
|
-
const text = model.getValueInRange(range);
|
|
1527
|
-
const parsed = parseColorString(text);
|
|
1528
|
-
if (!parsed) continue;
|
|
1529
|
-
info.push({
|
|
1530
|
-
range: {
|
|
1531
|
-
startLineNumber: range.startLineNumber,
|
|
1532
|
-
startColumn: range.startColumn + parsed.ats.length + parsed.quote.length,
|
|
1533
|
-
endLineNumber: range.endLineNumber,
|
|
1534
|
-
endColumn: range.endColumn - parsed.ats.length - parsed.quote.length
|
|
1535
|
-
},
|
|
1536
|
-
color: parsed.color
|
|
1537
|
-
});
|
|
1538
|
-
}
|
|
1539
|
-
return info;
|
|
1540
|
-
}
|
|
1541
|
-
/** @inheritdoc */
|
|
1542
|
-
provideColorPresentations(model, colorInfo, token) {
|
|
1543
|
-
const { color } = colorInfo;
|
|
1544
|
-
return [
|
|
1545
|
-
{
|
|
1546
|
-
label: `#${Math.round(color.red * 255).toString(16).padStart(2, "0")}${Math.round(color.green * 255).toString(16).padStart(2, "0")}${Math.round(color.blue * 255).toString(16).padStart(2, "0")}${color.alpha >= 1 ? "" : Math.round(color.alpha * 255).toString(16).padStart(2, "0")}`
|
|
1547
|
-
}
|
|
1548
|
-
];
|
|
1549
|
-
}
|
|
1550
|
-
};
|
|
1551
|
-
|
|
1552
|
-
// src/lsp/providers/completion-item-provider.ts
|
|
1553
|
-
import {
|
|
1554
|
-
getVmFunctionInfo as getVmFunctionInfo2,
|
|
1555
|
-
isVmExtern as isVmExtern2,
|
|
1556
|
-
isVmModule as isVmModule2,
|
|
1557
|
-
isVmWrapper as isVmWrapper2,
|
|
1558
|
-
serialize as serialize2
|
|
1559
|
-
} from "@mirascript/mirascript";
|
|
1560
|
-
import { DiagnosticCode as DiagnosticCode7 } from "@mirascript/mirascript/subtle";
|
|
1561
|
-
import { KEYWORDS as HELP_KEYWORDS } from "@mirascript/help";
|
|
1562
|
-
var DESC_GLOBAL = "(global)";
|
|
1563
|
-
var DESC_LOCAL = "(local)";
|
|
1564
|
-
var DESC_FIELD = "(field)";
|
|
1565
|
-
var SUGGEST_KEYWORDS = [];
|
|
1566
|
-
var loadSuggestKeywords = () => {
|
|
1567
|
-
if (SUGGEST_KEYWORDS.length > 0) return SUGGEST_KEYWORDS;
|
|
1568
|
-
for (const kw of KEYWORDS) {
|
|
1569
|
-
if (RESERVED_KEYWORDS.includes(kw)) continue;
|
|
1570
|
-
SUGGEST_KEYWORDS.push(kw);
|
|
1571
|
-
}
|
|
1572
|
-
return SUGGEST_KEYWORDS;
|
|
1573
|
-
};
|
|
1574
|
-
var COMMON_GLOBAL_SUGGESTIONS = (range, extension) => {
|
|
1575
|
-
const suggestions = [
|
|
1576
|
-
{
|
|
1577
|
-
label: "type",
|
|
1578
|
-
kind: languages.CompletionItemKind.Keyword,
|
|
1579
|
-
insertText: "type",
|
|
1580
|
-
commitCharacters: ["("],
|
|
1581
|
-
documentation: { value: HELP_KEYWORDS.type },
|
|
1582
|
-
range
|
|
1583
|
-
},
|
|
1584
|
-
{
|
|
1585
|
-
label: "global",
|
|
1586
|
-
kind: languages.CompletionItemKind.Keyword,
|
|
1587
|
-
insertText: "global",
|
|
1588
|
-
commitCharacters: [".", "["],
|
|
1589
|
-
documentation: { value: HELP_KEYWORDS.global },
|
|
1590
|
-
range
|
|
1591
|
-
}
|
|
1592
|
-
];
|
|
1593
|
-
if (!extension) {
|
|
1594
|
-
suggestions.push(
|
|
1595
|
-
{
|
|
1596
|
-
label: { label: "if", description: "If 表达式" },
|
|
1597
|
-
kind: languages.CompletionItemKind.Snippet,
|
|
1598
|
-
insertText: "if ${1:condition} {\n $0\n}",
|
|
1599
|
-
insertTextRules: languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
|
1600
|
-
documentation: {
|
|
1601
|
-
value: `使用 \`if\` 表达式进行条件判断。${codeblock("if condition {\n // code\n}")}`
|
|
1602
|
-
},
|
|
1603
|
-
range
|
|
1604
|
-
},
|
|
1605
|
-
{
|
|
1606
|
-
label: { label: "ifelse", description: "If-Else 表达式" },
|
|
1607
|
-
kind: languages.CompletionItemKind.Snippet,
|
|
1608
|
-
insertText: "if ${1:condition} {\n $0\n} else {\n \n}",
|
|
1609
|
-
insertTextRules: languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
|
1610
|
-
documentation: {
|
|
1611
|
-
value: `使用 \`ifelse\` 表达式进行条件判断。${codeblock("if condition {\n // code\n} else {\n // code\n}")}`
|
|
1612
|
-
},
|
|
1613
|
-
range
|
|
1614
|
-
},
|
|
1615
|
-
{
|
|
1616
|
-
label: { label: "match", description: "Match 表达式" },
|
|
1617
|
-
kind: languages.CompletionItemKind.Snippet,
|
|
1618
|
-
insertText: "match ${1:value} {\n case ${2:case1} {\n $0\n }\n case ${3:case2} {\n \n }\n case _ {\n \n }\n}",
|
|
1619
|
-
insertTextRules: languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
|
1620
|
-
documentation: {
|
|
1621
|
-
value: `使用 \`match\` 表达式进行模式匹配。${codeblock("match value {\n case case1 {\n // code\n }\n case case2 {\n // code\n }\n case _ {\n // code\n }\n}")}`
|
|
1622
|
-
},
|
|
1623
|
-
range
|
|
1624
|
-
},
|
|
1625
|
-
{
|
|
1626
|
-
label: { label: "loop", description: "Loop 表达式" },
|
|
1627
|
-
kind: languages.CompletionItemKind.Snippet,
|
|
1628
|
-
insertText: "loop {\n $0\n}",
|
|
1629
|
-
insertTextRules: languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
|
1630
|
-
documentation: {
|
|
1631
|
-
value: `使用 \`loop\` 表达式进行无限循环。${codeblock("loop {\n // code\n}")}`
|
|
1632
|
-
},
|
|
1633
|
-
range
|
|
1634
|
-
},
|
|
1635
|
-
{
|
|
1636
|
-
label: { label: "while", description: "While 表达式" },
|
|
1637
|
-
kind: languages.CompletionItemKind.Snippet,
|
|
1638
|
-
insertText: "while ${1:condition} {\n $0\n}",
|
|
1639
|
-
insertTextRules: languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
|
1640
|
-
documentation: {
|
|
1641
|
-
value: `使用 \`while\` 表达式进行条件循环。${codeblock("while condition {\n // code\n}")}`
|
|
1642
|
-
},
|
|
1643
|
-
range
|
|
1644
|
-
},
|
|
1645
|
-
{
|
|
1646
|
-
label: { label: "whileelse", description: "While-Else 表达式" },
|
|
1647
|
-
kind: languages.CompletionItemKind.Snippet,
|
|
1648
|
-
insertText: "while ${1:condition} {\n $0\n} else {\n \n}",
|
|
1649
|
-
insertTextRules: languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
|
1650
|
-
documentation: {
|
|
1651
|
-
value: `使用 \`whileelse\` 表达式进行条件循环。${codeblock("while condition {\n // code\n} else {\n // code\n}")}`
|
|
1652
|
-
},
|
|
1653
|
-
range
|
|
1654
|
-
},
|
|
1655
|
-
{
|
|
1656
|
-
label: { label: "for", description: "For 表达式" },
|
|
1657
|
-
kind: languages.CompletionItemKind.Snippet,
|
|
1658
|
-
insertText: "for ${1:item} in ${2:collection} {\n $0\n}",
|
|
1659
|
-
insertTextRules: languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
|
1660
|
-
documentation: {
|
|
1661
|
-
value: `使用 \`for\` 表达式进行迭代循环。${codeblock("for item in collection {\n // code\n}")}`
|
|
1662
|
-
},
|
|
1663
|
-
range
|
|
1664
|
-
},
|
|
1665
|
-
{
|
|
1666
|
-
label: { label: "forelse", description: "For-Else 表达式" },
|
|
1667
|
-
kind: languages.CompletionItemKind.Snippet,
|
|
1668
|
-
insertText: "for ${1:item} in ${2:collection} {\n $0\n} else {\n \n}",
|
|
1669
|
-
insertTextRules: languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
|
1670
|
-
documentation: {
|
|
1671
|
-
value: `使用 \`forelse\` 表达式进行迭代循环。${codeblock("for item in collection {\n // code\n} else {\n // code\n}")}`
|
|
1672
|
-
},
|
|
1673
|
-
range
|
|
1674
|
-
},
|
|
1675
|
-
{
|
|
1676
|
-
label: { label: "fn", description: "Fn 语句" },
|
|
1677
|
-
kind: languages.CompletionItemKind.Snippet,
|
|
1678
|
-
insertText: "fn ${1:name}(${2:params}) {\n $0\n}",
|
|
1679
|
-
insertTextRules: languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
|
1680
|
-
documentation: {
|
|
1681
|
-
value: `使用 \`fn\` 语句进行函数声明。${codeblock("fn name(params) {\n // code\n}")}`
|
|
1682
|
-
},
|
|
1683
|
-
range
|
|
1684
|
-
}
|
|
1685
|
-
);
|
|
1686
|
-
for (const kw of loadSuggestKeywords()) {
|
|
1687
|
-
const exist = suggestions.find(
|
|
1688
|
-
(item) => item.label === kw && item.kind === languages.CompletionItemKind.Keyword
|
|
1689
|
-
);
|
|
1690
|
-
if (exist) continue;
|
|
1691
|
-
suggestions.push(kwSuggestion(kw, range));
|
|
1692
|
-
}
|
|
1693
|
-
}
|
|
1694
|
-
return suggestions;
|
|
1695
|
-
};
|
|
1696
|
-
function kwSuggestion(kw, range) {
|
|
1697
|
-
const doc = HELP_KEYWORDS[kw];
|
|
1698
|
-
return {
|
|
1699
|
-
label: kw,
|
|
1700
|
-
kind: languages.CompletionItemKind.Keyword,
|
|
1701
|
-
insertText: kw,
|
|
1702
|
-
documentation: doc ? { value: doc } : void 0,
|
|
1703
|
-
range
|
|
1704
|
-
};
|
|
1705
|
-
}
|
|
1706
|
-
function filterText(key, char) {
|
|
1707
|
-
if (char == null || key.startsWith(char)) return key;
|
|
1708
|
-
if (key.startsWith("@")) return key.replace(/^@+/, "");
|
|
1709
|
-
if (key.startsWith("$")) return key.replace(/^\$+/, "");
|
|
1710
|
-
return key;
|
|
1711
|
-
}
|
|
1712
|
-
function completion(model, description, key, value, fn, field) {
|
|
1713
|
-
let detail = "";
|
|
1714
|
-
let kind;
|
|
1715
|
-
if (fn == null && typeof value == "function") {
|
|
1716
|
-
fn = getVmFunctionInfo2(value);
|
|
1717
|
-
}
|
|
1718
|
-
if (fn != null) {
|
|
1719
|
-
detail = paramsList(model, fn);
|
|
1720
|
-
kind = field ? languages.CompletionItemKind.Function : languages.CompletionItemKind.Method;
|
|
1721
|
-
} else if (isVmModule2(value)) {
|
|
1722
|
-
kind = languages.CompletionItemKind.Module;
|
|
1723
|
-
} else if (isVmExtern2(value) && typeof value.value == "function") {
|
|
1724
|
-
if (value.value.prototype != null && (key[0] ?? "").toUpperCase() === key[0]) {
|
|
1725
|
-
kind = languages.CompletionItemKind.Class;
|
|
1726
|
-
} else {
|
|
1727
|
-
detail = "(..)";
|
|
1728
|
-
kind = value.thisArg ? languages.CompletionItemKind.Method : languages.CompletionItemKind.Function;
|
|
1729
|
-
}
|
|
1730
|
-
} else if (!field && key.startsWith("@")) {
|
|
1731
|
-
kind = languages.CompletionItemKind.Constant;
|
|
1732
|
-
} else {
|
|
1733
|
-
kind = field ? languages.CompletionItemKind.Field : languages.CompletionItemKind.Variable;
|
|
1734
|
-
}
|
|
1735
|
-
return {
|
|
1736
|
-
label: { label: key, description, detail },
|
|
1737
|
-
kind,
|
|
1738
|
-
commitCharacters: fn ? ["!", "("] : ["!", ".", "[", "("],
|
|
1739
|
-
vmValue: value,
|
|
1740
|
-
isField: field
|
|
1741
|
-
};
|
|
1742
|
-
}
|
|
1743
|
-
var CompletionItemProvider = class extends Provider {
|
|
1744
|
-
constructor() {
|
|
1745
|
-
super(...arguments);
|
|
1746
|
-
this.triggerCharacters = [".", ":"];
|
|
1747
|
-
}
|
|
1748
|
-
/** 查找全局变量 */
|
|
1749
|
-
async completeGlobal(model, char, locals, range, hasGlobalPrefix) {
|
|
1750
|
-
const global = await this.getContext(model);
|
|
1751
|
-
const suggestions = [];
|
|
1752
|
-
const localKeys = new Set(locals.map((item) => item.insertText));
|
|
1753
|
-
for (const key of new Set(global.keys())) {
|
|
1754
|
-
if (!global.has(key)) continue;
|
|
1755
|
-
const element = global.get(key);
|
|
1756
|
-
let prefix = key;
|
|
1757
|
-
const edits = [];
|
|
1758
|
-
if (!REG_IDENTIFIER_FULL.test(key)) {
|
|
1759
|
-
const kStr = serialize2(key);
|
|
1760
|
-
if (hasGlobalPrefix) {
|
|
1761
|
-
prefix = `[${kStr}]`;
|
|
1762
|
-
edits.push({
|
|
1763
|
-
range: {
|
|
1764
|
-
startLineNumber: range.replace.startLineNumber,
|
|
1765
|
-
startColumn: range.replace.startColumn - 1,
|
|
1766
|
-
endLineNumber: range.replace.endLineNumber,
|
|
1767
|
-
endColumn: range.replace.endColumn
|
|
1768
|
-
},
|
|
1769
|
-
text: ""
|
|
1770
|
-
});
|
|
1771
|
-
} else {
|
|
1772
|
-
prefix = `global[${serialize2(key)}]`;
|
|
1773
|
-
}
|
|
1774
|
-
} else if (!hasGlobalPrefix && (localKeys.has(key) || isKeyword(key))) {
|
|
1775
|
-
prefix = `global.${key}`;
|
|
1776
|
-
}
|
|
1777
|
-
if (isVmModule2(element)) {
|
|
1778
|
-
for (const f of element.keys()) {
|
|
1779
|
-
if (char && !f.toLowerCase().includes(char)) {
|
|
1780
|
-
continue;
|
|
1781
|
-
}
|
|
1782
|
-
const field = element.get(f);
|
|
1783
|
-
if (field === void 0) continue;
|
|
1784
|
-
suggestions.push({
|
|
1785
|
-
insertText: `${prefix}.${f}`,
|
|
1786
|
-
filterText: filterText(f, char),
|
|
1787
|
-
range,
|
|
1788
|
-
additionalTextEdits: edits,
|
|
1789
|
-
vmParent: element,
|
|
1790
|
-
...completion(model, DESC_GLOBAL, `${key}.${f}`, field, void 0, true)
|
|
1791
|
-
});
|
|
1792
|
-
}
|
|
1793
|
-
}
|
|
1794
|
-
if (char && !key.toLowerCase().includes(char)) {
|
|
1795
|
-
continue;
|
|
1796
|
-
}
|
|
1797
|
-
if (isDeprecatedGlobal(global, key)) {
|
|
1798
|
-
continue;
|
|
1799
|
-
}
|
|
1800
|
-
suggestions.push({
|
|
1801
|
-
insertText: prefix,
|
|
1802
|
-
filterText: filterText(key, char),
|
|
1803
|
-
range,
|
|
1804
|
-
additionalTextEdits: edits,
|
|
1805
|
-
vmParent: global,
|
|
1806
|
-
...completion(model, DESC_GLOBAL, key, element, void 0, false)
|
|
1807
|
-
});
|
|
1808
|
-
}
|
|
1809
|
-
return suggestions;
|
|
1810
|
-
}
|
|
1811
|
-
/** 查找局部变量 */
|
|
1812
|
-
async completeLocal(model, position, char, range) {
|
|
1813
|
-
const compiled = await this.getCompileResult(model);
|
|
1814
|
-
if (!compiled) return [];
|
|
1815
|
-
const suggestions = [];
|
|
1816
|
-
let scope = compiled.scopeAt(model, position);
|
|
1817
|
-
const locals = /* @__PURE__ */ new Set();
|
|
1818
|
-
while (scope) {
|
|
1819
|
-
for (const { definition, fn } of scope.locals) {
|
|
1820
|
-
const name = definition.code === DiagnosticCode7.ParameterIt ? "it" : model.getValueInRange(definition.range);
|
|
1821
|
-
if (char && !name.toLowerCase().includes(char)) continue;
|
|
1822
|
-
if (locals.has(name)) continue;
|
|
1823
|
-
locals.add(name);
|
|
1824
|
-
const suggestion = {
|
|
1825
|
-
insertText: name,
|
|
1826
|
-
filterText: filterText(name, char),
|
|
1827
|
-
range,
|
|
1828
|
-
...completion(model, DESC_LOCAL, name, void 0, fn, false)
|
|
1829
|
-
};
|
|
1830
|
-
if (definition.code === DiagnosticCode7.LocalModule) {
|
|
1831
|
-
suggestion.kind = languages.CompletionItemKind.Module;
|
|
1832
|
-
} else if (definition.code === DiagnosticCode7.LocalFunction) {
|
|
1833
|
-
suggestion.kind = languages.CompletionItemKind.Function;
|
|
1834
|
-
}
|
|
1835
|
-
suggestions.push(suggestion);
|
|
1836
|
-
}
|
|
1837
|
-
if (!scope.parent) break;
|
|
1838
|
-
scope = scope.parent;
|
|
1839
|
-
}
|
|
1840
|
-
return suggestions;
|
|
1841
|
-
}
|
|
1842
|
-
/** 查找变量字段 */
|
|
1843
|
-
async completeFields(model, position, char, range) {
|
|
1844
|
-
const compiled = await this.getCompileResult(model);
|
|
1845
|
-
if (!compiled) return [];
|
|
1846
|
-
const access = compiled.fieldAccessAt(model, position);
|
|
1847
|
-
if (!access || access.fields.length === 0) return [];
|
|
1848
|
-
const { def, fields } = access;
|
|
1849
|
-
if ("definition" in def.def) {
|
|
1850
|
-
return [];
|
|
1851
|
-
}
|
|
1852
|
-
const vmGlobal = await this.getContext(model);
|
|
1853
|
-
fields.pop();
|
|
1854
|
-
const [, value] = getDeep(vmGlobal, def.def.name, fields);
|
|
1855
|
-
if (value == null || typeof value != "object") {
|
|
1856
|
-
return [];
|
|
1857
|
-
}
|
|
1858
|
-
const keys = listFields(value, true);
|
|
1859
|
-
const result = [];
|
|
1860
|
-
for (const k of keys) {
|
|
1861
|
-
const key = String(k);
|
|
1862
|
-
if (char && !String(key).toLowerCase().includes(char)) {
|
|
1863
|
-
continue;
|
|
1864
|
-
}
|
|
1865
|
-
if (!REG_IDENTIFIER_FULL.test(key) && !REG_ORDINAL_FULL.test(key)) {
|
|
1866
|
-
continue;
|
|
1867
|
-
}
|
|
1868
|
-
const field = getField(value, key);
|
|
1869
|
-
result.push({
|
|
1870
|
-
insertText: key,
|
|
1871
|
-
range,
|
|
1872
|
-
vmParent: isVmWrapper2(value) ? value : void 0,
|
|
1873
|
-
...completion(model, DESC_FIELD, key, field, void 0, true)
|
|
1874
|
-
});
|
|
1875
|
-
}
|
|
1876
|
-
return result;
|
|
1877
|
-
}
|
|
1878
|
-
/** 获取完成范围 */
|
|
1879
|
-
toCompletionItemRanges(position, range) {
|
|
1880
|
-
return {
|
|
1881
|
-
replace: range,
|
|
1882
|
-
insert: Range.fromPositions(Range.getStartPosition(range), position)
|
|
1883
|
-
};
|
|
1884
|
-
}
|
|
1885
|
-
/** @inheritdoc */
|
|
1886
|
-
async provideCompletionItems(model, position, context, token) {
|
|
1887
|
-
const compiled = await this.getCompileResult(model);
|
|
1888
|
-
if (!compiled) return void 0;
|
|
1889
|
-
if (context.triggerCharacter === ".") {
|
|
1890
|
-
const prevWord = model.getWordAtPosition({
|
|
1891
|
-
lineNumber: position.lineNumber,
|
|
1892
|
-
column: position.column - 1
|
|
1893
|
-
});
|
|
1894
|
-
if (prevWord?.word === "global") {
|
|
1895
|
-
const globals2 = await this.completeGlobal(
|
|
1896
|
-
model,
|
|
1897
|
-
void 0,
|
|
1898
|
-
[],
|
|
1899
|
-
this.toCompletionItemRanges(position, {
|
|
1900
|
-
startLineNumber: position.lineNumber,
|
|
1901
|
-
startColumn: position.column,
|
|
1902
|
-
endLineNumber: position.lineNumber,
|
|
1903
|
-
endColumn: position.column
|
|
1904
|
-
}),
|
|
1905
|
-
true
|
|
1906
|
-
);
|
|
1907
|
-
return { suggestions: globals2 };
|
|
1908
|
-
}
|
|
1909
|
-
}
|
|
1910
|
-
const word = wordAt(model, position);
|
|
1911
|
-
const prev = model.getValueInRange({
|
|
1912
|
-
startLineNumber: position.lineNumber,
|
|
1913
|
-
startColumn: (word?.range.startColumn ?? position.column) - 2,
|
|
1914
|
-
endLineNumber: position.lineNumber,
|
|
1915
|
-
endColumn: word?.range.startColumn ?? position.column
|
|
1916
|
-
});
|
|
1917
|
-
if (context.triggerCharacter === ":" && prev !== "::") {
|
|
1918
|
-
return void 0;
|
|
1919
|
-
}
|
|
1920
|
-
let char;
|
|
1921
|
-
let range;
|
|
1922
|
-
const def = compiled.variableAccessAt(model, position);
|
|
1923
|
-
if (def) {
|
|
1924
|
-
if (def.ref == null) {
|
|
1925
|
-
const suggestions2 = [];
|
|
1926
|
-
if (word && compiled.tags.some(
|
|
1927
|
-
(t) => strictContainsPosition(t.range, position) && t.code === DiagnosticCode7.MatchExpression
|
|
1928
|
-
)) {
|
|
1929
|
-
suggestions2.push(
|
|
1930
|
-
kwSuggestion("case", this.toCompletionItemRanges(position, word.range)),
|
|
1931
|
-
kwSuggestion("if", this.toCompletionItemRanges(position, word.range))
|
|
1932
|
-
);
|
|
1933
|
-
}
|
|
1934
|
-
return { suggestions: suggestions2 };
|
|
1935
|
-
}
|
|
1936
|
-
const d = def.def;
|
|
1937
|
-
range = d.references[def.ref].range;
|
|
1938
|
-
char = model.getValueInRange({
|
|
1939
|
-
startLineNumber: range.startLineNumber,
|
|
1940
|
-
startColumn: range.startColumn,
|
|
1941
|
-
endLineNumber: range.startLineNumber,
|
|
1942
|
-
endColumn: range.startColumn + 1
|
|
1943
|
-
});
|
|
1944
|
-
} else if (word) {
|
|
1945
|
-
range = word.range;
|
|
1946
|
-
char = word.word[0];
|
|
1947
|
-
} else {
|
|
1948
|
-
range = {
|
|
1949
|
-
startLineNumber: position.lineNumber,
|
|
1950
|
-
startColumn: position.column,
|
|
1951
|
-
endLineNumber: position.lineNumber,
|
|
1952
|
-
endColumn: position.column
|
|
1953
|
-
};
|
|
1954
|
-
}
|
|
1955
|
-
char = char?.toLowerCase();
|
|
1956
|
-
const completionRange = this.toCompletionItemRanges(position, range);
|
|
1957
|
-
if (/[^.]\.$/u.test(prev)) {
|
|
1958
|
-
const suggestions2 = await this.completeFields(model, position, char, completionRange);
|
|
1959
|
-
return { suggestions: suggestions2 };
|
|
1960
|
-
}
|
|
1961
|
-
const suggestions = COMMON_GLOBAL_SUGGESTIONS(completionRange, prev === "::");
|
|
1962
|
-
const locals = await this.completeLocal(model, position, char, completionRange);
|
|
1963
|
-
const globals = await this.completeGlobal(model, char, locals, completionRange, false);
|
|
1964
|
-
suggestions.push(...locals, ...globals);
|
|
1965
|
-
return { suggestions };
|
|
1966
|
-
}
|
|
1967
|
-
/** @inheritdoc */
|
|
1968
|
-
resolveCompletionItem(item, token) {
|
|
1969
|
-
if (typeof item.label == "string") {
|
|
1970
|
-
return item;
|
|
1971
|
-
}
|
|
1972
|
-
const { vmValue, isField, vmParent } = item;
|
|
1973
|
-
const { label } = item.label;
|
|
1974
|
-
if (vmValue !== void 0 || vmParent) {
|
|
1975
|
-
if (item.documentation) return item;
|
|
1976
|
-
const last = label.split(".").pop();
|
|
1977
|
-
const def = valueDoc(last, vmValue, isField ? "field" : "hint", vmParent ?? null);
|
|
1978
|
-
item.documentation = {
|
|
1979
|
-
value: `${codeblock("\0" + def.script)}
|
|
1980
|
-
${def.doc.join("\n")}`
|
|
1981
|
-
};
|
|
1982
|
-
}
|
|
1983
|
-
return item;
|
|
1984
|
-
}
|
|
1985
|
-
};
|
|
1986
|
-
|
|
1987
|
-
// src/lsp/providers/definition-reference-provider.ts
|
|
1988
|
-
var DefinitionReferenceProvider = class extends Provider {
|
|
1989
|
-
constructor() {
|
|
1990
|
-
super(...arguments);
|
|
1991
|
-
/** 创建全局模型 */
|
|
1992
|
-
this.createGlobalModel = (uri) => editor.createModel(``, "mirascript-doc", Uri.parse(uri));
|
|
1993
|
-
}
|
|
1994
|
-
#globalModel;
|
|
1995
|
-
/** 全局模型 */
|
|
1996
|
-
async getGlobalModel() {
|
|
1997
|
-
if (!this.#globalModel || this.#globalModel.isDisposed()) {
|
|
1998
|
-
this.#globalModel = await this.createGlobalModel("mirascript:///lib/global.mira") ?? void 0;
|
|
1999
|
-
}
|
|
2000
|
-
return this.#globalModel;
|
|
2001
|
-
}
|
|
2002
|
-
/** 准备要显示的定义 */
|
|
2003
|
-
async prepareGlobal(model, paths, focus = 0) {
|
|
2004
|
-
const globalModel = await this.getGlobalModel();
|
|
2005
|
-
if (!globalModel) return void 0;
|
|
2006
|
-
const globals = await this.getContext(model);
|
|
2007
|
-
const code = [];
|
|
2008
|
-
const focusRange = {
|
|
2009
|
-
startColumn: 1,
|
|
2010
|
-
startLineNumber: 1,
|
|
2011
|
-
endColumn: 1,
|
|
2012
|
-
endLineNumber: 1
|
|
2013
|
-
};
|
|
2014
|
-
for (const [index, path] of paths.entries()) {
|
|
2015
|
-
const [name, ...access] = path;
|
|
2016
|
-
const [parent, value] = getDeep(globals, name, access);
|
|
2017
|
-
if (value === void 0) return void 0;
|
|
2018
|
-
const { script, doc } = valueDoc(path.at(-1), value, "declare", parent);
|
|
2019
|
-
if (index !== focus) {
|
|
2020
|
-
code.push(...docComment(doc), ...script.split("\n"), "");
|
|
2021
|
-
continue;
|
|
2022
|
-
}
|
|
2023
|
-
code.push(...docComment(doc));
|
|
2024
|
-
const defName = path.at(-1);
|
|
2025
|
-
const scriptLines = script.split("\n");
|
|
2026
|
-
const decLine = scriptLines.findIndex((line) => line.includes(defName));
|
|
2027
|
-
if (decLine < 0) {
|
|
2028
|
-
focusRange.startLineNumber = code.length + 1;
|
|
2029
|
-
code.push(...script.split("\n"));
|
|
2030
|
-
focusRange.endLineNumber = code.length + 1;
|
|
2031
|
-
} else {
|
|
2032
|
-
code.push(...script.split("\n"));
|
|
2033
|
-
const decLineText = scriptLines[decLine];
|
|
2034
|
-
focusRange.startLineNumber = code.length - scriptLines.length + decLine + 1;
|
|
2035
|
-
focusRange.endLineNumber = focusRange.startLineNumber;
|
|
2036
|
-
const nameIndex = decLineText.indexOf(defName);
|
|
2037
|
-
focusRange.startColumn = nameIndex + 1;
|
|
2038
|
-
focusRange.endColumn = nameIndex + defName.length + 1;
|
|
2039
|
-
}
|
|
2040
|
-
code.push("");
|
|
2041
|
-
}
|
|
2042
|
-
globalModel.setValue(code.join("\n"));
|
|
2043
|
-
return {
|
|
2044
|
-
uri: globalModel.uri,
|
|
2045
|
-
range: focusRange
|
|
2046
|
-
};
|
|
2047
|
-
}
|
|
2048
|
-
/** @inheritdoc */
|
|
2049
|
-
async provideDefinition(model, position, token) {
|
|
2050
|
-
const value = await this.getValueAt(model, position);
|
|
2051
|
-
if (!value) return void 0;
|
|
2052
|
-
if ("variable" in value) {
|
|
2053
|
-
const { def } = value.variable;
|
|
2054
|
-
let link;
|
|
2055
|
-
if ("name" in def) {
|
|
2056
|
-
link = await this.prepareGlobal(model, [[def.name]]);
|
|
2057
|
-
} else {
|
|
2058
|
-
link = { uri: model.uri, range: def.definition.range };
|
|
2059
|
-
}
|
|
2060
|
-
if (!link) return void 0;
|
|
2061
|
-
link.originSelectionRange = value.range;
|
|
2062
|
-
return [link];
|
|
2063
|
-
} else {
|
|
2064
|
-
const {
|
|
2065
|
-
def: { def },
|
|
2066
|
-
fields
|
|
2067
|
-
} = value.fields;
|
|
2068
|
-
if ("name" in def) {
|
|
2069
|
-
const link = await this.prepareGlobal(model, [
|
|
2070
|
-
[def.name, ...fields]
|
|
2071
|
-
]);
|
|
2072
|
-
if (!link) return void 0;
|
|
2073
|
-
link.originSelectionRange = value.range;
|
|
2074
|
-
return [link];
|
|
2075
|
-
}
|
|
2076
|
-
}
|
|
2077
|
-
return void 0;
|
|
2078
|
-
}
|
|
2079
|
-
/** @inheritdoc */
|
|
2080
|
-
async provideReferences(model, position, context, token) {
|
|
2081
|
-
const value = await this.getValueAt(model, position);
|
|
2082
|
-
if (!value) return void 0;
|
|
2083
|
-
if ("variable" in value) {
|
|
2084
|
-
const { def } = value.variable;
|
|
2085
|
-
const links = def.references.map((u) => ({
|
|
2086
|
-
uri: model.uri,
|
|
2087
|
-
range: u.range
|
|
2088
|
-
}));
|
|
2089
|
-
if (context.includeDeclaration) {
|
|
2090
|
-
if ("name" in def) {
|
|
2091
|
-
const link = await this.prepareGlobal(model, [[def.name]]);
|
|
2092
|
-
if (link) links.push(link);
|
|
2093
|
-
} else if (!Range.isEmpty(def.definition.range)) {
|
|
2094
|
-
links.push({ uri: model.uri, range: def.definition.range });
|
|
2095
|
-
}
|
|
2096
|
-
}
|
|
2097
|
-
return links;
|
|
2098
|
-
}
|
|
2099
|
-
return void 0;
|
|
2100
|
-
}
|
|
2101
|
-
};
|
|
2102
|
-
|
|
2103
|
-
// src/lsp/providers/document-highlight-provider.ts
|
|
2104
|
-
import { DiagnosticCode as DiagnosticCode8 } from "@mirascript/mirascript/subtle";
|
|
2105
|
-
var DocumentHighlightProvider = class extends Provider {
|
|
2106
|
-
/** @inheritdoc */
|
|
2107
|
-
async provideDocumentHighlights(model, position, token) {
|
|
2108
|
-
const word = model.getWordAtPosition(position);
|
|
2109
|
-
if (word && isKeyword(word.word)) {
|
|
2110
|
-
const result = await this.highlightKeyword(model, position, word.word);
|
|
2111
|
-
if (result) return result;
|
|
2112
|
-
}
|
|
2113
|
-
return this.getDocumentHighlightsFromDefinition(model, position);
|
|
2114
|
-
}
|
|
2115
|
-
/** 从 definition 生成 DocumentHighlight 列表 */
|
|
2116
|
-
async getDocumentHighlightsFromDefinition(model, position) {
|
|
2117
|
-
const compiled = await this.getCompileResult(model);
|
|
2118
|
-
if (!compiled) return void 0;
|
|
2119
|
-
const def = compiled.variableAccessAt(model, position)?.def;
|
|
2120
|
-
if (!def) return void 0;
|
|
2121
|
-
const links = def.references.map((u) => {
|
|
2122
|
-
const { code, range } = u;
|
|
2123
|
-
let kind = languages.DocumentHighlightKind.Read;
|
|
2124
|
-
if (code === DiagnosticCode8.WriteLocal || code === DiagnosticCode8.ReadWriteLocal || code === DiagnosticCode8.RedeclareLocal) {
|
|
2125
|
-
kind = languages.DocumentHighlightKind.Write;
|
|
2126
|
-
}
|
|
2127
|
-
return {
|
|
2128
|
-
kind,
|
|
2129
|
-
range
|
|
2130
|
-
};
|
|
2131
|
-
});
|
|
2132
|
-
if ("definition" in def && !Range.isEmpty(def.definition.range)) {
|
|
2133
|
-
links.push({
|
|
2134
|
-
kind: languages.DocumentHighlightKind.Write,
|
|
2135
|
-
range: def.definition.range
|
|
2136
|
-
});
|
|
2137
|
-
}
|
|
2138
|
-
return links;
|
|
2139
|
-
}
|
|
2140
|
-
/** 高亮关键字 */
|
|
2141
|
-
async highlightKeyword(model, position, word) {
|
|
2142
|
-
const compiled = await this.getCompileResult(model);
|
|
2143
|
-
if (!compiled) return void 0;
|
|
2144
|
-
const kw = compiled.tagsReferences.find((kw2) => Range.containsPosition(kw2.range, position));
|
|
2145
|
-
if (!kw) return void 0;
|
|
2146
|
-
return kw.diagnostic.references.map((r) => ({
|
|
2147
|
-
kind: languages.DocumentHighlightKind.Text,
|
|
2148
|
-
range: r.range
|
|
2149
|
-
}));
|
|
2150
|
-
}
|
|
2151
|
-
};
|
|
2152
|
-
|
|
2153
|
-
// src/lsp/providers/document-symbol-provider.ts
|
|
2154
|
-
import { DiagnosticCode as DiagnosticCode9 } from "@mirascript/constants";
|
|
2155
|
-
var DocumentSymbolProvider = class extends Provider {
|
|
2156
|
-
/** 构建树 */
|
|
2157
|
-
handleScope(model, scope) {
|
|
2158
|
-
const symbols = [];
|
|
2159
|
-
const unhandledChildren = new Set(scope.children);
|
|
2160
|
-
for (const { definition } of scope.locals) {
|
|
2161
|
-
const { range } = definition;
|
|
2162
|
-
let kind;
|
|
2163
|
-
let name;
|
|
2164
|
-
let children = [];
|
|
2165
|
-
let allRange = range;
|
|
2166
|
-
switch (definition.code) {
|
|
2167
|
-
case DiagnosticCode9.ParameterIt:
|
|
2168
|
-
if (definition.references.length === 0) {
|
|
2169
|
-
continue;
|
|
2170
|
-
}
|
|
2171
|
-
name = `it`;
|
|
2172
|
-
break;
|
|
2173
|
-
case DiagnosticCode9.LocalFunction: {
|
|
2174
|
-
kind = languages.SymbolKind.Function;
|
|
2175
|
-
const funcScope = scope.children.find((s) => Range.compareRangesUsingStarts(s.range, range) > 0);
|
|
2176
|
-
if (funcScope) {
|
|
2177
|
-
allRange = Range.plusRange(range, funcScope.range);
|
|
2178
|
-
children = this.handleScope(model, funcScope);
|
|
2179
|
-
unhandledChildren.delete(funcScope);
|
|
2180
|
-
}
|
|
2181
|
-
break;
|
|
2182
|
-
}
|
|
2183
|
-
}
|
|
2184
|
-
name ??= model.getValueInRange(definition.range);
|
|
2185
|
-
kind ??= name.startsWith("@") ? languages.SymbolKind.Constant : languages.SymbolKind.Variable;
|
|
2186
|
-
symbols.push({
|
|
2187
|
-
name,
|
|
2188
|
-
detail: "",
|
|
2189
|
-
kind,
|
|
2190
|
-
range: allRange,
|
|
2191
|
-
tags: [],
|
|
2192
|
-
selectionRange: range,
|
|
2193
|
-
children
|
|
2194
|
-
});
|
|
2195
|
-
}
|
|
2196
|
-
for (const child of unhandledChildren) {
|
|
2197
|
-
symbols.push(...this.handleScope(model, child));
|
|
2198
|
-
}
|
|
2199
|
-
return symbols;
|
|
2200
|
-
}
|
|
2201
|
-
/** @inheritdoc */
|
|
2202
|
-
async provideDocumentSymbols(model, token) {
|
|
2203
|
-
const compiled = await this.getCompileResult(model);
|
|
2204
|
-
if (!compiled) return void 0;
|
|
2205
|
-
const root = compiled.scopes(model)[0];
|
|
2206
|
-
if (!root) return void 0;
|
|
2207
|
-
return this.handleScope(model, root);
|
|
2208
|
-
}
|
|
2209
|
-
};
|
|
2210
|
-
|
|
2211
|
-
// src/lsp/providers/formatter-provider.ts
|
|
2212
|
-
async function format(model, ranges, options, hint, token) {
|
|
2213
|
-
if (hint !== "full") return [];
|
|
2214
|
-
const compiled = await Provider.getCompileResult(model);
|
|
2215
|
-
if (compiled?.result.formatted == null) return [];
|
|
2216
|
-
return [
|
|
2217
|
-
{
|
|
2218
|
-
range: model.getFullModelRange(),
|
|
2219
|
-
text: compiled.result.formatted
|
|
2220
|
-
}
|
|
2221
|
-
];
|
|
2222
|
-
}
|
|
2223
|
-
var FormatterProvider = class extends Provider {
|
|
2224
|
-
constructor() {
|
|
2225
|
-
super(...arguments);
|
|
2226
|
-
/** @inheritdoc */
|
|
2227
|
-
this.autoFormatTriggerCharacters = [";", "}", "]", ")"];
|
|
2228
|
-
}
|
|
2229
|
-
/** 进行完整格式化 */
|
|
2230
|
-
static async format(model, options) {
|
|
2231
|
-
const formatted = await format(model, [], options, "full", void 0);
|
|
2232
|
-
return formatted.length === 1 ? formatted[0].text : null;
|
|
2233
|
-
}
|
|
2234
|
-
/** @inheritdoc */
|
|
2235
|
-
provideDocumentFormattingEdits(model, options, token) {
|
|
2236
|
-
return format(model, [], options, "full", token);
|
|
2237
|
-
}
|
|
2238
|
-
/** @inheritdoc */
|
|
2239
|
-
provideDocumentRangeFormattingEdits(model, range, options, token) {
|
|
2240
|
-
return format(model, [range], options, "range", token);
|
|
2241
|
-
}
|
|
2242
|
-
/** @inheritdoc */
|
|
2243
|
-
provideDocumentRangesFormattingEdits(model, ranges, options, token) {
|
|
2244
|
-
return format(model, ranges, options, "range", token);
|
|
2245
|
-
}
|
|
2246
|
-
/** @inheritdoc */
|
|
2247
|
-
provideOnTypeFormattingEdits(model, position, ch, options, token) {
|
|
2248
|
-
return format(
|
|
2249
|
-
model,
|
|
2250
|
-
[Range.fromPositions(position, position)],
|
|
2251
|
-
options,
|
|
2252
|
-
ch === ";" ? "statement" : "expression",
|
|
2253
|
-
token
|
|
2254
|
-
);
|
|
2255
|
-
}
|
|
2256
|
-
};
|
|
2257
|
-
|
|
2258
|
-
// src/lsp/providers/hover-provider.ts
|
|
2259
|
-
import { DiagnosticCode as DiagnosticCode10 } from "@mirascript/constants";
|
|
2260
|
-
import { convert } from "@mirascript/mirascript/subtle";
|
|
2261
|
-
import { KEYWORDS as HELP_KEYWORDS2, OPERATORS as HELP_OPERATORS } from "@mirascript/help";
|
|
2262
|
-
|
|
2263
|
-
// src/lsp/monaco-private.js
|
|
2264
|
-
function fromStandardTokenType(tokenType) {
|
|
2265
|
-
switch (tokenType) {
|
|
2266
|
-
case 1:
|
|
2267
|
-
return "comment";
|
|
2268
|
-
case 2:
|
|
2269
|
-
return "string";
|
|
2270
|
-
case 3:
|
|
2271
|
-
return "regex";
|
|
2272
|
-
default:
|
|
2273
|
-
return "other";
|
|
2274
|
-
}
|
|
2275
|
-
}
|
|
2276
|
-
function tokenAt(model, position) {
|
|
2277
|
-
try {
|
|
2278
|
-
let tryGetTokenProp2 = function(method, fallback) {
|
|
2279
|
-
try {
|
|
2280
|
-
return lineTokens[method](tokenIndex);
|
|
2281
|
-
} catch {
|
|
2282
|
-
return fallback;
|
|
2283
|
-
}
|
|
2284
|
-
};
|
|
2285
|
-
var tryGetTokenProp = tryGetTokenProp2;
|
|
2286
|
-
const lineTokens = model.tokenization.getLineTokens(position.lineNumber);
|
|
2287
|
-
const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
|
|
2288
|
-
if (tokenIndex < 0) return void 0;
|
|
2289
|
-
return {
|
|
2290
|
-
type: fromStandardTokenType(tryGetTokenProp2("getStandardTokenType", 0)),
|
|
2291
|
-
text: tryGetTokenProp2("getTokenText", null),
|
|
2292
|
-
startColumn: tryGetTokenProp2("getStartOffset", 0) + 1,
|
|
2293
|
-
endColumn: tryGetTokenProp2("getEndOffset", 0) + 1
|
|
2294
|
-
};
|
|
2295
|
-
} catch {
|
|
2296
|
-
return void 0;
|
|
2297
|
-
}
|
|
2298
|
-
}
|
|
2299
|
-
|
|
2300
|
-
// src/lsp/providers/hover-provider.ts
|
|
2301
|
-
var OPERATOR_TOKENS_DESC = Object.keys(HELP_OPERATORS).sort((a, b) => b.length - a.length);
|
|
2302
|
-
var REG_NUMBER_ALL_FULL = new RegExp(
|
|
2303
|
-
`^(?:${REG_BIN.source}|${REG_OCT.source}|${REG_HEX.source}|${REG_NUMBER.source})$`,
|
|
2304
|
-
REG_NUMBER.flags
|
|
2305
|
-
);
|
|
2306
|
-
var BIN_MAX = 2 ** 32 - 1;
|
|
2307
|
-
var OCT_MAX = 8 ** 18 - 1;
|
|
2308
|
-
var HEX_MAX = 16 ** 16 - 1;
|
|
2309
|
-
function operatorAt(lineContent, column) {
|
|
2310
|
-
const index = Math.max(0, column - 1);
|
|
2311
|
-
for (const token of OPERATOR_TOKENS_DESC) {
|
|
2312
|
-
for (let offset = 0; offset < token.length; offset++) {
|
|
2313
|
-
const start = index - offset;
|
|
2314
|
-
if (start < 0) continue;
|
|
2315
|
-
const end = start + token.length;
|
|
2316
|
-
if (end > lineContent.length) continue;
|
|
2317
|
-
if (lineContent.slice(start, end) !== token) continue;
|
|
2318
|
-
if (index < start || index >= end) continue;
|
|
2319
|
-
return {
|
|
2320
|
-
token,
|
|
2321
|
-
range: {
|
|
2322
|
-
startLineNumber: 0,
|
|
2323
|
-
startColumn: start + 1,
|
|
2324
|
-
endLineNumber: 0,
|
|
2325
|
-
endColumn: end + 1
|
|
2326
|
-
}
|
|
2327
|
-
};
|
|
2328
|
-
}
|
|
2329
|
-
}
|
|
2330
|
-
return void 0;
|
|
2331
|
-
}
|
|
2332
|
-
var HoverProvider = class extends Provider {
|
|
2333
|
-
/** 变量提示 */
|
|
2334
|
-
async provideVariableHover(model, { def, ref }) {
|
|
2335
|
-
const contents = [];
|
|
2336
|
-
let range;
|
|
2337
|
-
if ("name" in def) {
|
|
2338
|
-
const globals = await this.getContext(model);
|
|
2339
|
-
const value = globals.getOrUndefined(def.name);
|
|
2340
|
-
const { script, doc } = valueDoc(def.name, value, "hint", globals);
|
|
2341
|
-
contents.push({ value: codeblock(`\0(global) ${script}`) });
|
|
2342
|
-
for (const d of doc) {
|
|
2343
|
-
contents.push({ value: d });
|
|
2344
|
-
}
|
|
2345
|
-
range = def.references[ref]?.range;
|
|
2346
|
-
} else {
|
|
2347
|
-
let content;
|
|
2348
|
-
const tag = def.definition;
|
|
2349
|
-
switch (tag.code) {
|
|
2350
|
-
case DiagnosticCode10.ParameterSubPatternImmutable:
|
|
2351
|
-
content = {
|
|
2352
|
-
value: codeblock(`\0(parameter pattern) ${model.getValueInRange(tag.range)}`)
|
|
2353
|
-
};
|
|
2354
|
-
break;
|
|
2355
|
-
case DiagnosticCode10.ParameterSubPatternMutable:
|
|
2356
|
-
content = {
|
|
2357
|
-
value: codeblock(`\0(parameter pattern) mut ${model.getValueInRange(tag.range)}`)
|
|
2358
|
-
};
|
|
2359
|
-
break;
|
|
2360
|
-
case DiagnosticCode10.ParameterImmutable:
|
|
2361
|
-
content = {
|
|
2362
|
-
value: codeblock(`\0(parameter) ${model.getValueInRange(tag.range)}`)
|
|
2363
|
-
};
|
|
2364
|
-
break;
|
|
2365
|
-
case DiagnosticCode10.ParameterMutable:
|
|
2366
|
-
content = {
|
|
2367
|
-
value: codeblock(`\0(parameter) mut ${model.getValueInRange(tag.range)}`)
|
|
2368
|
-
};
|
|
2369
|
-
break;
|
|
2370
|
-
case DiagnosticCode10.ParameterIt:
|
|
2371
|
-
content = {
|
|
2372
|
-
value: codeblock(`\0(parameter) it`)
|
|
2373
|
-
};
|
|
2374
|
-
break;
|
|
2375
|
-
case DiagnosticCode10.ParameterImmutableRest:
|
|
2376
|
-
content = {
|
|
2377
|
-
value: codeblock(`\0(parameter) ..${model.getValueInRange(tag.range)}`)
|
|
2378
|
-
};
|
|
2379
|
-
break;
|
|
2380
|
-
case DiagnosticCode10.ParameterMutableRest:
|
|
2381
|
-
content = {
|
|
2382
|
-
value: codeblock(`\0(parameter) ..mut ${model.getValueInRange(tag.range)}`)
|
|
2383
|
-
};
|
|
2384
|
-
break;
|
|
2385
|
-
case DiagnosticCode10.LocalFunction: {
|
|
2386
|
-
const params = paramsList(model, def.fn);
|
|
2387
|
-
content = {
|
|
2388
|
-
value: codeblock(`\0fn ${model.getValueInRange(tag.range)}${params}`)
|
|
2389
|
-
};
|
|
2390
|
-
break;
|
|
2391
|
-
}
|
|
2392
|
-
case DiagnosticCode10.LocalModule:
|
|
2393
|
-
content = {
|
|
2394
|
-
value: codeblock(`\0mod ${model.getValueInRange(tag.range)}`)
|
|
2395
|
-
};
|
|
2396
|
-
break;
|
|
2397
|
-
case DiagnosticCode10.LocalImmutable:
|
|
2398
|
-
content = {
|
|
2399
|
-
value: codeblock(`\0let ${model.getValueInRange(tag.range)}`)
|
|
2400
|
-
};
|
|
2401
|
-
break;
|
|
2402
|
-
case DiagnosticCode10.LocalConst:
|
|
2403
|
-
content = {
|
|
2404
|
-
value: codeblock(`\0const ${model.getValueInRange(tag.range)}`)
|
|
2405
|
-
};
|
|
2406
|
-
break;
|
|
2407
|
-
case DiagnosticCode10.LocalMutable:
|
|
2408
|
-
content = {
|
|
2409
|
-
value: codeblock(`\0let mut ${model.getValueInRange(tag.range)}`)
|
|
2410
|
-
};
|
|
2411
|
-
break;
|
|
2412
|
-
}
|
|
2413
|
-
if (ref == null) {
|
|
2414
|
-
range = tag.range;
|
|
2415
|
-
} else {
|
|
2416
|
-
range = def.references[ref]?.range;
|
|
2417
|
-
}
|
|
2418
|
-
if (content) {
|
|
2419
|
-
contents.push(content);
|
|
2420
|
-
}
|
|
2421
|
-
}
|
|
2422
|
-
if (!contents.length) return void 0;
|
|
2423
|
-
return {
|
|
2424
|
-
contents,
|
|
2425
|
-
range
|
|
2426
|
-
};
|
|
2427
|
-
}
|
|
2428
|
-
/** 字段提示 */
|
|
2429
|
-
async provideFieldHover(model, range, { def: { def, ref }, fields }) {
|
|
2430
|
-
if ("definition" in def) {
|
|
2431
|
-
return void 0;
|
|
2432
|
-
}
|
|
2433
|
-
const vmGlobal = await this.getContext(model);
|
|
2434
|
-
const lastField = fields.at(-1);
|
|
2435
|
-
const [obj, value] = getDeep(vmGlobal, def.name, fields);
|
|
2436
|
-
if (value == null) return void 0;
|
|
2437
|
-
const { script, doc } = valueDoc(lastField, value, "field", obj);
|
|
2438
|
-
return {
|
|
2439
|
-
contents: [{ value: codeblock(`\0(field) ${script}`) }, ...doc.map((d) => ({ value: d }))],
|
|
2440
|
-
range
|
|
2441
|
-
};
|
|
2442
|
-
}
|
|
2443
|
-
/** 语法元素提示 */
|
|
2444
|
-
provideSyntaxHover(model, position) {
|
|
2445
|
-
const token = tokenAt(model, position);
|
|
2446
|
-
if (token?.type && token.type !== "other") {
|
|
2447
|
-
return void 0;
|
|
2448
|
-
}
|
|
2449
|
-
if (token?.text) {
|
|
2450
|
-
if (token.text in HELP_KEYWORDS2) {
|
|
2451
|
-
const doc = HELP_KEYWORDS2[token.text];
|
|
2452
|
-
return {
|
|
2453
|
-
contents: [{ value: doc }],
|
|
2454
|
-
range: rangeAt(position, token)
|
|
2455
|
-
};
|
|
2456
|
-
}
|
|
2457
|
-
if (token.text in HELP_OPERATORS) {
|
|
2458
|
-
const doc = HELP_OPERATORS[token.text];
|
|
2459
|
-
return {
|
|
2460
|
-
contents: [{ value: doc }],
|
|
2461
|
-
range: rangeAt(position, token)
|
|
2462
|
-
};
|
|
2463
|
-
}
|
|
2464
|
-
if (REG_NUMBER_ALL_FULL.test(token.text)) {
|
|
2465
|
-
const num = convert.toNumber(token.text.replaceAll("_", ""), null);
|
|
2466
|
-
if (num == null) return void 0;
|
|
2467
|
-
const contents = [];
|
|
2468
|
-
if (!token.text.includes(".") && !token.text.includes("e") && !token.text.includes("E") && Number.isInteger(num)) {
|
|
2469
|
-
contents.push(`\0(dec) ` + serializeNumber(num));
|
|
2470
|
-
const abs = Math.abs(num);
|
|
2471
|
-
if (abs <= BIN_MAX) {
|
|
2472
|
-
contents.push("\0(bin) " + serializeInteger(num, 2));
|
|
2473
|
-
}
|
|
2474
|
-
if (abs <= OCT_MAX) {
|
|
2475
|
-
contents.push("\0(oct) " + serializeInteger(num, 8));
|
|
2476
|
-
}
|
|
2477
|
-
if (abs <= HEX_MAX) {
|
|
2478
|
-
contents.push("\0(hex) " + serializeInteger(num, 16));
|
|
2479
|
-
}
|
|
2480
|
-
} else {
|
|
2481
|
-
contents.push(`\0(number) ` + serializeNumber(num));
|
|
2482
|
-
}
|
|
2483
|
-
return {
|
|
2484
|
-
contents: [{ value: codeblock(contents.join("\n")) }],
|
|
2485
|
-
range: rangeAt(position, token)
|
|
2486
|
-
};
|
|
2487
|
-
}
|
|
2488
|
-
}
|
|
2489
|
-
const word = model.getWordAtPosition(position);
|
|
2490
|
-
if (word?.word && word.word in HELP_KEYWORDS2) {
|
|
2491
|
-
const doc = HELP_KEYWORDS2[word.word];
|
|
2492
|
-
return {
|
|
2493
|
-
contents: [{ value: doc }],
|
|
2494
|
-
range: rangeAt(position, word)
|
|
2495
|
-
};
|
|
2496
|
-
}
|
|
2497
|
-
const lineContent = model.getLineContent(position.lineNumber);
|
|
2498
|
-
const hit = operatorAt(lineContent, position.column);
|
|
2499
|
-
if (hit && hit.token in HELP_OPERATORS) {
|
|
2500
|
-
const doc = HELP_OPERATORS[hit.token];
|
|
2501
|
-
return {
|
|
2502
|
-
contents: [{ value: doc }],
|
|
2503
|
-
range: rangeAt(position, hit.range)
|
|
2504
|
-
};
|
|
2505
|
-
}
|
|
2506
|
-
return void 0;
|
|
2507
|
-
}
|
|
2508
|
-
/** @inheritdoc */
|
|
2509
|
-
async provideHover(model, position, token, context) {
|
|
2510
|
-
const value = await this.getValueAt(model, position);
|
|
2511
|
-
if (!value) {
|
|
2512
|
-
return this.provideSyntaxHover(model, position);
|
|
2513
|
-
} else if ("fields" in value) {
|
|
2514
|
-
return this.provideFieldHover(model, value.range, value.fields);
|
|
2515
|
-
} else {
|
|
2516
|
-
return this.provideVariableHover(model, value.variable);
|
|
2517
|
-
}
|
|
2518
|
-
}
|
|
2519
|
-
};
|
|
2520
|
-
|
|
2521
|
-
// src/lsp/providers/inlay-hints-provider.ts
|
|
2522
|
-
import { DiagnosticCode as DiagnosticCode11 } from "@mirascript/constants";
|
|
2523
|
-
var InlayHintsProvider = class extends Provider {
|
|
2524
|
-
/** @inheritdoc */
|
|
2525
|
-
get onDidChangeInlayHints() {
|
|
2526
|
-
return this.onDidChange;
|
|
2527
|
-
}
|
|
2528
|
-
/** @inheritdoc */
|
|
2529
|
-
async provideInlayHints(model, range, token) {
|
|
2530
|
-
const compiled = await this.getCompileResult(model);
|
|
2531
|
-
if (!compiled) {
|
|
2532
|
-
return void 0;
|
|
2533
|
-
}
|
|
2534
|
-
const hints = [];
|
|
2535
|
-
for (const tag of compiled.tags) {
|
|
2536
|
-
if (!range.containsRange(tag.range)) {
|
|
2537
|
-
continue;
|
|
2538
|
-
}
|
|
2539
|
-
let lineNumber = 0;
|
|
2540
|
-
let column = 0;
|
|
2541
|
-
let label = "";
|
|
2542
|
-
const kind = languages.InlayHintKind.Parameter;
|
|
2543
|
-
let paddingLeft = true;
|
|
2544
|
-
let paddingRight = false;
|
|
2545
|
-
const edits = [];
|
|
2546
|
-
switch (tag.code) {
|
|
2547
|
-
case DiagnosticCode11.ParameterIt: {
|
|
2548
|
-
if (!tag.references.length) {
|
|
2549
|
-
continue;
|
|
2550
|
-
}
|
|
2551
|
-
lineNumber = tag.range.endLineNumber;
|
|
2552
|
-
column = tag.range.endColumn;
|
|
2553
|
-
label = "(it)";
|
|
2554
|
-
paddingLeft = /\bfn$/u.test(
|
|
2555
|
-
model.getValueInRange(new Range(lineNumber, column - 3, lineNumber, column))
|
|
2556
|
-
);
|
|
2557
|
-
paddingRight = model.getValueInRange(new Range(lineNumber, column, lineNumber, column + 1)) === "{";
|
|
2558
|
-
edits.push({
|
|
2559
|
-
range: new Range(lineNumber, column, lineNumber, column),
|
|
2560
|
-
text: `${paddingLeft ? " " : ""}${label}${paddingRight ? " " : ""}`
|
|
2561
|
-
});
|
|
2562
|
-
break;
|
|
2563
|
-
}
|
|
2564
|
-
case DiagnosticCode11.UnnamedRecordField0:
|
|
2565
|
-
case DiagnosticCode11.UnnamedRecordField1:
|
|
2566
|
-
case DiagnosticCode11.UnnamedRecordField2:
|
|
2567
|
-
case DiagnosticCode11.UnnamedRecordField3:
|
|
2568
|
-
case DiagnosticCode11.UnnamedRecordField4:
|
|
2569
|
-
case DiagnosticCode11.UnnamedRecordField5:
|
|
2570
|
-
case DiagnosticCode11.UnnamedRecordField6:
|
|
2571
|
-
case DiagnosticCode11.UnnamedRecordField7:
|
|
2572
|
-
case DiagnosticCode11.UnnamedRecordField8:
|
|
2573
|
-
case DiagnosticCode11.UnnamedRecordField9:
|
|
2574
|
-
case DiagnosticCode11.UnnamedRecordFieldN: {
|
|
2575
|
-
const index = tag.code - DiagnosticCode11.UnnamedRecordField0;
|
|
2576
|
-
if (index > 9) break;
|
|
2577
|
-
lineNumber = tag.range.startLineNumber;
|
|
2578
|
-
column = tag.range.startColumn;
|
|
2579
|
-
label = `${index}:`;
|
|
2580
|
-
paddingLeft = /[^\s(]/u.test(
|
|
2581
|
-
model.getValueInRange(new Range(lineNumber, column - 1, lineNumber, column))
|
|
2582
|
-
);
|
|
2583
|
-
paddingRight = true;
|
|
2584
|
-
break;
|
|
2585
|
-
}
|
|
2586
|
-
case DiagnosticCode11.OmitNamedRecordField: {
|
|
2587
|
-
const ref = tag.references[0];
|
|
2588
|
-
if (ref?.code !== DiagnosticCode11.OmitNamedRecordFieldName) continue;
|
|
2589
|
-
lineNumber = tag.range.startLineNumber;
|
|
2590
|
-
column = tag.range.startColumn;
|
|
2591
|
-
label = model.getValueInRange(ref.range);
|
|
2592
|
-
paddingLeft = /[^\s(]/u.test(
|
|
2593
|
-
model.getValueInRange(new Range(lineNumber, column - 1, lineNumber, column))
|
|
2594
|
-
);
|
|
2595
|
-
paddingRight = false;
|
|
2596
|
-
const insertRight = !/\s/u.test(
|
|
2597
|
-
model.getValueInRange(
|
|
2598
|
-
new Range(
|
|
2599
|
-
tag.range.endLineNumber,
|
|
2600
|
-
tag.range.endColumn,
|
|
2601
|
-
tag.range.endLineNumber,
|
|
2602
|
-
tag.range.endColumn + 1
|
|
2603
|
-
)
|
|
2604
|
-
)
|
|
2605
|
-
);
|
|
2606
|
-
edits.push({
|
|
2607
|
-
range: tag.range,
|
|
2608
|
-
text: `${paddingLeft ? " " : ""}${label}${model.getValueInRange(tag.range)}${insertRight ? " " : ""}`
|
|
2609
|
-
});
|
|
2610
|
-
break;
|
|
2611
|
-
}
|
|
2612
|
-
}
|
|
2613
|
-
if (!label) continue;
|
|
2614
|
-
const hint = {
|
|
2615
|
-
position: { lineNumber, column },
|
|
2616
|
-
label,
|
|
2617
|
-
kind,
|
|
2618
|
-
paddingLeft,
|
|
2619
|
-
paddingRight,
|
|
2620
|
-
textEdits: edits
|
|
2621
|
-
};
|
|
2622
|
-
hints.push(hint);
|
|
2623
|
-
}
|
|
2624
|
-
return {
|
|
2625
|
-
hints,
|
|
2626
|
-
dispose: () => {
|
|
2627
|
-
}
|
|
2628
|
-
};
|
|
2629
|
-
}
|
|
2630
|
-
};
|
|
2631
|
-
|
|
2632
|
-
// src/lsp/providers/range-provider.ts
|
|
2633
|
-
var RangeProvider = class extends Provider {
|
|
2634
|
-
/** @inheritdoc */
|
|
2635
|
-
async provideFoldingRanges(model, context, token) {
|
|
2636
|
-
const compiled = await this.getCompileResult(model);
|
|
2637
|
-
if (!compiled) return void 0;
|
|
2638
|
-
return void 0;
|
|
2639
|
-
}
|
|
2640
|
-
/** @inheritdoc */
|
|
2641
|
-
async provideSelectionRanges(model, positions, token) {
|
|
2642
|
-
const compiled = await this.getCompileResult(model);
|
|
2643
|
-
if (!compiled) return void 0;
|
|
2644
|
-
const { ranges } = compiled.groupedTags(model);
|
|
2645
|
-
return positions.map((pos) => {
|
|
2646
|
-
return ranges.filter((r) => Range.containsPosition(r.range, pos)).map((t) => ({
|
|
2647
|
-
range: t.range
|
|
2648
|
-
}));
|
|
2649
|
-
});
|
|
2650
|
-
}
|
|
2651
|
-
};
|
|
2652
|
-
|
|
2653
|
-
// src/lsp/providers/rename-provider.ts
|
|
2654
|
-
import { DiagnosticCode as DiagnosticCode12 } from "@mirascript/constants";
|
|
2655
|
-
var RenameProvider = class extends Provider {
|
|
2656
|
-
/** 重命名推断字段 */
|
|
2657
|
-
provideRenameEditsOmitNameFields(model, compiled, edits, ref, oldName) {
|
|
2658
|
-
const { omitNameFields } = compiled.groupedTags(model);
|
|
2659
|
-
for (const tag of omitNameFields) {
|
|
2660
|
-
if (Range.equalsRange(tag.references[0]?.range, ref.range)) {
|
|
2661
|
-
const current = model.getValueInRange(tag.range);
|
|
2662
|
-
const paddingLeft = /[^\s(]/u.test(
|
|
2663
|
-
model.getValueInRange({
|
|
2664
|
-
startLineNumber: tag.range.startLineNumber,
|
|
2665
|
-
startColumn: tag.range.startColumn - 1,
|
|
2666
|
-
endLineNumber: tag.range.startLineNumber,
|
|
2667
|
-
endColumn: tag.range.startColumn
|
|
2668
|
-
})
|
|
2669
|
-
);
|
|
2670
|
-
const paddingRight = !/\s/u.test(
|
|
2671
|
-
model.getValueInRange({
|
|
2672
|
-
startLineNumber: tag.range.endLineNumber,
|
|
2673
|
-
startColumn: tag.range.endColumn,
|
|
2674
|
-
endLineNumber: tag.range.endLineNumber,
|
|
2675
|
-
endColumn: tag.range.endColumn + 1
|
|
2676
|
-
})
|
|
2677
|
-
);
|
|
2678
|
-
edits.push({
|
|
2679
|
-
resource: model.uri,
|
|
2680
|
-
versionId: compiled.version,
|
|
2681
|
-
textEdit: {
|
|
2682
|
-
range: tag.range,
|
|
2683
|
-
text: `${paddingLeft ? " " : ""}${oldName}${current}${paddingRight ? " " : ""}`
|
|
2684
|
-
}
|
|
2685
|
-
});
|
|
2686
|
-
}
|
|
2687
|
-
}
|
|
2688
|
-
}
|
|
2689
|
-
/** @inheritdoc */
|
|
2690
|
-
async provideRenameEdits(model, position, newName, token) {
|
|
2691
|
-
newName = newName.trim();
|
|
2692
|
-
const compiled = await this.getCompileResult(model);
|
|
2693
|
-
if (!compiled) return void 0;
|
|
2694
|
-
const d = compiled.variableAccessAt(model, position);
|
|
2695
|
-
if (!d) return void 0;
|
|
2696
|
-
const edits = [];
|
|
2697
|
-
const { references } = d.def;
|
|
2698
|
-
let oldName;
|
|
2699
|
-
if ("definition" in d.def) {
|
|
2700
|
-
edits.push({
|
|
2701
|
-
resource: model.uri,
|
|
2702
|
-
versionId: compiled.version,
|
|
2703
|
-
textEdit: {
|
|
2704
|
-
range: d.def.definition.range,
|
|
2705
|
-
text: d.def.definition.code === DiagnosticCode12.ParameterIt ? `(${newName})` : newName
|
|
2706
|
-
}
|
|
2707
|
-
});
|
|
2708
|
-
oldName = model.getValueInRange(d.def.definition.range);
|
|
2709
|
-
this.provideRenameEditsOmitNameFields(model, compiled, edits, d.def.definition, oldName);
|
|
2710
|
-
} else {
|
|
2711
|
-
oldName = d.def.name;
|
|
2712
|
-
}
|
|
2713
|
-
for (const ref of references) {
|
|
2714
|
-
edits.push({
|
|
2715
|
-
resource: model.uri,
|
|
2716
|
-
versionId: compiled.version,
|
|
2717
|
-
textEdit: {
|
|
2718
|
-
range: ref.range,
|
|
2719
|
-
text: newName
|
|
2720
|
-
}
|
|
2721
|
-
});
|
|
2722
|
-
this.provideRenameEditsOmitNameFields(model, compiled, edits, ref, oldName);
|
|
2723
|
-
}
|
|
2724
|
-
const { globals } = compiled.groupedTags(model);
|
|
2725
|
-
const globalWithSameName = globals.find((g) => g.name === newName);
|
|
2726
|
-
if (globalWithSameName) {
|
|
2727
|
-
for (const ref of globalWithSameName.references) {
|
|
2728
|
-
edits.push({
|
|
2729
|
-
resource: model.uri,
|
|
2730
|
-
versionId: compiled.version,
|
|
2731
|
-
textEdit: {
|
|
2732
|
-
range: ref.range,
|
|
2733
|
-
text: `global.${newName}`
|
|
2734
|
-
}
|
|
2735
|
-
});
|
|
2736
|
-
this.provideRenameEditsOmitNameFields(model, compiled, edits, ref, oldName);
|
|
2737
|
-
}
|
|
2738
|
-
}
|
|
2739
|
-
return { edits };
|
|
2740
|
-
}
|
|
2741
|
-
/** @inheritdoc */
|
|
2742
|
-
async resolveRenameLocation(model, position, token) {
|
|
2743
|
-
const compiled = await this.getCompileResult(model);
|
|
2744
|
-
if (!compiled) return void 0;
|
|
2745
|
-
const d = compiled.variableAccessAt(model, position);
|
|
2746
|
-
if (!d) {
|
|
2747
|
-
return {
|
|
2748
|
-
range: Range.fromPositions(position),
|
|
2749
|
-
text: "",
|
|
2750
|
-
rejectReason: "Cannot rename this element"
|
|
2751
|
-
};
|
|
2752
|
-
}
|
|
2753
|
-
const { def, ref } = d;
|
|
2754
|
-
if ("name" in def) {
|
|
2755
|
-
return {
|
|
2756
|
-
range: def.references[ref]?.range ?? Range.fromPositions(position),
|
|
2757
|
-
text: def.name,
|
|
2758
|
-
rejectReason: "Cannot rename global variables"
|
|
2759
|
-
};
|
|
2760
|
-
}
|
|
2761
|
-
const tag = ref == null ? def.definition : def.references[ref];
|
|
2762
|
-
return {
|
|
2763
|
-
range: tag.range,
|
|
2764
|
-
text: model.getValueInRange(tag.range) ?? ""
|
|
2765
|
-
};
|
|
2766
|
-
}
|
|
2767
|
-
};
|
|
2768
|
-
|
|
2769
|
-
// src/lsp/providers/semantic-tokens-provider.ts
|
|
2770
|
-
import { isVmFunction as isVmFunction2, isVmModule as isVmModule3 } from "@mirascript/mirascript";
|
|
2771
|
-
import { DiagnosticCode as DiagnosticCode13 } from "@mirascript/constants";
|
|
2772
|
-
var TOKEN_TYPES = {
|
|
2773
|
-
[0 /* VARIABLE */]: "variable.other.constant",
|
|
2774
|
-
[1 /* VARIABLE_MUTABLE */]: "variable",
|
|
2775
|
-
[2 /* CONSTANT */]: "variable.other.constant",
|
|
2776
|
-
[3 /* GLOBAL */]: "variable",
|
|
2777
|
-
[4 /* FUNCTION */]: "entity.name.function",
|
|
2778
|
-
[5 /* MODULE */]: "type",
|
|
2779
|
-
[6 /* PROPERTY */]: "variable.other.property",
|
|
2780
|
-
[7 /* KEYWORD_CONTROL */]: "keyword.flow",
|
|
2781
|
-
[8 /* PARAM */]: "variable.other.constant.emphasis",
|
|
2782
|
-
[9 /* PARAM_MUTABLE */]: "variable.emphasis"
|
|
2783
|
-
};
|
|
2784
|
-
var DocumentSemanticTokensProvider = class extends Provider {
|
|
2785
|
-
/** @inheritdoc */
|
|
2786
|
-
getLegend() {
|
|
2787
|
-
const tokenTypes = Object.values(TOKEN_TYPES);
|
|
2788
|
-
return {
|
|
2789
|
-
tokenTypes,
|
|
2790
|
-
tokenModifiers: tokenTypes.map((_) => "")
|
|
2791
|
-
};
|
|
2792
|
-
}
|
|
2793
|
-
/** @inheritdoc */
|
|
2794
|
-
async provideDocumentSemanticTokens(model, lastResultId, token) {
|
|
2795
|
-
const resultId = `${model.uri.toString()}?${model.getVersionId()}`;
|
|
2796
|
-
const compiled = await this.getCompileResult(model);
|
|
2797
|
-
if (!compiled) {
|
|
2798
|
-
return void 0;
|
|
2799
|
-
}
|
|
2800
|
-
const globals = await this.getContext(model);
|
|
2801
|
-
const data = [];
|
|
2802
|
-
for (const { code, range, references } of compiled.tags) {
|
|
2803
|
-
let tokenType = -1;
|
|
2804
|
-
let onlyReferences = false;
|
|
2805
|
-
switch (code) {
|
|
2806
|
-
case DiagnosticCode13.GlobalVariable: {
|
|
2807
|
-
const id = model.getValueInRange(range);
|
|
2808
|
-
if (id.startsWith("@")) {
|
|
2809
|
-
tokenType = 2 /* CONSTANT */;
|
|
2810
|
-
} else {
|
|
2811
|
-
const val = globals.getOrUndefined(id);
|
|
2812
|
-
if (isVmFunction2(val)) {
|
|
2813
|
-
tokenType = 4 /* FUNCTION */;
|
|
2814
|
-
} else if (isVmModule3(val)) {
|
|
2815
|
-
tokenType = 5 /* MODULE */;
|
|
2816
|
-
} else {
|
|
2817
|
-
tokenType = 3 /* GLOBAL */;
|
|
2818
|
-
}
|
|
2819
|
-
}
|
|
2820
|
-
break;
|
|
2821
|
-
}
|
|
2822
|
-
case DiagnosticCode13.LocalFunction: {
|
|
2823
|
-
tokenType = 4 /* FUNCTION */;
|
|
2824
|
-
break;
|
|
2825
|
-
}
|
|
2826
|
-
case DiagnosticCode13.LocalModule: {
|
|
2827
|
-
tokenType = 5 /* MODULE */;
|
|
2828
|
-
break;
|
|
2829
|
-
}
|
|
2830
|
-
case DiagnosticCode13.ParameterMutable:
|
|
2831
|
-
case DiagnosticCode13.ParameterSubPatternMutable:
|
|
2832
|
-
case DiagnosticCode13.ParameterMutableRest: {
|
|
2833
|
-
tokenType = 9 /* PARAM_MUTABLE */;
|
|
2834
|
-
break;
|
|
2835
|
-
}
|
|
2836
|
-
case DiagnosticCode13.LocalMutable: {
|
|
2837
|
-
tokenType = 1 /* VARIABLE_MUTABLE */;
|
|
2838
|
-
break;
|
|
2839
|
-
}
|
|
2840
|
-
case DiagnosticCode13.ParameterIt: {
|
|
2841
|
-
tokenType = 8 /* PARAM */;
|
|
2842
|
-
onlyReferences = true;
|
|
2843
|
-
break;
|
|
2844
|
-
}
|
|
2845
|
-
case DiagnosticCode13.ParameterImmutable:
|
|
2846
|
-
case DiagnosticCode13.ParameterSubPatternImmutable:
|
|
2847
|
-
case DiagnosticCode13.ParameterImmutableRest: {
|
|
2848
|
-
tokenType = 8 /* PARAM */;
|
|
2849
|
-
break;
|
|
2850
|
-
}
|
|
2851
|
-
case DiagnosticCode13.LocalImmutable: {
|
|
2852
|
-
tokenType = 0 /* VARIABLE */;
|
|
2853
|
-
break;
|
|
2854
|
-
}
|
|
2855
|
-
case DiagnosticCode13.LocalConst: {
|
|
2856
|
-
tokenType = 2 /* CONSTANT */;
|
|
2857
|
-
break;
|
|
2858
|
-
}
|
|
2859
|
-
// case DiagnosticCode.RecordFieldStringName:
|
|
2860
|
-
case DiagnosticCode13.RecordFieldOrdinalName:
|
|
2861
|
-
case DiagnosticCode13.RecordFieldIdName: {
|
|
2862
|
-
tokenType = 6 /* PROPERTY */;
|
|
2863
|
-
break;
|
|
2864
|
-
}
|
|
2865
|
-
case DiagnosticCode13.ForExpression: {
|
|
2866
|
-
tokenType = 7 /* KEYWORD_CONTROL */;
|
|
2867
|
-
onlyReferences = true;
|
|
2868
|
-
break;
|
|
2869
|
-
}
|
|
2870
|
-
}
|
|
2871
|
-
if (tokenType < 0) continue;
|
|
2872
|
-
const { startLineNumber, startColumn, endColumn } = range;
|
|
2873
|
-
const length = endColumn - startColumn;
|
|
2874
|
-
if (!onlyReferences) {
|
|
2875
|
-
data.push({
|
|
2876
|
-
row: startLineNumber - 1,
|
|
2877
|
-
// 从 0 开始
|
|
2878
|
-
col: startColumn - 1,
|
|
2879
|
-
length,
|
|
2880
|
-
tokenType,
|
|
2881
|
-
tokenModifiers: 1 << tokenType
|
|
2882
|
-
});
|
|
2883
|
-
}
|
|
2884
|
-
for (const ref of references) {
|
|
2885
|
-
if (ref.code === DiagnosticCode13.ExportedLocal) {
|
|
2886
|
-
continue;
|
|
2887
|
-
}
|
|
2888
|
-
data.push({
|
|
2889
|
-
row: ref.range.startLineNumber - 1,
|
|
2890
|
-
col: ref.range.startColumn - 1,
|
|
2891
|
-
length: ref.range.endColumn - ref.range.startColumn,
|
|
2892
|
-
tokenType,
|
|
2893
|
-
tokenModifiers: 1 << tokenType
|
|
2894
|
-
});
|
|
2895
|
-
}
|
|
2896
|
-
}
|
|
2897
|
-
data.sort((a, b) => {
|
|
2898
|
-
if (a.row !== b.row) {
|
|
2899
|
-
return a.row - b.row;
|
|
2900
|
-
}
|
|
2901
|
-
return a.col - b.col;
|
|
2902
|
-
});
|
|
2903
|
-
const bin = new Uint32Array(data.length * 5);
|
|
2904
|
-
for (let i = 0; i < data.length; i++) {
|
|
2905
|
-
const current = data[i];
|
|
2906
|
-
let { row, col } = current;
|
|
2907
|
-
if (i > 0) {
|
|
2908
|
-
const prev = data[i - 1];
|
|
2909
|
-
row -= prev.row;
|
|
2910
|
-
if (row === 0) {
|
|
2911
|
-
col -= prev.col;
|
|
2912
|
-
}
|
|
2913
|
-
}
|
|
2914
|
-
bin.set([row, col, current.length, current.tokenType, current.tokenModifiers], i * 5);
|
|
2915
|
-
}
|
|
2916
|
-
return {
|
|
2917
|
-
resultId,
|
|
2918
|
-
data: bin
|
|
2919
|
-
};
|
|
2920
|
-
}
|
|
2921
|
-
/** @inheritdoc */
|
|
2922
|
-
releaseDocumentSemanticTokens(resultId) {
|
|
2923
|
-
}
|
|
2924
|
-
};
|
|
2925
|
-
|
|
2926
|
-
// src/lsp/providers/signature-help-provider.ts
|
|
2927
|
-
import { DiagnosticCode as DiagnosticCode14 } from "@mirascript/constants";
|
|
2928
|
-
import { getVmFunctionInfo as getVmFunctionInfo3 } from "@mirascript/mirascript";
|
|
2929
|
-
var SignatureHelpProvider = class extends Provider {
|
|
2930
|
-
constructor() {
|
|
2931
|
-
super(...arguments);
|
|
2932
|
-
/** @inheritdoc */
|
|
2933
|
-
this.signatureHelpTriggerCharacters = ["(", ","];
|
|
2934
|
-
/** @inheritdoc */
|
|
2935
|
-
this.signatureHelpRetriggerCharacters = [")"];
|
|
2936
|
-
}
|
|
2937
|
-
/** @inheritdoc */
|
|
2938
|
-
async provideSignatureHelp(model, position, token, context) {
|
|
2939
|
-
const compiled = await this.getCompileResult(model);
|
|
2940
|
-
if (!compiled) return void 0;
|
|
2941
|
-
const invokes = compiled.groupedTags(model).ranges.filter((r) => {
|
|
2942
|
-
if (r.code !== DiagnosticCode14.FunctionCall && r.code !== DiagnosticCode14.ExtensionCall) {
|
|
2943
|
-
return false;
|
|
2944
|
-
}
|
|
2945
|
-
if (!strictContainsPosition(r.range, position)) {
|
|
2946
|
-
return false;
|
|
2947
|
-
}
|
|
2948
|
-
const argStart = r.references.find((ref) => ref.code === DiagnosticCode14.ArgumentStart);
|
|
2949
|
-
const argEnd = r.references.find((ref) => ref.code === DiagnosticCode14.ArgumentEnd);
|
|
2950
|
-
if (!argStart || !argEnd) {
|
|
2951
|
-
return false;
|
|
2952
|
-
}
|
|
2953
|
-
return Range.containsPosition(
|
|
2954
|
-
Range.fromPositions(Range.getEndPosition(argStart.range), Range.getStartPosition(argEnd.range)),
|
|
2955
|
-
position
|
|
2956
|
-
);
|
|
2957
|
-
});
|
|
2958
|
-
if (!invokes.length) return void 0;
|
|
2959
|
-
invokes.sort((a, b) => Range.strictContainsRange(a.range, b.range) ? 1 : -1);
|
|
2960
|
-
const invoke = invokes[0];
|
|
2961
|
-
const callableRef = invoke.references.find((ref) => ref.code === DiagnosticCode14.Callable);
|
|
2962
|
-
if (!callableRef) return void 0;
|
|
2963
|
-
const callableInfo = compiled.accessAt(model, Range.getEndPosition(callableRef.range));
|
|
2964
|
-
if (!callableInfo) return void 0;
|
|
2965
|
-
let sig;
|
|
2966
|
-
if ("name" in callableInfo.def.def) {
|
|
2967
|
-
const { name } = callableInfo.def.def;
|
|
2968
|
-
const globals = await this.getContext(model);
|
|
2969
|
-
const [, callable] = getDeep(globals, name, callableInfo.fields);
|
|
2970
|
-
const info = getVmFunctionInfo3(callable);
|
|
2971
|
-
if (!info) return void 0;
|
|
2972
|
-
const fnName = callableInfo.fields.length ? callableInfo.fields.at(-1) : name;
|
|
2973
|
-
sig = { ...fnSignature(fnName, info), name: fnName, summary: info.summary };
|
|
2974
|
-
} else if (callableInfo.def.def.fn) {
|
|
2975
|
-
const { fn, definition } = callableInfo.def.def;
|
|
2976
|
-
const params = localParamSignature(model, fn);
|
|
2977
|
-
const name = model.getValueInRange(definition.range);
|
|
2978
|
-
sig = { params, returns: "", name, summary: "" };
|
|
2979
|
-
}
|
|
2980
|
-
if (!sig) return void 0;
|
|
2981
|
-
const signature = {
|
|
2982
|
-
label: "",
|
|
2983
|
-
parameters: []
|
|
2984
|
-
};
|
|
2985
|
-
if (invoke.code === DiagnosticCode14.ExtensionCall) {
|
|
2986
|
-
const thisArg = sig.params[0];
|
|
2987
|
-
if (thisArg && !thisArg[0].startsWith("..")) {
|
|
2988
|
-
sig.params.shift();
|
|
2989
|
-
const s = thisArg[1].includes(" ") ? `(${thisArg[1]})` : thisArg[1];
|
|
2990
|
-
signature.label = `fn ${s}::${sig.name}(`;
|
|
2991
|
-
} else {
|
|
2992
|
-
signature.label = `fn ()::${sig.name}(`;
|
|
2993
|
-
}
|
|
2994
|
-
} else {
|
|
2995
|
-
signature.label = `fn ${sig.name}(`;
|
|
2996
|
-
}
|
|
2997
|
-
signature.documentation = { value: sig.summary ?? "" };
|
|
2998
|
-
for (let i = 0; i < sig.params.length; i++) {
|
|
2999
|
-
const [_, p, doc] = sig.params[i];
|
|
3000
|
-
const start = signature.label.length;
|
|
3001
|
-
signature.parameters.push({
|
|
3002
|
-
label: [start, start + p.length],
|
|
3003
|
-
documentation: { value: doc }
|
|
3004
|
-
});
|
|
3005
|
-
if (i === sig.params.length - 1) {
|
|
3006
|
-
signature.label += p;
|
|
3007
|
-
} else {
|
|
3008
|
-
signature.label += p + ", ";
|
|
3009
|
-
}
|
|
3010
|
-
}
|
|
3011
|
-
signature.label += ")" + sig.returns;
|
|
3012
|
-
let pos = 0;
|
|
3013
|
-
for (const ref of invoke.references) {
|
|
3014
|
-
if (ref.code === DiagnosticCode14.ArgumentSpread) pos = Number.NaN;
|
|
3015
|
-
if (ref.code !== DiagnosticCode14.ArgumentComma || Range.isEmpty(ref.range)) continue;
|
|
3016
|
-
if (Position.isBeforeOrEqual(Range.getEndPosition(ref.range), position) && !sig.params[pos]?.[0].startsWith("..")) {
|
|
3017
|
-
pos++;
|
|
3018
|
-
}
|
|
3019
|
-
}
|
|
3020
|
-
return {
|
|
3021
|
-
dispose: () => void 0,
|
|
3022
|
-
value: {
|
|
3023
|
-
signatures: [signature],
|
|
3024
|
-
activeSignature: 0,
|
|
3025
|
-
activeParameter: pos
|
|
3026
|
-
}
|
|
3027
|
-
};
|
|
3028
|
-
}
|
|
3029
|
-
};
|
|
3030
|
-
|
|
3031
|
-
// src/lsp/index.ts
|
|
3032
|
-
async function registerLSP(contextProvider2, features = {}) {
|
|
3033
|
-
Provider.setContextProvider(contextProvider2);
|
|
3034
|
-
const { loadModule } = await import("@mirascript/bindings/wasm");
|
|
3035
|
-
await loadModule();
|
|
3036
|
-
const disposables = [];
|
|
3037
|
-
const registerIfEnabled = (feature, provider, register) => {
|
|
3038
|
-
const providerInstance = new provider(() => features[feature] !== false);
|
|
3039
|
-
const d = register(["mirascript", "mirascript-template"], providerInstance);
|
|
3040
|
-
if (Array.isArray(d)) disposables.push(...d);
|
|
3041
|
-
else disposables.push(d);
|
|
3042
|
-
};
|
|
3043
|
-
registerIfEnabled("codeAction", CodeActionProvider, languages.registerCodeActionProvider);
|
|
3044
|
-
registerIfEnabled("codeLens", CodeLensProvider, languages.registerCodeLensProvider);
|
|
3045
|
-
registerIfEnabled("color", ColorProvider, languages.registerColorProvider);
|
|
3046
|
-
registerIfEnabled("definitionReference", DefinitionReferenceProvider, (language, provider) => {
|
|
3047
|
-
return [
|
|
3048
|
-
languages.registerDefinitionProvider(language, provider),
|
|
3049
|
-
languages.registerReferenceProvider(language, provider)
|
|
3050
|
-
];
|
|
3051
|
-
});
|
|
3052
|
-
registerIfEnabled("documentHighlight", DocumentHighlightProvider, languages.registerDocumentHighlightProvider);
|
|
3053
|
-
registerIfEnabled("documentSymbol", DocumentSymbolProvider, languages.registerDocumentSymbolProvider);
|
|
3054
|
-
registerIfEnabled("formatter", FormatterProvider, (language, provider) => {
|
|
3055
|
-
return [
|
|
3056
|
-
languages.registerDocumentFormattingEditProvider(language, provider)
|
|
3057
|
-
// languages.registerDocumentRangeFormattingEditProvider(language, provider),
|
|
3058
|
-
// languages.registerOnTypeFormattingEditProvider(language, provider),
|
|
3059
|
-
];
|
|
3060
|
-
});
|
|
3061
|
-
registerIfEnabled("hover", HoverProvider, languages.registerHoverProvider);
|
|
3062
|
-
registerIfEnabled("inlayHints", InlayHintsProvider, languages.registerInlayHintsProvider);
|
|
3063
|
-
registerIfEnabled("range", RangeProvider, (language, provider) => {
|
|
3064
|
-
return [
|
|
3065
|
-
languages.registerFoldingRangeProvider(language, provider),
|
|
3066
|
-
languages.registerSelectionRangeProvider(language, provider)
|
|
3067
|
-
];
|
|
3068
|
-
});
|
|
3069
|
-
registerIfEnabled(
|
|
3070
|
-
"documentSemanticTokens",
|
|
3071
|
-
DocumentSemanticTokensProvider,
|
|
3072
|
-
languages.registerDocumentSemanticTokensProvider
|
|
3073
|
-
);
|
|
3074
|
-
registerIfEnabled("rename", RenameProvider, languages.registerRenameProvider);
|
|
3075
|
-
registerIfEnabled("completionItem", CompletionItemProvider, languages.registerCompletionItemProvider);
|
|
3076
|
-
registerIfEnabled("signatureHelp", SignatureHelpProvider, languages.registerSignatureHelpProvider);
|
|
3077
|
-
return disposables;
|
|
3078
|
-
}
|
|
3079
|
-
export {
|
|
3080
|
-
CodeActionProvider,
|
|
3081
|
-
CodeLensProvider,
|
|
3082
|
-
ColorProvider,
|
|
3083
|
-
CompletionItemProvider,
|
|
3084
|
-
DefinitionReferenceProvider,
|
|
3085
|
-
DocumentHighlightProvider,
|
|
3086
|
-
DocumentSemanticTokensProvider,
|
|
3087
|
-
DocumentSymbolProvider,
|
|
3088
|
-
FormatterProvider,
|
|
3089
|
-
HoverProvider,
|
|
3090
|
-
InlayHintsProvider,
|
|
3091
|
-
Provider,
|
|
3092
|
-
RangeProvider,
|
|
3093
|
-
RenameProvider,
|
|
3094
|
-
SignatureHelpProvider,
|
|
3095
|
-
registerLSP
|
|
3096
|
-
};
|
|
3097
|
-
//# sourceMappingURL=index.js.map
|