@prisma/orm-toolchain 8.0.0-rc.11-dev.6 → 8.0.0-rc.11-dev.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +129 -81
- package/dist/cli.mjs.map +1 -1
- package/dist/cli__control-api.d.mts +26 -23
- package/dist/cli__control-api.d.mts.map +1 -1
- package/dist/cli__control-api.mjs +2 -2
- package/dist/cli__control-api__testing.d.mts +2 -1
- package/dist/cli__control-api__testing.d.mts.map +1 -1
- package/dist/cli__control-api__testing.mjs +5 -1
- package/dist/cli__control-api__testing.mjs.map +1 -1
- package/dist/{db-verify-Yih5kWtB-B1kv76ec.d.mts → db-verify-BdKY7U7l-6VLIVuKF.d.mts} +41 -3
- package/dist/db-verify-BdKY7U7l-6VLIVuKF.d.mts.map +1 -0
- package/dist/{exports-CYa2di3d.mjs → exports-B8peSdx4.mjs} +523 -180
- package/dist/exports-B8peSdx4.mjs.map +1 -0
- package/dist/{ref-DcqFmceq-QaUjgZeM.mjs → ref-uqvZQnnQ-DpAQaLiM.mjs} +108 -81
- package/dist/ref-uqvZQnnQ-DpAQaLiM.mjs.map +1 -0
- package/dist/vite-plugin-contract-emit.mjs +1 -1
- package/package.json +12 -12
- package/dist/db-verify-Yih5kWtB-B1kv76ec.d.mts.map +0 -1
- package/dist/exports-CYa2di3d.mjs.map +0 -1
- package/dist/ref-DcqFmceq-QaUjgZeM.mjs.map +0 -1
|
@@ -7,9 +7,9 @@ import { join } from "pathe";
|
|
|
7
7
|
import { normalize as normalize$1 } from "node:path";
|
|
8
8
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
9
9
|
import { format } from "@prisma/orm-framework/psl-parser/format";
|
|
10
|
-
import { CompletionItemKind, ConnectionError, ConnectionErrors, DiagnosticSeverity, DidChangeWatchedFilesNotification, DocumentDiagnosticReportKind, FoldingRangeKind, InsertTextFormat, ProposedFeatures, RegistrationRequest, SemanticTokenModifiers, SemanticTokenTypes, TextDocumentSyncKind, TextDocuments, createConnection } from "vscode-languageserver";
|
|
10
|
+
import { CompletionItemKind, ConnectionError, ConnectionErrors, DiagnosticSeverity, DidChangeWatchedFilesNotification, DocumentDiagnosticReportKind, FoldingRangeKind, InsertTextFormat, LSPErrorCodes, ProposedFeatures, RegistrationRequest, ResponseError, SemanticTokenModifiers, SemanticTokenTypes, TextDocumentSyncKind, TextDocuments, createConnection } from "vscode-languageserver";
|
|
11
11
|
import { TextDocument } from "vscode-languageserver-textdocument";
|
|
12
|
-
import { ArrayLiteralAst,
|
|
12
|
+
import { ArrayLiteralAst, AttributeArgListAst, BooleanLiteralExprAst, CompositeTypeDeclarationAst, FieldAttributeAst, FieldDeclarationAst, FunctionCallAst, GenericBlockDeclarationAst, IdentifierAst, KeyValuePairAst, ModelAttributeAst, ModelDeclarationAst, NamespaceDeclarationAst, NumberLiteralExprAst, ObjectLiteralExprAst, StringLiteralExprAst, TypesBlockAst, any, filterChildren, findChildToken, isTrivia, parse, skipTriviaToken } from "@prisma/orm-framework/psl-parser/syntax";
|
|
13
13
|
import { isAuthoringPslBlockDescriptor } from "@prisma/orm-framework/components/authoring";
|
|
14
14
|
import { assembleAttributeSpecs, buildSymbolTable, findBlockDescriptor } from "@prisma/orm-framework/psl-parser";
|
|
15
15
|
import { hasPslInterpreter } from "@prisma/orm-framework/psl-parser/interpret";
|
|
@@ -68,7 +68,7 @@ function classifyPslCompletionContext(input) {
|
|
|
68
68
|
const replacementStartOffset = edit?.offset ?? offset;
|
|
69
69
|
const attributeClassifierInput = {
|
|
70
70
|
offset,
|
|
71
|
-
node:
|
|
71
|
+
node: attributeAnchor(at),
|
|
72
72
|
replacementStartOffset
|
|
73
73
|
};
|
|
74
74
|
const attributeContext = classifyFieldAttribute(attributeClassifierInput) ?? classifyGenericBlockAttribute(attributeClassifierInput) ?? classifyModelAttribute(attributeClassifierInput);
|
|
@@ -205,29 +205,36 @@ function blockBodyContainsOffset(block, offset) {
|
|
|
205
205
|
}
|
|
206
206
|
function classifyFieldAttribute(input) {
|
|
207
207
|
const attribute = input.node?.findAncestor(FieldAttributeAst.cast);
|
|
208
|
-
if (attribute === void 0 || attribute
|
|
208
|
+
if (attribute === void 0 || !attributeContainsOffset(attribute, input.offset)) return;
|
|
209
209
|
const field = attribute.syntax.findAncestor(FieldDeclarationAst.cast);
|
|
210
210
|
const model = attribute.syntax.findAncestor(ModelDeclarationAst.cast);
|
|
211
211
|
if (field === void 0 || model === void 0) return UNSUPPORTED;
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
212
|
+
return classifyAttributePosition(attribute, input, {
|
|
213
|
+
name: (position) => ({
|
|
214
|
+
kind: "fieldAttributeName",
|
|
215
|
+
...position,
|
|
216
|
+
field,
|
|
217
|
+
model
|
|
218
|
+
}),
|
|
219
|
+
namedKey: (position) => ({
|
|
220
|
+
kind: "fieldAttributeNamedKey",
|
|
221
|
+
...position,
|
|
222
|
+
field,
|
|
223
|
+
model
|
|
224
|
+
}),
|
|
225
|
+
argumentSlot: (position) => ({
|
|
226
|
+
kind: "fieldAttributeArgumentSlot",
|
|
227
|
+
...position,
|
|
228
|
+
field,
|
|
229
|
+
model
|
|
230
|
+
}),
|
|
231
|
+
value: (position) => ({
|
|
232
|
+
kind: "fieldAttributeValue",
|
|
233
|
+
...position,
|
|
234
|
+
field,
|
|
235
|
+
model
|
|
236
|
+
})
|
|
237
|
+
});
|
|
231
238
|
}
|
|
232
239
|
function classifyGenericBlockAttribute(input) {
|
|
233
240
|
const attribute = activeModelAttribute(input);
|
|
@@ -235,80 +242,226 @@ function classifyGenericBlockAttribute(input) {
|
|
|
235
242
|
if (attribute === void 0 || block === void 0) return;
|
|
236
243
|
const blockKeyword = block.keyword()?.text;
|
|
237
244
|
if (blockKeyword === void 0 || blockKeyword.length === 0) return UNSUPPORTED;
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
245
|
+
return classifyAttributePosition(attribute, input, {
|
|
246
|
+
name: (position) => ({
|
|
247
|
+
kind: "blockAttributeName",
|
|
248
|
+
...position,
|
|
249
|
+
block,
|
|
250
|
+
blockKeyword
|
|
251
|
+
}),
|
|
252
|
+
namedKey: (position) => ({
|
|
253
|
+
kind: "blockAttributeNamedKey",
|
|
254
|
+
...position,
|
|
255
|
+
block,
|
|
256
|
+
blockKeyword
|
|
257
|
+
}),
|
|
258
|
+
argumentSlot: (position) => ({
|
|
259
|
+
kind: "blockAttributeArgumentSlot",
|
|
260
|
+
...position,
|
|
261
|
+
block,
|
|
262
|
+
blockKeyword
|
|
263
|
+
}),
|
|
264
|
+
value: (position) => ({
|
|
265
|
+
kind: "blockAttributeValue",
|
|
266
|
+
...position,
|
|
267
|
+
block,
|
|
268
|
+
blockKeyword
|
|
269
|
+
})
|
|
270
|
+
});
|
|
257
271
|
}
|
|
258
272
|
function classifyModelAttribute(input) {
|
|
259
273
|
const attribute = activeModelAttribute(input);
|
|
260
274
|
if (attribute === void 0) return;
|
|
261
275
|
const model = attribute.syntax.findAncestor(ModelDeclarationAst.cast);
|
|
262
276
|
if (model === void 0) return;
|
|
263
|
-
|
|
264
|
-
|
|
277
|
+
return classifyAttributePosition(attribute, input, {
|
|
278
|
+
name: (position) => ({
|
|
279
|
+
kind: "modelAttributeName",
|
|
280
|
+
...position,
|
|
281
|
+
model
|
|
282
|
+
}),
|
|
283
|
+
namedKey: (position) => ({
|
|
284
|
+
kind: "modelAttributeNamedKey",
|
|
285
|
+
...position,
|
|
286
|
+
model
|
|
287
|
+
}),
|
|
288
|
+
argumentSlot: (position) => ({
|
|
289
|
+
kind: "modelAttributeArgumentSlot",
|
|
290
|
+
...position,
|
|
291
|
+
model
|
|
292
|
+
}),
|
|
293
|
+
value: (position) => ({
|
|
294
|
+
kind: "modelAttributeValue",
|
|
295
|
+
...position,
|
|
296
|
+
model
|
|
297
|
+
})
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
function activeModelAttribute(input) {
|
|
301
|
+
const attribute = input.node?.findAncestor(ModelAttributeAst.cast);
|
|
302
|
+
if (attribute === void 0 || !attributeContainsOffset(attribute, input.offset)) return;
|
|
303
|
+
return attribute;
|
|
304
|
+
}
|
|
305
|
+
function attributeAnchor(at) {
|
|
306
|
+
const token = at.leftBiased() ?? at.rightBiased();
|
|
307
|
+
return token === void 0 ? void 0 : skipTriviaToken(token, "prev")?.parent;
|
|
308
|
+
}
|
|
309
|
+
function attributeContainsOffset(attribute, offset) {
|
|
310
|
+
if (attribute.syntax.isInside(offset)) return true;
|
|
311
|
+
const args = attribute.argList();
|
|
312
|
+
return args !== void 0 && args.rparen() === void 0 && offset >= args.syntax.endOffset;
|
|
313
|
+
}
|
|
314
|
+
function isAttributeNamePosition(attribute, offset) {
|
|
315
|
+
const argList = attribute.argList();
|
|
316
|
+
return argList === void 0 || offset < argList.syntax.offset;
|
|
317
|
+
}
|
|
318
|
+
function attributeArgumentName(attribute, offset) {
|
|
319
|
+
const args = attribute.argList();
|
|
320
|
+
if (args === void 0 || offset < args.syntax.offset) return void 0;
|
|
321
|
+
const closing = args.rparen();
|
|
322
|
+
if (closing !== void 0 && offset >= closing.endOffset) return void 0;
|
|
323
|
+
return attribute.name()?.identifier()?.name();
|
|
324
|
+
}
|
|
325
|
+
function classifyAttributePosition(attribute, input, factory) {
|
|
326
|
+
const args = attribute.argList();
|
|
327
|
+
if (isAttributeNamePosition(attribute, input.offset)) return factory.name({
|
|
265
328
|
offset: input.offset,
|
|
266
329
|
replacementStartOffset: input.replacementStartOffset,
|
|
267
|
-
attribute,
|
|
268
|
-
|
|
269
|
-
};
|
|
270
|
-
const attributeName =
|
|
271
|
-
if (attributeName === void 0) return UNSUPPORTED;
|
|
272
|
-
|
|
273
|
-
|
|
330
|
+
replacementEndOffset: attribute.name()?.syntax.endOffset ?? input.offset,
|
|
331
|
+
hasArgumentList: args !== void 0
|
|
332
|
+
});
|
|
333
|
+
const attributeName = attributeArgumentName(attribute, input.offset);
|
|
334
|
+
if (attributeName === void 0 || args === void 0) return UNSUPPORTED;
|
|
335
|
+
const at = attribute.syntax.tokenAtOffset(input.offset);
|
|
336
|
+
const right = at.rightBiased();
|
|
337
|
+
const token = isValueToken(right) ? right : at.leftBiased();
|
|
338
|
+
const replaceToken = isValueToken(token);
|
|
339
|
+
const anchor = at.leftBiased() ?? attribute.syntax.lastToken;
|
|
340
|
+
return classifyArguments({
|
|
274
341
|
offset: input.offset,
|
|
275
|
-
replacementStartOffset: input.
|
|
342
|
+
replacementStartOffset: replaceToken ? token.offset : input.offset,
|
|
343
|
+
replacementEndOffset: replaceToken ? token.endOffset : input.offset,
|
|
276
344
|
attributeName,
|
|
277
|
-
|
|
278
|
-
|
|
345
|
+
preceding: anchor === void 0 ? void 0 : skipTriviaToken(anchor, "prev"),
|
|
346
|
+
factory
|
|
347
|
+
}, args, []);
|
|
348
|
+
}
|
|
349
|
+
function argumentPosition(cursor, path) {
|
|
350
|
+
return {
|
|
351
|
+
offset: cursor.offset,
|
|
352
|
+
replacementStartOffset: cursor.replacementStartOffset,
|
|
353
|
+
replacementEndOffset: cursor.replacementEndOffset,
|
|
354
|
+
attributeName: cursor.attributeName,
|
|
355
|
+
path
|
|
279
356
|
};
|
|
280
357
|
}
|
|
281
|
-
function
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
return
|
|
358
|
+
function classifyArguments(cursor, container, path) {
|
|
359
|
+
const opening = container.lparen();
|
|
360
|
+
const closing = container.rparen();
|
|
361
|
+
if (opening === void 0 || cursor.offset <= opening.offset || closing !== void 0 && cursor.offset >= closing.endOffset) return UNSUPPORTED;
|
|
362
|
+
let positionalIndex = 0;
|
|
363
|
+
let active;
|
|
364
|
+
const existingNamedKeys = [];
|
|
365
|
+
for (const arg of container.args()) {
|
|
366
|
+
const name = arg.name()?.name();
|
|
367
|
+
const selected = arg.syntax.offset <= cursor.offset && (containsCursor(arg.syntax, cursor) || recoveredContainerContainsCursor(arg.value(), cursor.offset));
|
|
368
|
+
if (active === void 0 && selected) active = arg;
|
|
369
|
+
else {
|
|
370
|
+
if (name !== void 0) existingNamedKeys.push(name);
|
|
371
|
+
if (active === void 0 && arg.syntax.offset <= cursor.offset && name === void 0) positionalIndex += 1;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const position = argumentPosition(cursor, path);
|
|
375
|
+
if (active === void 0) return followsSeparator(cursor, ["LParen", "Comma"]) ? cursor.factory.argumentSlot({
|
|
376
|
+
...position,
|
|
377
|
+
positionalIndex,
|
|
378
|
+
existingNamedKeys,
|
|
379
|
+
hasColon: false
|
|
380
|
+
}) : UNSUPPORTED;
|
|
381
|
+
const colon = active.colon();
|
|
382
|
+
if (colon !== void 0) {
|
|
383
|
+
if (cursor.offset <= colon.offset) return cursor.factory.namedKey({
|
|
384
|
+
...position,
|
|
385
|
+
existingNamedKeys,
|
|
386
|
+
hasColon: true
|
|
387
|
+
});
|
|
388
|
+
const name = active.name()?.name();
|
|
389
|
+
return name === void 0 ? UNSUPPORTED : classifyExpression(cursor, active.value(), [...path, {
|
|
390
|
+
kind: "namedArgument",
|
|
391
|
+
name
|
|
392
|
+
}]);
|
|
393
|
+
}
|
|
394
|
+
const value = active.value();
|
|
395
|
+
if (value === void 0 || value instanceof IdentifierAst && value.syntax.isInside(cursor.offset)) return cursor.factory.argumentSlot({
|
|
396
|
+
...position,
|
|
397
|
+
positionalIndex,
|
|
398
|
+
existingNamedKeys,
|
|
399
|
+
hasColon: false
|
|
400
|
+
});
|
|
401
|
+
return classifyExpression(cursor, value, [...path, {
|
|
402
|
+
kind: "positionalArgument",
|
|
403
|
+
index: positionalIndex
|
|
404
|
+
}]);
|
|
405
|
+
}
|
|
406
|
+
function classifyExpression(cursor, expression, path) {
|
|
407
|
+
if (expression instanceof ArrayLiteralAst) return classifyList(cursor, expression, path);
|
|
408
|
+
if (expression instanceof ObjectLiteralExprAst) return classifyRecord(cursor, expression, path);
|
|
409
|
+
if (expression instanceof FunctionCallAst) {
|
|
410
|
+
const opening = expression.lparen();
|
|
411
|
+
if (opening !== void 0 && cursor.offset > opening.offset) {
|
|
412
|
+
const name = expression.name();
|
|
413
|
+
const identifier = name?.identifier()?.name();
|
|
414
|
+
return identifier !== void 0 && name?.isSimpleName(identifier) === true ? classifyArguments(cursor, expression, [...path, {
|
|
415
|
+
kind: "functionCall",
|
|
416
|
+
name: identifier
|
|
417
|
+
}]) : UNSUPPORTED;
|
|
418
|
+
}
|
|
419
|
+
return expression.name()?.syntax.isInside(cursor.offset) === true ? cursor.factory.value({
|
|
420
|
+
...argumentPosition(cursor, path),
|
|
421
|
+
syntax: "functionName"
|
|
422
|
+
}) : UNSUPPORTED;
|
|
423
|
+
}
|
|
424
|
+
return expression?.syntax.isOutside(cursor.offset) === true ? UNSUPPORTED : cursor.factory.value({
|
|
425
|
+
...argumentPosition(cursor, path),
|
|
426
|
+
syntax: "scalar"
|
|
427
|
+
});
|
|
285
428
|
}
|
|
286
|
-
function
|
|
287
|
-
|
|
429
|
+
function classifyList(cursor, expression, path) {
|
|
430
|
+
const opening = expression.lbracket();
|
|
431
|
+
const closing = expression.rbracket();
|
|
432
|
+
if (opening === void 0 || cursor.offset <= opening.offset || closing !== void 0 && cursor.offset >= closing.endOffset) return UNSUPPORTED;
|
|
433
|
+
const elementPath = [...path, { kind: "listElement" }];
|
|
434
|
+
for (const element of expression.elements()) if (containsCursor(element.syntax, cursor) || recoveredContainerContainsCursor(element, cursor.offset)) return classifyExpression(cursor, element, elementPath);
|
|
435
|
+
return followsSeparator(cursor, ["LBracket", "Comma"]) ? classifyExpression(cursor, void 0, elementPath) : UNSUPPORTED;
|
|
288
436
|
}
|
|
289
|
-
function
|
|
290
|
-
const
|
|
291
|
-
if (
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (
|
|
303
|
-
if (
|
|
304
|
-
|
|
305
|
-
if (
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
return
|
|
437
|
+
function classifyRecord(cursor, expression, path) {
|
|
438
|
+
const closing = expression.rbrace();
|
|
439
|
+
if (closing !== void 0 && cursor.offset >= closing.endOffset) return UNSUPPORTED;
|
|
440
|
+
for (const field of expression.fields()) {
|
|
441
|
+
const colon = field.colon();
|
|
442
|
+
if (colon !== void 0 && cursor.offset > colon.offset && (containsCursor(field.syntax, cursor) || recoveredContainerContainsCursor(field.value(), cursor.offset))) return classifyExpression(cursor, field.value(), [...path, { kind: "recordValue" }]);
|
|
443
|
+
}
|
|
444
|
+
return UNSUPPORTED;
|
|
445
|
+
}
|
|
446
|
+
function isValueToken(token) {
|
|
447
|
+
return token !== void 0 && (token.kind === "Ident" || token.kind === "StringLiteral" || token.kind === "NumberLiteral");
|
|
448
|
+
}
|
|
449
|
+
function recoveredContainerContainsCursor(expression, offset) {
|
|
450
|
+
if (expression === void 0 || expression.syntax.endOffset > offset) return false;
|
|
451
|
+
if (!(expression instanceof ArrayLiteralAst ? expression.rbracket() === void 0 : expression instanceof ObjectLiteralExprAst ? expression.rbrace() === void 0 : expression instanceof FunctionCallAst && expression.rparen() === void 0)) return false;
|
|
452
|
+
for (let token = expression.syntax.lastToken?.nextToken; token !== void 0; token = token.nextToken) {
|
|
453
|
+
if (token.offset >= offset) return true;
|
|
454
|
+
if (!isTrivia(token) && token.kind !== "Comma") return false;
|
|
455
|
+
}
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
function containsCursor(node, cursor) {
|
|
459
|
+
if (node.isInside(cursor.offset)) return true;
|
|
460
|
+
const preceding = cursor.preceding;
|
|
461
|
+
return preceding !== void 0 && preceding.endOffset <= cursor.offset && preceding.offset >= node.offset && preceding.offset < node.endOffset;
|
|
462
|
+
}
|
|
463
|
+
function followsSeparator(cursor, kinds) {
|
|
464
|
+
return kinds.includes(cursor.preceding?.kind ?? "");
|
|
312
465
|
}
|
|
313
466
|
function classifyGenericBlockParameter(input) {
|
|
314
467
|
const node = input.at.leftBiased()?.parent;
|
|
@@ -360,6 +513,200 @@ function cursorIdentifier(at, offset) {
|
|
|
360
513
|
const left = at.leftBiased();
|
|
361
514
|
if (left?.kind === "Ident" && left.endOffset === offset) return left;
|
|
362
515
|
}
|
|
516
|
+
function requiredArgumentsSnippet(signature) {
|
|
517
|
+
return requiredArguments(signature).map((argument, index) => requiredArgumentSnippet(argument, index + 1)).join(", ");
|
|
518
|
+
}
|
|
519
|
+
function requiredArguments(signature) {
|
|
520
|
+
const positional = signature.positional ?? [];
|
|
521
|
+
const positionalKeys = new Set(positional.map((argument) => argument.key));
|
|
522
|
+
return [...positional.flatMap((argument) => isOptionalParam(argument.type) ? [] : [{
|
|
523
|
+
kind: "positional",
|
|
524
|
+
argument
|
|
525
|
+
}]), ...Object.entries(signature.named ?? {}).flatMap(([key, type]) => positionalKeys.has(key) || isOptionalParam(type) ? [] : [{
|
|
526
|
+
kind: "named",
|
|
527
|
+
key,
|
|
528
|
+
type
|
|
529
|
+
}])];
|
|
530
|
+
}
|
|
531
|
+
function requiredArgumentSnippet(argument, tabStop) {
|
|
532
|
+
if (argument.kind === "positional") return argSnippetPlaceholder(argument.argument.type, tabStop);
|
|
533
|
+
return `${argument.key}: ${argSnippetPlaceholder(argument.type, tabStop)}`;
|
|
534
|
+
}
|
|
535
|
+
function argSnippetPlaceholder(param, tabStop) {
|
|
536
|
+
const placeholder = `\${${tabStop.toString()}:}`;
|
|
537
|
+
if (param.kind === "str") return `"${placeholder}"`;
|
|
538
|
+
if (param.kind === "list") return `[${placeholder}]`;
|
|
539
|
+
if (param.kind === "record") return `{ ${placeholder} }`;
|
|
540
|
+
return placeholder;
|
|
541
|
+
}
|
|
542
|
+
function isOptionalParam(param) {
|
|
543
|
+
return "optional" in param && param.optional === true;
|
|
544
|
+
}
|
|
545
|
+
function modelSymbolForNode(symbolTable, node) {
|
|
546
|
+
const topLevelMatch = Object.values(symbolTable.topLevel.models).find((model) => sameSyntax(model.node.syntax, node.syntax));
|
|
547
|
+
if (topLevelMatch !== void 0) return topLevelMatch;
|
|
548
|
+
for (const namespace of Object.values(symbolTable.topLevel.namespaces)) {
|
|
549
|
+
const namespaceMatch = Object.values(namespace.models).find((model) => sameSyntax(model.node.syntax, node.syntax));
|
|
550
|
+
if (namespaceMatch !== void 0) return namespaceMatch;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
function fieldSymbolForNode(model, node) {
|
|
554
|
+
return Object.values(model.fields).find((field) => sameSyntax(field.node.syntax, node.syntax));
|
|
555
|
+
}
|
|
556
|
+
function localFieldNames(context, symbols) {
|
|
557
|
+
switch (context.kind) {
|
|
558
|
+
case "blockAttributeNamedKey":
|
|
559
|
+
case "blockAttributeArgumentSlot":
|
|
560
|
+
case "blockAttributeValue": return [];
|
|
561
|
+
case "fieldAttributeNamedKey":
|
|
562
|
+
case "fieldAttributeArgumentSlot":
|
|
563
|
+
case "fieldAttributeValue":
|
|
564
|
+
case "modelAttributeNamedKey":
|
|
565
|
+
case "modelAttributeArgumentSlot":
|
|
566
|
+
case "modelAttributeValue": return Object.keys(modelSymbolForNode(symbols, context.model)?.fields ?? {});
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function referencedFieldNames(context, symbols) {
|
|
570
|
+
switch (context.kind) {
|
|
571
|
+
case "blockAttributeNamedKey":
|
|
572
|
+
case "blockAttributeArgumentSlot":
|
|
573
|
+
case "blockAttributeValue":
|
|
574
|
+
case "modelAttributeNamedKey":
|
|
575
|
+
case "modelAttributeArgumentSlot":
|
|
576
|
+
case "modelAttributeValue": return [];
|
|
577
|
+
case "fieldAttributeNamedKey":
|
|
578
|
+
case "fieldAttributeArgumentSlot":
|
|
579
|
+
case "fieldAttributeValue": {
|
|
580
|
+
const model = modelSymbolForNode(symbols, context.model);
|
|
581
|
+
if (model === void 0) return [];
|
|
582
|
+
const field = fieldSymbolForNode(model, context.field);
|
|
583
|
+
if (field === void 0) return [];
|
|
584
|
+
return Object.keys(referencedModel(symbols, model, field)?.fields ?? {});
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
function referencedModel(symbols, model, field) {
|
|
589
|
+
if (field.malformedType === true || field.typeContractSpaceId !== void 0) return void 0;
|
|
590
|
+
if (field.typeNamespaceId !== void 0) return symbols.topLevel.namespaces[field.typeNamespaceId]?.models[field.typeName];
|
|
591
|
+
const namespace = model.node.syntax.findAncestor(NamespaceDeclarationAst.cast)?.name()?.name();
|
|
592
|
+
return (namespace === void 0 ? void 0 : symbols.topLevel.namespaces[namespace]?.models[field.typeName]) ?? symbols.topLevel.models[field.typeName];
|
|
593
|
+
}
|
|
594
|
+
function sameSyntax(left, right) {
|
|
595
|
+
return left.offset === right.offset && left.endOffset === right.endOffset;
|
|
596
|
+
}
|
|
597
|
+
function provideAttributeNamedKeyCompletionItems(input, spec) {
|
|
598
|
+
return orderedItems(resolveGrammar(spec, input.context.path).flatMap((grammar) => "kind" in grammar ? [] : namedKeyItems(input, grammar)));
|
|
599
|
+
}
|
|
600
|
+
function provideAttributeArgumentSlotCompletionItems(input, spec) {
|
|
601
|
+
return orderedItems(resolveGrammar(spec, input.context.path).flatMap((grammar) => {
|
|
602
|
+
if ("kind" in grammar) return [];
|
|
603
|
+
const param = grammar.positional?.[input.context.positionalIndex]?.type;
|
|
604
|
+
return [...valueItems(input, param, "scalar"), ...namedKeyItems(input, grammar)];
|
|
605
|
+
}));
|
|
606
|
+
}
|
|
607
|
+
function provideAttributeValueCompletionItems(input, spec) {
|
|
608
|
+
return orderedItems(resolveGrammar(spec, input.context.path).flatMap((grammar) => "kind" in grammar ? valueItems(input, grammar, input.context.syntax) : []));
|
|
609
|
+
}
|
|
610
|
+
function directArgType(param) {
|
|
611
|
+
return blindCast(param);
|
|
612
|
+
}
|
|
613
|
+
function resolveGrammar(signature, path) {
|
|
614
|
+
let grammars = [signature];
|
|
615
|
+
for (const step of path) grammars = grammars.flatMap((grammar) => advanceGrammar(grammar, step));
|
|
616
|
+
return grammars;
|
|
617
|
+
}
|
|
618
|
+
function advanceGrammar(grammar, step) {
|
|
619
|
+
const type = "kind" in grammar ? directArgType(grammar) : void 0;
|
|
620
|
+
if (type?.kind === "oneOf") return type.alternatives.flatMap((alternative) => advanceGrammar(alternative, step));
|
|
621
|
+
switch (step.kind) {
|
|
622
|
+
case "positionalArgument": {
|
|
623
|
+
if ("kind" in grammar) return [];
|
|
624
|
+
const param = grammar.positional?.[step.index]?.type;
|
|
625
|
+
return param === void 0 ? [] : [param];
|
|
626
|
+
}
|
|
627
|
+
case "namedArgument": {
|
|
628
|
+
if ("kind" in grammar) return [];
|
|
629
|
+
const param = grammar.named?.[step.name];
|
|
630
|
+
return param === void 0 ? [] : [param];
|
|
631
|
+
}
|
|
632
|
+
case "listElement": return type?.kind === "list" ? [type.of] : [];
|
|
633
|
+
case "recordValue": return type?.kind === "record" ? [type.of] : [];
|
|
634
|
+
case "functionCall": return type?.kind === "funcCall" && type.name === step.name ? [type.signature] : [];
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
function namedKeyItems(input, signature) {
|
|
638
|
+
return Object.keys(signature.named ?? {}).filter((name) => !input.context.existingNamedKeys.includes(name)).map((name) => {
|
|
639
|
+
const snippet = input.clientSupportsSnippets && !input.context.hasColon;
|
|
640
|
+
const value = snippet ? "${1:}" : "";
|
|
641
|
+
return {
|
|
642
|
+
...completionItem(input, name, input.context.hasColon ? name : `${name}: ${value}`, CompletionItemKind.Property, snippet),
|
|
643
|
+
...!input.context.hasColon && input.clientSupportsTriggerSuggestCommand === true ? { command: {
|
|
644
|
+
title: "Suggest argument values",
|
|
645
|
+
command: "editor.action.triggerSuggest"
|
|
646
|
+
} } : {}
|
|
647
|
+
};
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
function valueItems(input, param, syntax) {
|
|
651
|
+
if (param === void 0) return [];
|
|
652
|
+
const type = directArgType(param);
|
|
653
|
+
if (type.kind === "oneOf") return type.alternatives.flatMap((alternative) => valueItems(input, alternative, syntax));
|
|
654
|
+
if (type.kind === "funcCall") {
|
|
655
|
+
const snippet = input.clientSupportsSnippets && syntax !== "functionName";
|
|
656
|
+
const text = snippet ? `${type.name}(${requiredArgumentsSnippet(type.signature)})` : type.name;
|
|
657
|
+
return [completionItem(input, type.name, text, CompletionItemKind.Function, snippet)];
|
|
658
|
+
}
|
|
659
|
+
if (syntax === "functionName") return [];
|
|
660
|
+
switch (type.kind) {
|
|
661
|
+
case "identifier": return scalarItems(input, [type.name]);
|
|
662
|
+
case "str": return scalarItems(input, type.value === void 0 ? [] : [JSON.stringify(type.value)]);
|
|
663
|
+
case "num": return scalarItems(input, type.value === void 0 ? [] : [String(type.value)]);
|
|
664
|
+
case "bool": return scalarItems(input, ["true", "false"]);
|
|
665
|
+
case "fieldRef":
|
|
666
|
+
case "referencedFieldRef": return scalarItems(input, input.fieldNames(type.kind));
|
|
667
|
+
case "list":
|
|
668
|
+
case "record":
|
|
669
|
+
case "entityRef":
|
|
670
|
+
case "int":
|
|
671
|
+
case "json":
|
|
672
|
+
case "rejecting": return [];
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
function scalarItems(input, labels) {
|
|
676
|
+
return labels.map((label) => completionItem(input, label, label, CompletionItemKind.Value));
|
|
677
|
+
}
|
|
678
|
+
function completionItem(input, label, newText, kind, snippet = false) {
|
|
679
|
+
return {
|
|
680
|
+
label,
|
|
681
|
+
kind,
|
|
682
|
+
detail: kind === CompletionItemKind.Property ? "Attribute argument" : "PSL argument value",
|
|
683
|
+
filterText: label,
|
|
684
|
+
textEdit: {
|
|
685
|
+
range: {
|
|
686
|
+
start: input.sourceFile.positionAt(input.context.replacementStartOffset),
|
|
687
|
+
end: input.sourceFile.positionAt(input.context.replacementEndOffset)
|
|
688
|
+
},
|
|
689
|
+
newText
|
|
690
|
+
},
|
|
691
|
+
...snippet ? { insertTextFormat: InsertTextFormat.Snippet } : {}
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
function orderedItems(items) {
|
|
695
|
+
const seen = /* @__PURE__ */ new Set();
|
|
696
|
+
return items.filter((item) => {
|
|
697
|
+
const key = JSON.stringify([
|
|
698
|
+
item.label,
|
|
699
|
+
item.textEdit,
|
|
700
|
+
item.insertTextFormat
|
|
701
|
+
]);
|
|
702
|
+
if (seen.has(key)) return false;
|
|
703
|
+
seen.add(key);
|
|
704
|
+
return true;
|
|
705
|
+
}).map((item, index) => ({
|
|
706
|
+
...item,
|
|
707
|
+
sortText: index.toString().padStart(4, "0")
|
|
708
|
+
}));
|
|
709
|
+
}
|
|
363
710
|
/**
|
|
364
711
|
* Presentation-level classification of a `types {}` binding: a
|
|
365
712
|
* non-constructor binding whose base is a configured scalar type refines that
|
|
@@ -403,7 +750,38 @@ function providePslCompletionItems(input) {
|
|
|
403
750
|
case "blockAttributeName": return provideAttributeNameCompletionItems(context, input.sourceFile, input.candidates, input.clientSupportsSnippets);
|
|
404
751
|
case "fieldAttributeNamedKey":
|
|
405
752
|
case "modelAttributeNamedKey":
|
|
406
|
-
case "blockAttributeNamedKey":
|
|
753
|
+
case "blockAttributeNamedKey": {
|
|
754
|
+
const spec = attributeSpecResolver(context, input.candidates)(context.attributeName);
|
|
755
|
+
return spec === void 0 ? [] : provideAttributeNamedKeyCompletionItems({
|
|
756
|
+
context,
|
|
757
|
+
sourceFile: input.sourceFile,
|
|
758
|
+
clientSupportsSnippets: input.clientSupportsSnippets,
|
|
759
|
+
clientSupportsTriggerSuggestCommand: input.clientSupportsTriggerSuggestCommand === true
|
|
760
|
+
}, spec);
|
|
761
|
+
}
|
|
762
|
+
case "fieldAttributeArgumentSlot":
|
|
763
|
+
case "modelAttributeArgumentSlot":
|
|
764
|
+
case "blockAttributeArgumentSlot": {
|
|
765
|
+
const spec = attributeSpecResolver(context, input.candidates)(context.attributeName);
|
|
766
|
+
return spec === void 0 ? [] : provideAttributeArgumentSlotCompletionItems({
|
|
767
|
+
context,
|
|
768
|
+
sourceFile: input.sourceFile,
|
|
769
|
+
clientSupportsSnippets: input.clientSupportsSnippets,
|
|
770
|
+
clientSupportsTriggerSuggestCommand: input.clientSupportsTriggerSuggestCommand === true,
|
|
771
|
+
fieldNames: (kind) => kind === "fieldRef" ? localFieldNames(context, input.candidates.symbolTable) : referencedFieldNames(context, input.candidates.symbolTable)
|
|
772
|
+
}, spec);
|
|
773
|
+
}
|
|
774
|
+
case "fieldAttributeValue":
|
|
775
|
+
case "modelAttributeValue":
|
|
776
|
+
case "blockAttributeValue": {
|
|
777
|
+
const spec = attributeSpecResolver(context, input.candidates)(context.attributeName);
|
|
778
|
+
return spec === void 0 ? [] : provideAttributeValueCompletionItems({
|
|
779
|
+
context,
|
|
780
|
+
sourceFile: input.sourceFile,
|
|
781
|
+
clientSupportsSnippets: input.clientSupportsSnippets,
|
|
782
|
+
fieldNames: (kind) => kind === "fieldRef" ? localFieldNames(context, input.candidates.symbolTable) : referencedFieldNames(context, input.candidates.symbolTable)
|
|
783
|
+
}, spec);
|
|
784
|
+
}
|
|
407
785
|
case "declarationKeyword": return provideDeclarationKeywordCompletionItems(context, input.sourceFile, input.candidates, input.clientSupportsSnippets);
|
|
408
786
|
case "genericBlockKey": return provideGenericBlockKeyCompletionItems(context, input.sourceFile, input.candidates);
|
|
409
787
|
case "modelType": return provideModelTypeCompletionItems(context, input.sourceFile, input.candidates);
|
|
@@ -412,17 +790,16 @@ function providePslCompletionItems(input) {
|
|
|
412
790
|
}
|
|
413
791
|
function provideAttributeNameCompletionItems(context, sourceFile, source, clientSupportsSnippets) {
|
|
414
792
|
const names = attributeNames(context, source);
|
|
415
|
-
const replacementEndOffset = attributeNameReplacementEndOffset(context);
|
|
416
793
|
const replacementRange = {
|
|
417
794
|
start: sourceFile.positionAt(context.replacementStartOffset),
|
|
418
|
-
end: sourceFile.positionAt(replacementEndOffset)
|
|
795
|
+
end: sourceFile.positionAt(context.replacementEndOffset)
|
|
419
796
|
};
|
|
420
797
|
const resolveSpec = attributeSpecResolver(context, source);
|
|
421
798
|
return names.map((name) => {
|
|
422
799
|
const newText = attributeNameEditText({
|
|
423
800
|
name,
|
|
424
801
|
spec: resolveSpec(name),
|
|
425
|
-
|
|
802
|
+
hasArgumentList: context.hasArgumentList,
|
|
426
803
|
clientSupportsSnippets
|
|
427
804
|
});
|
|
428
805
|
return {
|
|
@@ -439,26 +816,6 @@ function provideAttributeNameCompletionItems(context, sourceFile, source, client
|
|
|
439
816
|
};
|
|
440
817
|
});
|
|
441
818
|
}
|
|
442
|
-
function provideAttributeNamedKeyCompletionItems(context, sourceFile, source) {
|
|
443
|
-
const spec = attributeSpec(context, source);
|
|
444
|
-
if (spec === void 0) return [];
|
|
445
|
-
const existing = existingAttributeNamedKeys(context.attribute, context.offset);
|
|
446
|
-
const replacementRange = {
|
|
447
|
-
start: sourceFile.positionAt(context.replacementStartOffset),
|
|
448
|
-
end: sourceFile.positionAt(namedKeyReplacementEndOffset(context))
|
|
449
|
-
};
|
|
450
|
-
return Object.keys(spec.named).filter((name) => !existing.has(name)).map((name) => ({
|
|
451
|
-
label: name,
|
|
452
|
-
kind: CompletionItemKind.Property,
|
|
453
|
-
detail: "Attribute argument",
|
|
454
|
-
sortText: name,
|
|
455
|
-
filterText: name,
|
|
456
|
-
textEdit: {
|
|
457
|
-
range: replacementRange,
|
|
458
|
-
newText: name
|
|
459
|
-
}
|
|
460
|
-
}));
|
|
461
|
-
}
|
|
462
819
|
function attributeNames(context, source) {
|
|
463
820
|
switch (context.kind) {
|
|
464
821
|
case "blockAttributeName": {
|
|
@@ -474,54 +831,16 @@ function attributeNames(context, source) {
|
|
|
474
831
|
}
|
|
475
832
|
}
|
|
476
833
|
function attributeNameEditText(input) {
|
|
477
|
-
if (!input.clientSupportsSnippets || input.spec === void 0 || input.
|
|
478
|
-
const required =
|
|
479
|
-
|
|
480
|
-
return `${input.name}(${required.map((argument, index) => requiredAttributeArgumentSnippet(argument, index + 1)).join(", ")})`;
|
|
481
|
-
}
|
|
482
|
-
function requiredAttributeArguments(spec) {
|
|
483
|
-
const positionalKeys = new Set(spec.positional.map((argument) => argument.key));
|
|
484
|
-
return [...spec.positional.flatMap((argument) => isOptionalParam(argument.type) ? [] : [{
|
|
485
|
-
kind: "positional",
|
|
486
|
-
argument
|
|
487
|
-
}]), ...Object.entries(spec.named).flatMap(([key, type]) => positionalKeys.has(key) || isOptionalParam(type) ? [] : [{
|
|
488
|
-
kind: "named",
|
|
489
|
-
key,
|
|
490
|
-
type
|
|
491
|
-
}])];
|
|
492
|
-
}
|
|
493
|
-
function requiredAttributeArgumentSnippet(argument, tabStop) {
|
|
494
|
-
if (argument.kind === "positional") return argSnippetPlaceholder(argument.argument.type, tabStop);
|
|
495
|
-
return `${argument.key}: ${argSnippetPlaceholder(argument.type, tabStop)}`;
|
|
496
|
-
}
|
|
497
|
-
function argSnippetPlaceholder(param, tabStop) {
|
|
498
|
-
const placeholder = `\${${tabStop.toString()}:}`;
|
|
499
|
-
if (param.kind === "str") return `"${placeholder}"`;
|
|
500
|
-
if (param.kind === "list") return `[${placeholder}]`;
|
|
501
|
-
if (param.kind === "record") return `{ ${placeholder} }`;
|
|
502
|
-
return placeholder;
|
|
503
|
-
}
|
|
504
|
-
function isOptionalParam(param) {
|
|
505
|
-
return "optional" in param && param.optional === true;
|
|
506
|
-
}
|
|
507
|
-
function attributeNameReplacementEndOffset(context) {
|
|
508
|
-
return context.attribute.name()?.syntax.endOffset ?? context.offset;
|
|
509
|
-
}
|
|
510
|
-
function namedKeyReplacementEndOffset(context) {
|
|
511
|
-
const token = context.attribute.syntax.tokenAtOffset(context.offset).rightBiased();
|
|
512
|
-
if (token?.kind === "Ident" && token.offset <= context.offset) return token.endOffset;
|
|
513
|
-
return context.offset;
|
|
514
|
-
}
|
|
515
|
-
function attributeSpec(context, source) {
|
|
516
|
-
return attributeSpecForName(context, source, context.attributeName);
|
|
517
|
-
}
|
|
518
|
-
function attributeSpecForName(context, source, name) {
|
|
519
|
-
return attributeSpecResolver(context, source)(name);
|
|
834
|
+
if (!input.clientSupportsSnippets || input.spec === void 0 || input.hasArgumentList) return input.name;
|
|
835
|
+
const required = requiredArgumentsSnippet(input.spec);
|
|
836
|
+
return required.length === 0 ? input.name : `${input.name}(${required})`;
|
|
520
837
|
}
|
|
521
838
|
function attributeSpecResolver(context, source) {
|
|
522
839
|
switch (context.kind) {
|
|
523
840
|
case "blockAttributeName":
|
|
524
|
-
case "blockAttributeNamedKey":
|
|
841
|
+
case "blockAttributeNamedKey":
|
|
842
|
+
case "blockAttributeArgumentSlot":
|
|
843
|
+
case "blockAttributeValue": {
|
|
525
844
|
const descriptor = findBlockDescriptor(source.pslBlockDescriptors, context.blockKeyword);
|
|
526
845
|
return (name) => {
|
|
527
846
|
const factory = descriptor?.attributes?.[name];
|
|
@@ -530,7 +849,9 @@ function attributeSpecResolver(context, source) {
|
|
|
530
849
|
};
|
|
531
850
|
}
|
|
532
851
|
case "modelAttributeName":
|
|
533
|
-
case "modelAttributeNamedKey":
|
|
852
|
+
case "modelAttributeNamedKey":
|
|
853
|
+
case "modelAttributeArgumentSlot":
|
|
854
|
+
case "modelAttributeValue": {
|
|
534
855
|
if (source.authoringContributions === void 0) return () => void 0;
|
|
535
856
|
const model = modelSymbolForNode(source.symbolTable, context.model);
|
|
536
857
|
if (model === void 0 || source.controlMutationDefaults === void 0) return () => void 0;
|
|
@@ -543,7 +864,9 @@ function attributeSpecResolver(context, source) {
|
|
|
543
864
|
return (name) => specs.model[name]?.(specContext);
|
|
544
865
|
}
|
|
545
866
|
case "fieldAttributeName":
|
|
546
|
-
case "fieldAttributeNamedKey":
|
|
867
|
+
case "fieldAttributeNamedKey":
|
|
868
|
+
case "fieldAttributeArgumentSlot":
|
|
869
|
+
case "fieldAttributeValue": {
|
|
547
870
|
if (source.authoringContributions === void 0) return () => void 0;
|
|
548
871
|
const model = modelSymbolForNode(source.symbolTable, context.model);
|
|
549
872
|
if (model === void 0 || source.controlMutationDefaults === void 0) return () => void 0;
|
|
@@ -562,29 +885,6 @@ function attributeSpecResolver(context, source) {
|
|
|
562
885
|
}
|
|
563
886
|
}
|
|
564
887
|
}
|
|
565
|
-
function existingAttributeNamedKeys(attribute, cursorOffset) {
|
|
566
|
-
const names = /* @__PURE__ */ new Set();
|
|
567
|
-
for (const arg of attribute.argList()?.args() ?? []) {
|
|
568
|
-
if (!arg.syntax.isOutside(cursorOffset)) continue;
|
|
569
|
-
const name = arg.name()?.name();
|
|
570
|
-
if (name !== void 0) names.add(name);
|
|
571
|
-
}
|
|
572
|
-
return names;
|
|
573
|
-
}
|
|
574
|
-
function modelSymbolForNode(symbolTable, node) {
|
|
575
|
-
const topLevelMatch = Object.values(symbolTable.topLevel.models).find((model) => sameSyntax(model.node.syntax, node.syntax));
|
|
576
|
-
if (topLevelMatch !== void 0) return topLevelMatch;
|
|
577
|
-
for (const namespace of Object.values(symbolTable.topLevel.namespaces)) {
|
|
578
|
-
const namespaceMatch = Object.values(namespace.models).find((model) => sameSyntax(model.node.syntax, node.syntax));
|
|
579
|
-
if (namespaceMatch !== void 0) return namespaceMatch;
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
function fieldSymbolForNode(model, node) {
|
|
583
|
-
return Object.values(model.fields).find((field) => sameSyntax(field.node.syntax, node.syntax));
|
|
584
|
-
}
|
|
585
|
-
function sameSyntax(left, right) {
|
|
586
|
-
return left.offset === right.offset && left.endOffset === right.endOffset;
|
|
587
|
-
}
|
|
588
888
|
function provideDeclarationKeywordCompletionItems(context, sourceFile, source, clientSupportsSnippets) {
|
|
589
889
|
const replacementRange = {
|
|
590
890
|
start: sourceFile.positionAt(context.replacementStartOffset),
|
|
@@ -1020,7 +1320,7 @@ function createProjectArtifacts(options) {
|
|
|
1020
1320
|
function createInterpretSlot(uri, computed) {
|
|
1021
1321
|
if (interpretation === void 0) return () => [];
|
|
1022
1322
|
let memo;
|
|
1023
|
-
|
|
1323
|
+
const interpretDiagnostics = () => {
|
|
1024
1324
|
if (memo === void 0) {
|
|
1025
1325
|
const result = interpretation.source.interpret({
|
|
1026
1326
|
document: computed.document,
|
|
@@ -1032,6 +1332,29 @@ function createProjectArtifacts(options) {
|
|
|
1032
1332
|
}
|
|
1033
1333
|
return memo;
|
|
1034
1334
|
};
|
|
1335
|
+
return () => {
|
|
1336
|
+
try {
|
|
1337
|
+
return interpretDiagnostics();
|
|
1338
|
+
} catch (error) {
|
|
1339
|
+
if (error instanceof ResponseError && (error.code === LSPErrorCodes.RequestCancelled || error.code === LSPErrorCodes.ServerCancelled || error.code === LSPErrorCodes.ContentModified)) throw error;
|
|
1340
|
+
options.onInterpretationError(uri, error);
|
|
1341
|
+
return [{
|
|
1342
|
+
range: {
|
|
1343
|
+
start: {
|
|
1344
|
+
line: 0,
|
|
1345
|
+
character: 0
|
|
1346
|
+
},
|
|
1347
|
+
end: {
|
|
1348
|
+
line: 0,
|
|
1349
|
+
character: 1
|
|
1350
|
+
}
|
|
1351
|
+
},
|
|
1352
|
+
code: "PRISMA_NEXT_INTERPRETATION_FAILED",
|
|
1353
|
+
message: "Semantic diagnostics are unavailable because of an internal error. A subsequent diagnostic request or edit will retry.",
|
|
1354
|
+
severity: ParseDiagnosticSeverity.Error
|
|
1355
|
+
}];
|
|
1356
|
+
}
|
|
1357
|
+
};
|
|
1035
1358
|
}
|
|
1036
1359
|
function drop(uri) {
|
|
1037
1360
|
if (documents.delete(uri)) symbolTable = void 0;
|
|
@@ -1578,6 +1901,10 @@ function createServerOn(connection) {
|
|
|
1578
1901
|
inputs: resolution.inputs,
|
|
1579
1902
|
controlStack: resolution.controlStack,
|
|
1580
1903
|
getText: (uri) => documents.get(uri)?.getText(),
|
|
1904
|
+
onInterpretationError: (uri, error) => {
|
|
1905
|
+
const detail = error instanceof Error ? error.stack ?? error.message : String(error);
|
|
1906
|
+
connection.console.error(`PSL interpretation failed for ${uri}: ${detail}`);
|
|
1907
|
+
},
|
|
1581
1908
|
...resolution.interpretation === void 0 ? {} : { interpretation: resolution.interpretation }
|
|
1582
1909
|
});
|
|
1583
1910
|
return {
|
|
@@ -1679,7 +2006,8 @@ function createServerOn(connection) {
|
|
|
1679
2006
|
...project.controlStack.authoringContributions === void 0 ? {} : { authoringContributions: project.controlStack.authoringContributions },
|
|
1680
2007
|
...project.controlStack.controlMutationDefaults === void 0 ? {} : { controlMutationDefaults: project.controlStack.controlMutationDefaults }
|
|
1681
2008
|
},
|
|
1682
|
-
clientSupportsSnippets: clientCapabilities.completionSnippets
|
|
2009
|
+
clientSupportsSnippets: clientCapabilities.completionSnippets,
|
|
2010
|
+
clientSupportsTriggerSuggestCommand: clientCapabilities.completionTriggerSuggestCommand
|
|
1683
2011
|
})];
|
|
1684
2012
|
} catch {
|
|
1685
2013
|
return [];
|
|
@@ -1698,7 +2026,15 @@ function createServerOn(connection) {
|
|
|
1698
2026
|
full: true,
|
|
1699
2027
|
range: true
|
|
1700
2028
|
},
|
|
1701
|
-
completionProvider: { triggerCharacters: [
|
|
2029
|
+
completionProvider: { triggerCharacters: [
|
|
2030
|
+
".",
|
|
2031
|
+
"@",
|
|
2032
|
+
"[",
|
|
2033
|
+
"(",
|
|
2034
|
+
"{",
|
|
2035
|
+
":",
|
|
2036
|
+
","
|
|
2037
|
+
] },
|
|
1702
2038
|
...clientCapabilities.pullDiagnostics ? { diagnosticProvider: {
|
|
1703
2039
|
interFileDependencies: false,
|
|
1704
2040
|
workspaceDiagnostics: false
|
|
@@ -1817,6 +2153,7 @@ function toLspSeverity(severity) {
|
|
|
1817
2153
|
const noClientCapabilities = {
|
|
1818
2154
|
watchedFilesRegistration: false,
|
|
1819
2155
|
completionSnippets: false,
|
|
2156
|
+
completionTriggerSuggestCommand: false,
|
|
1820
2157
|
pullDiagnostics: false,
|
|
1821
2158
|
diagnosticsRefresh: false
|
|
1822
2159
|
};
|
|
@@ -1824,10 +2161,16 @@ function resolveClientCapabilities(params) {
|
|
|
1824
2161
|
return {
|
|
1825
2162
|
watchedFilesRegistration: params.capabilities.workspace?.didChangeWatchedFiles?.dynamicRegistration === true,
|
|
1826
2163
|
completionSnippets: params.capabilities.textDocument?.completion?.completionItem?.snippetSupport === true,
|
|
2164
|
+
completionTriggerSuggestCommand: supportsCompletionTriggerSuggest(params.initializationOptions),
|
|
1827
2165
|
pullDiagnostics: params.capabilities.textDocument?.diagnostic !== void 0,
|
|
1828
2166
|
diagnosticsRefresh: params.capabilities.workspace?.diagnostics?.refreshSupport === true
|
|
1829
2167
|
};
|
|
1830
2168
|
}
|
|
2169
|
+
function supportsCompletionTriggerSuggest(options) {
|
|
2170
|
+
if (typeof options !== "object" || options === null || !("completion" in options)) return false;
|
|
2171
|
+
const completion = options.completion;
|
|
2172
|
+
return typeof completion === "object" && completion !== null && "supportsTriggerSuggestCommand" in completion && completion.supportsTriggerSuggestCommand === true;
|
|
2173
|
+
}
|
|
1831
2174
|
function resolveRootPath(params) {
|
|
1832
2175
|
const workspaceFolder = params.workspaceFolders?.[0];
|
|
1833
2176
|
if (workspaceFolder !== void 0) return fileURLToPath(workspaceFolder.uri);
|
|
@@ -2091,4 +2434,4 @@ function startServer(streams) {
|
|
|
2091
2434
|
//#endregion
|
|
2092
2435
|
export { startServer };
|
|
2093
2436
|
|
|
2094
|
-
//# sourceMappingURL=exports-
|
|
2437
|
+
//# sourceMappingURL=exports-B8peSdx4.mjs.map
|