@player-tools/json-language-service 0.13.0-next.4 → 0.13.0-next.5
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/cjs/index.cjs +440 -35
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/index.legacy-esm.js +430 -26
- package/dist/index.mjs +430 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/__tests__/__snapshots__/service.test.ts.snap +5 -15
- package/src/__tests__/service.test.ts +1 -28
- package/src/constants.ts +2 -0
- package/src/plugins/__tests__/asset-wrapper-array-plugin.test.ts +2 -2
- package/src/plugins/__tests__/missing-asset-wrapper-plugin.test.ts +2 -2
- package/src/plugins/__tests__/schema-validation-plugin.test.ts +1923 -0
- package/src/plugins/schema-validation-plugin.ts +508 -0
- package/src/plugins/xlr-plugin.ts +2 -21
- package/src/utils.ts +20 -0
- package/src/xlr/registry.ts +6 -1
- package/types/plugins/schema-validation-plugin.d.ts +12 -0
- package/types/plugins/xlr-plugin.d.ts +7 -0
- package/types/utils.d.ts +3 -0
package/dist/cjs/index.cjs
CHANGED
|
@@ -58,6 +58,7 @@ __export(src_exports, {
|
|
|
58
58
|
applyTemplateProperty: () => applyTemplateProperty,
|
|
59
59
|
applyValueRefs: () => applyValueRefs,
|
|
60
60
|
containsRange: () => containsRange,
|
|
61
|
+
findErrorNode: () => findErrorNode,
|
|
61
62
|
formatLikeNode: () => formatLikeNode,
|
|
62
63
|
getContentNode: () => getContentNode,
|
|
63
64
|
getLSLocationOfNode: () => getLSLocationOfNode,
|
|
@@ -89,7 +90,7 @@ __export(src_exports, {
|
|
|
89
90
|
module.exports = __toCommonJS(src_exports);
|
|
90
91
|
var import_jsonc_parser4 = require("jsonc-parser");
|
|
91
92
|
var import_tapable_ts = require("tapable-ts");
|
|
92
|
-
var
|
|
93
|
+
var import_vscode_languageserver_types12 = require("vscode-languageserver-types");
|
|
93
94
|
|
|
94
95
|
// ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/json-language-service/src/plugins/asset-wrapper-array-plugin.ts
|
|
95
96
|
var import_vscode_languageserver_types4 = require("vscode-languageserver-types");
|
|
@@ -760,6 +761,19 @@ function mapFlowStateToType(flowType) {
|
|
|
760
761
|
}
|
|
761
762
|
return flowXLR;
|
|
762
763
|
}
|
|
764
|
+
var findErrorNode = (rootNode, nodeToFind) => {
|
|
765
|
+
const children = [rootNode];
|
|
766
|
+
while (children.length > 0) {
|
|
767
|
+
const child = children.pop();
|
|
768
|
+
if (child.jsonNode === nodeToFind) {
|
|
769
|
+
return child;
|
|
770
|
+
}
|
|
771
|
+
if (child.children) {
|
|
772
|
+
children.push(...child.children);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
return rootNode;
|
|
776
|
+
};
|
|
763
777
|
|
|
764
778
|
// ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/json-language-service/src/plugins/asset-wrapper-array-plugin.ts
|
|
765
779
|
var isInView = (node) => {
|
|
@@ -1007,19 +1021,6 @@ var import_vscode_languageserver_types6 = require("vscode-languageserver-types")
|
|
|
1007
1021
|
function isError(issue) {
|
|
1008
1022
|
return issue.severity === import_vscode_languageserver_types6.DiagnosticSeverity.Error;
|
|
1009
1023
|
}
|
|
1010
|
-
var findErrorNode = (rootNode, nodeToFind) => {
|
|
1011
|
-
const children = [rootNode];
|
|
1012
|
-
while (children.length > 0) {
|
|
1013
|
-
const child = children.pop();
|
|
1014
|
-
if (child.jsonNode === nodeToFind) {
|
|
1015
|
-
return child;
|
|
1016
|
-
}
|
|
1017
|
-
if (child.children) {
|
|
1018
|
-
children.push(...child.children);
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
return rootNode;
|
|
1022
|
-
};
|
|
1023
1024
|
var translateSeverity = (severity) => {
|
|
1024
1025
|
return severity;
|
|
1025
1026
|
};
|
|
@@ -1271,8 +1272,409 @@ var XLRPlugin = class {
|
|
|
1271
1272
|
}
|
|
1272
1273
|
};
|
|
1273
1274
|
|
|
1274
|
-
// ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/json-language-service/src/plugins/
|
|
1275
|
+
// ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/json-language-service/src/plugins/schema-validation-plugin.ts
|
|
1275
1276
|
var import_vscode_languageserver_types7 = require("vscode-languageserver-types");
|
|
1277
|
+
var import_xlr_utils = require("@player-tools/xlr-utils");
|
|
1278
|
+
function formatErrorMessage(message) {
|
|
1279
|
+
return `Schema Validation Error: ${message}`;
|
|
1280
|
+
}
|
|
1281
|
+
function makeValidationRefObject(baseObject, validationFunction) {
|
|
1282
|
+
return {
|
|
1283
|
+
...baseObject,
|
|
1284
|
+
properties: {
|
|
1285
|
+
...baseObject.properties,
|
|
1286
|
+
...validationFunction.properties
|
|
1287
|
+
},
|
|
1288
|
+
additionalProperties: false
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
function validateSchemaValidations(validationNode, sdk, validationContext) {
|
|
1292
|
+
const claimedValidator = getProperty(validationNode, "type");
|
|
1293
|
+
if (!claimedValidator) {
|
|
1294
|
+
validationContext.addViolation({
|
|
1295
|
+
node: validationNode,
|
|
1296
|
+
message: formatErrorMessage('Validation object missing "type" property'),
|
|
1297
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1298
|
+
});
|
|
1299
|
+
} else if (claimedValidator.valueNode?.type !== "string") {
|
|
1300
|
+
validationContext.addViolation({
|
|
1301
|
+
node: claimedValidator.valueNode ?? validationNode,
|
|
1302
|
+
message: formatErrorMessage("Validation type must be a string"),
|
|
1303
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1304
|
+
});
|
|
1305
|
+
} else {
|
|
1306
|
+
const validationXLR = sdk.getType(claimedValidator.valueNode.value, {
|
|
1307
|
+
getRawType: true
|
|
1308
|
+
});
|
|
1309
|
+
if (!validationXLR) {
|
|
1310
|
+
validationContext.addViolation({
|
|
1311
|
+
node: validationNode,
|
|
1312
|
+
message: formatErrorMessage(
|
|
1313
|
+
`Validation Function ${claimedValidator} is not a registered validator`
|
|
1314
|
+
),
|
|
1315
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1316
|
+
});
|
|
1317
|
+
} else {
|
|
1318
|
+
const valRef = sdk.getType("Validation.Reference", {
|
|
1319
|
+
getRawType: true
|
|
1320
|
+
});
|
|
1321
|
+
if (valRef) {
|
|
1322
|
+
let validationIssues;
|
|
1323
|
+
const validatorFunctionProps = validationXLR.genericArguments?.[0];
|
|
1324
|
+
if (!validatorFunctionProps || (0, import_xlr_utils.isObjectType)(validatorFunctionProps)) {
|
|
1325
|
+
validationIssues = sdk.validateByType(
|
|
1326
|
+
makeValidationRefObject(
|
|
1327
|
+
valRef,
|
|
1328
|
+
validatorFunctionProps ?? {}
|
|
1329
|
+
),
|
|
1330
|
+
validationNode.jsonNode
|
|
1331
|
+
);
|
|
1332
|
+
validationIssues.forEach((issue) => {
|
|
1333
|
+
validationContext.addViolation({
|
|
1334
|
+
node: validationNode,
|
|
1335
|
+
message: formatErrorMessage(issue.message),
|
|
1336
|
+
severity: translateSeverity(issue.severity)
|
|
1337
|
+
});
|
|
1338
|
+
});
|
|
1339
|
+
} else {
|
|
1340
|
+
const validationResults = validatorFunctionProps.or.map((node) => {
|
|
1341
|
+
if ((0, import_xlr_utils.isObjectType)(node)) {
|
|
1342
|
+
return sdk.validateByType(
|
|
1343
|
+
makeValidationRefObject(valRef, node),
|
|
1344
|
+
validationNode.jsonNode
|
|
1345
|
+
);
|
|
1346
|
+
} else {
|
|
1347
|
+
validationIssues.forEach((issue) => {
|
|
1348
|
+
validationContext.addViolation({
|
|
1349
|
+
node: validationNode,
|
|
1350
|
+
message: formatErrorMessage(
|
|
1351
|
+
`Internal Error - Validation function ${validationXLR.name} type argument is not an object`
|
|
1352
|
+
),
|
|
1353
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1354
|
+
});
|
|
1355
|
+
});
|
|
1356
|
+
return null;
|
|
1357
|
+
}
|
|
1358
|
+
}).filter((o) => o !== null && Array.isArray(o) && o.length === 0);
|
|
1359
|
+
if (validationResults.length !== 1) {
|
|
1360
|
+
validationContext.addViolation({
|
|
1361
|
+
node: validationNode,
|
|
1362
|
+
message: formatErrorMessage(
|
|
1363
|
+
`Validation function invalid function parameters for type ${validationXLR.name}`
|
|
1364
|
+
),
|
|
1365
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1366
|
+
});
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
} else {
|
|
1370
|
+
validationContext.addViolation({
|
|
1371
|
+
node: validationNode,
|
|
1372
|
+
message: formatErrorMessage(
|
|
1373
|
+
"Validation.Reference from @player-ui/types is not loaded into SDK"
|
|
1374
|
+
),
|
|
1375
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1376
|
+
});
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
function validateSchemaFormat(formatNode, sdk, validationContext) {
|
|
1382
|
+
const claimedFormatter = getProperty(formatNode, "type");
|
|
1383
|
+
if (!claimedFormatter) {
|
|
1384
|
+
validationContext.addViolation({
|
|
1385
|
+
node: formatNode,
|
|
1386
|
+
message: formatErrorMessage('Format object missing "type" property'),
|
|
1387
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1388
|
+
});
|
|
1389
|
+
} else if (claimedFormatter.valueNode?.type !== "string") {
|
|
1390
|
+
validationContext.addViolation({
|
|
1391
|
+
node: claimedFormatter.valueNode ?? claimedFormatter,
|
|
1392
|
+
message: formatErrorMessage("Format type must be a string"),
|
|
1393
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1394
|
+
});
|
|
1395
|
+
} else {
|
|
1396
|
+
const formatterXLR = sdk.getType(claimedFormatter.valueNode.value, {
|
|
1397
|
+
getRawType: true
|
|
1398
|
+
});
|
|
1399
|
+
if (!formatterXLR) {
|
|
1400
|
+
validationContext.addViolation({
|
|
1401
|
+
node: formatNode,
|
|
1402
|
+
message: formatErrorMessage(
|
|
1403
|
+
`Formatter ${claimedFormatter} is not a registered formatter`
|
|
1404
|
+
),
|
|
1405
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1406
|
+
});
|
|
1407
|
+
} else if (formatterXLR.genericArguments && formatterXLR.genericArguments.length === 3) {
|
|
1408
|
+
const otherArgsXLR = formatterXLR.genericArguments[2];
|
|
1409
|
+
const validationIssues = sdk.validateByType(
|
|
1410
|
+
{
|
|
1411
|
+
...otherArgsXLR,
|
|
1412
|
+
properties: {
|
|
1413
|
+
...otherArgsXLR.properties,
|
|
1414
|
+
type: {
|
|
1415
|
+
required: true,
|
|
1416
|
+
node: {
|
|
1417
|
+
type: "string",
|
|
1418
|
+
const: claimedFormatter.valueNode.value
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
},
|
|
1423
|
+
formatNode.jsonNode
|
|
1424
|
+
);
|
|
1425
|
+
validationIssues.forEach((issue) => {
|
|
1426
|
+
validationContext.addViolation({
|
|
1427
|
+
node: formatNode,
|
|
1428
|
+
message: formatErrorMessage(issue.message),
|
|
1429
|
+
severity: translateSeverity(issue.severity)
|
|
1430
|
+
});
|
|
1431
|
+
});
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
function getSchemaTypeNames(schemaObj) {
|
|
1436
|
+
const names = /* @__PURE__ */ new Set();
|
|
1437
|
+
for (const prop of schemaObj.properties) {
|
|
1438
|
+
const key = prop.keyNode?.value;
|
|
1439
|
+
if (typeof key === "string") {
|
|
1440
|
+
names.add(key);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
return names;
|
|
1444
|
+
}
|
|
1445
|
+
function validateDataTypeStructure(dataTypeNode, claimedDataType, sdk, validationContext) {
|
|
1446
|
+
const validationProp = getProperty(dataTypeNode, "validation");
|
|
1447
|
+
if (validationProp?.valueNode && validationProp.valueNode.type !== "array") {
|
|
1448
|
+
validationContext.addViolation({
|
|
1449
|
+
node: validationProp.valueNode,
|
|
1450
|
+
message: formatErrorMessage(
|
|
1451
|
+
'Schema.DataType "validation" must be an array.'
|
|
1452
|
+
),
|
|
1453
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1454
|
+
});
|
|
1455
|
+
} else if (validationProp?.valueNode) {
|
|
1456
|
+
validationProp.valueNode.children?.forEach((valRef) => {
|
|
1457
|
+
if (valRef && valRef.type === "object") {
|
|
1458
|
+
validateSchemaValidations(valRef, sdk, validationContext);
|
|
1459
|
+
} else {
|
|
1460
|
+
validationContext.addViolation({
|
|
1461
|
+
node: validationProp.valueNode ?? dataTypeNode,
|
|
1462
|
+
message: formatErrorMessage(
|
|
1463
|
+
'Schema.DataType "validation" must be an object.'
|
|
1464
|
+
),
|
|
1465
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1468
|
+
});
|
|
1469
|
+
}
|
|
1470
|
+
const formatProp = getProperty(dataTypeNode, "format");
|
|
1471
|
+
if (formatProp?.valueNode?.type === "object") {
|
|
1472
|
+
validateSchemaFormat(formatProp.valueNode, sdk, validationContext);
|
|
1473
|
+
} else {
|
|
1474
|
+
if (formatProp) {
|
|
1475
|
+
validationContext.addViolation({
|
|
1476
|
+
node: formatProp?.valueNode ?? dataTypeNode,
|
|
1477
|
+
message: formatErrorMessage(
|
|
1478
|
+
'Schema.DataType "format" must be an object.'
|
|
1479
|
+
),
|
|
1480
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
const defaultNode = claimedDataType.properties?.["default"]?.node;
|
|
1485
|
+
const defaultProp = getProperty(dataTypeNode, "default");
|
|
1486
|
+
if (defaultNode && defaultProp?.valueNode) {
|
|
1487
|
+
if ((0, import_xlr_utils.isPrimitiveTypeNode)(defaultNode)) {
|
|
1488
|
+
if (defaultProp.valueNode.type !== defaultNode.type) {
|
|
1489
|
+
validationContext.addViolation({
|
|
1490
|
+
node: defaultProp.valueNode,
|
|
1491
|
+
message: formatErrorMessage(
|
|
1492
|
+
`Default value doesn't match the expected type of ${defaultNode.type} for type ${claimedDataType.name}`
|
|
1493
|
+
),
|
|
1494
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1495
|
+
});
|
|
1496
|
+
}
|
|
1497
|
+
} else if (defaultNode.type === "or") {
|
|
1498
|
+
if (!defaultNode.or.some((n) => n.type === defaultProp.valueNode?.type)) {
|
|
1499
|
+
validationContext.addViolation({
|
|
1500
|
+
node: defaultProp.valueNode,
|
|
1501
|
+
message: formatErrorMessage(
|
|
1502
|
+
`Default value doesn't match any of the expected types ${defaultNode.or.map((t) => t.type).join(", ")} for type ${claimedDataType.name}`
|
|
1503
|
+
),
|
|
1504
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
} else {
|
|
1508
|
+
validationContext.addViolation({
|
|
1509
|
+
node: defaultProp.valueNode,
|
|
1510
|
+
message: formatErrorMessage(
|
|
1511
|
+
`Unknown default node type ${defaultNode.type}`
|
|
1512
|
+
),
|
|
1513
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
const isArrayProp = getProperty(dataTypeNode, "isArray");
|
|
1518
|
+
const isRecordProp = getProperty(dataTypeNode, "isRecord");
|
|
1519
|
+
if (isArrayProp?.valueNode && isArrayProp.valueNode.type !== "boolean") {
|
|
1520
|
+
validationContext.addViolation({
|
|
1521
|
+
node: isArrayProp.valueNode,
|
|
1522
|
+
message: formatErrorMessage(
|
|
1523
|
+
'Schema.DataType "isArray" must be a boolean.'
|
|
1524
|
+
),
|
|
1525
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1526
|
+
});
|
|
1527
|
+
}
|
|
1528
|
+
if (isRecordProp?.valueNode && isRecordProp.valueNode.type !== "boolean") {
|
|
1529
|
+
validationContext.addViolation({
|
|
1530
|
+
node: isRecordProp.valueNode,
|
|
1531
|
+
message: formatErrorMessage(
|
|
1532
|
+
'Schema.DataType "isRecord" must be a boolean.'
|
|
1533
|
+
),
|
|
1534
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1535
|
+
});
|
|
1536
|
+
}
|
|
1537
|
+
if (isArrayProp?.valueNode && isRecordProp?.valueNode && isArrayProp.valueNode.value === true && isRecordProp.valueNode.value === true) {
|
|
1538
|
+
validationContext.addViolation({
|
|
1539
|
+
node: dataTypeNode,
|
|
1540
|
+
message: formatErrorMessage(
|
|
1541
|
+
'Schema.DataType cannot have both "isArray" and "isRecord" true.'
|
|
1542
|
+
),
|
|
1543
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1544
|
+
});
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
function validateSchemaNode(node, schemaTypeNames, sdk, validationContext) {
|
|
1548
|
+
for (const prop of node.properties) {
|
|
1549
|
+
const valueNode = prop.valueNode;
|
|
1550
|
+
if (!(valueNode && valueNode.type === "object")) {
|
|
1551
|
+
if (valueNode) {
|
|
1552
|
+
validationContext.addViolation({
|
|
1553
|
+
node: valueNode,
|
|
1554
|
+
message: formatErrorMessage(
|
|
1555
|
+
`Schema property "${prop.keyNode.value}" must be an object (Schema.DataType) with a "type" field.`
|
|
1556
|
+
),
|
|
1557
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
continue;
|
|
1561
|
+
}
|
|
1562
|
+
const dataTypeNode = valueNode;
|
|
1563
|
+
const typeProp = getProperty(dataTypeNode, "type");
|
|
1564
|
+
if (!typeProp) {
|
|
1565
|
+
validationContext.addViolation({
|
|
1566
|
+
node: valueNode,
|
|
1567
|
+
message: formatErrorMessage(
|
|
1568
|
+
'Schema.DataType must have a "type" property (reference to schema or XLR type).'
|
|
1569
|
+
),
|
|
1570
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1571
|
+
});
|
|
1572
|
+
continue;
|
|
1573
|
+
}
|
|
1574
|
+
const typeValueNode = typeProp.valueNode;
|
|
1575
|
+
if (!typeValueNode || typeValueNode.type !== "string") {
|
|
1576
|
+
validationContext.addViolation({
|
|
1577
|
+
node: typeValueNode ?? typeProp,
|
|
1578
|
+
message: formatErrorMessage(
|
|
1579
|
+
'Schema "type" must be a string (schema type name or XLR type name).'
|
|
1580
|
+
),
|
|
1581
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1582
|
+
});
|
|
1583
|
+
continue;
|
|
1584
|
+
}
|
|
1585
|
+
const typeName = typeValueNode.value;
|
|
1586
|
+
const isSchemaType = schemaTypeNames.has(typeName);
|
|
1587
|
+
const XLRType = sdk.getType(typeName, { getRawType: true });
|
|
1588
|
+
if (!isSchemaType && !XLRType) {
|
|
1589
|
+
validationContext.addViolation({
|
|
1590
|
+
node: typeValueNode,
|
|
1591
|
+
message: formatErrorMessage(
|
|
1592
|
+
`Unknown schema type "${typeName}". Type must be a schema type (key in this schema) or an XLR type loaded in the SDK.`
|
|
1593
|
+
),
|
|
1594
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1595
|
+
});
|
|
1596
|
+
} else if (XLRType) {
|
|
1597
|
+
validateDataTypeStructure(
|
|
1598
|
+
dataTypeNode,
|
|
1599
|
+
XLRType,
|
|
1600
|
+
sdk,
|
|
1601
|
+
validationContext
|
|
1602
|
+
);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
function validateFlowSchema(contentNode, sdk, validationContext) {
|
|
1607
|
+
const schemaProp = getProperty(contentNode, "schema");
|
|
1608
|
+
if (!schemaProp?.valueNode) {
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
const schemaValue = schemaProp.valueNode;
|
|
1612
|
+
if (schemaValue.type !== "object") {
|
|
1613
|
+
validationContext.addViolation({
|
|
1614
|
+
node: schemaValue,
|
|
1615
|
+
message: formatErrorMessage(
|
|
1616
|
+
'Flow "schema" must be an object with at least a "ROOT" key.'
|
|
1617
|
+
),
|
|
1618
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1619
|
+
});
|
|
1620
|
+
return;
|
|
1621
|
+
}
|
|
1622
|
+
const schemaObj = schemaValue;
|
|
1623
|
+
const hasRoot = schemaObj.properties.some((p) => p.keyNode.value === "ROOT");
|
|
1624
|
+
if (!hasRoot) {
|
|
1625
|
+
validationContext.addViolation({
|
|
1626
|
+
node: schemaValue,
|
|
1627
|
+
message: formatErrorMessage('Schema must have a "ROOT" key.'),
|
|
1628
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1629
|
+
});
|
|
1630
|
+
}
|
|
1631
|
+
const schemaTypeNames = getSchemaTypeNames(schemaObj);
|
|
1632
|
+
for (const prop of schemaObj.properties) {
|
|
1633
|
+
const nodeValue = prop.valueNode;
|
|
1634
|
+
if (!nodeValue || nodeValue.type !== "object") {
|
|
1635
|
+
if (nodeValue) {
|
|
1636
|
+
validationContext.addViolation({
|
|
1637
|
+
node: nodeValue,
|
|
1638
|
+
message: formatErrorMessage(
|
|
1639
|
+
`Schema node "${prop.keyNode.value}" must be an object.`
|
|
1640
|
+
),
|
|
1641
|
+
severity: import_vscode_languageserver_types7.DiagnosticSeverity.Error
|
|
1642
|
+
});
|
|
1643
|
+
}
|
|
1644
|
+
continue;
|
|
1645
|
+
}
|
|
1646
|
+
validateSchemaNode(
|
|
1647
|
+
nodeValue,
|
|
1648
|
+
schemaTypeNames,
|
|
1649
|
+
sdk,
|
|
1650
|
+
validationContext
|
|
1651
|
+
);
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
var SchemaValidationPlugin = class {
|
|
1655
|
+
name = "schema-validation";
|
|
1656
|
+
/** Resolved when CommonTypes have been loaded into the XLR SDK (once per plugin apply) */
|
|
1657
|
+
commonTypesLoaded = null;
|
|
1658
|
+
apply(service) {
|
|
1659
|
+
service.hooks.validate.tap(this.name, async (_ctx, validationContext) => {
|
|
1660
|
+
await this.commonTypesLoaded;
|
|
1661
|
+
validationContext.useASTVisitor(
|
|
1662
|
+
this.createValidationVisitor(service, validationContext)
|
|
1663
|
+
);
|
|
1664
|
+
});
|
|
1665
|
+
}
|
|
1666
|
+
createValidationVisitor(service, validationContext) {
|
|
1667
|
+
const sdk = service.XLRService.XLRSDK;
|
|
1668
|
+
return {
|
|
1669
|
+
ContentNode: (contentNode) => {
|
|
1670
|
+
validateFlowSchema(contentNode, sdk, validationContext);
|
|
1671
|
+
}
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
};
|
|
1675
|
+
|
|
1676
|
+
// ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/json-language-service/src/plugins/duplicate-id-plugin.ts
|
|
1677
|
+
var import_vscode_languageserver_types8 = require("vscode-languageserver-types");
|
|
1276
1678
|
var checkParentTemplate = (node, depth = 0) => {
|
|
1277
1679
|
if (node.parent) {
|
|
1278
1680
|
if (isPropertyNode(node.parent) && node.parent.keyNode.value === "template") {
|
|
@@ -1303,7 +1705,7 @@ var createViolation = (node) => {
|
|
|
1303
1705
|
}
|
|
1304
1706
|
return {
|
|
1305
1707
|
node: valueNode,
|
|
1306
|
-
severity:
|
|
1708
|
+
severity: import_vscode_languageserver_types8.DiagnosticSeverity.Error,
|
|
1307
1709
|
message: `The id "${node.id?.valueNode?.value}" is already in use in this view.`,
|
|
1308
1710
|
fix: () => {
|
|
1309
1711
|
return {
|
|
@@ -1345,7 +1747,7 @@ var createValidationVisitor2 = (ctx) => {
|
|
|
1345
1747
|
if (missingIndexSegments.length !== 0) {
|
|
1346
1748
|
ctx.addViolation({
|
|
1347
1749
|
node: assetNode,
|
|
1348
|
-
severity:
|
|
1750
|
+
severity: import_vscode_languageserver_types8.DiagnosticSeverity.Error,
|
|
1349
1751
|
message: `The id for this templated elements is missing the following index segments: ${missingIndexSegments.join(
|
|
1350
1752
|
", "
|
|
1351
1753
|
)}`
|
|
@@ -1380,7 +1782,7 @@ var DuplicateIDPlugin = class {
|
|
|
1380
1782
|
};
|
|
1381
1783
|
|
|
1382
1784
|
// ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/json-language-service/src/plugins/missing-asset-wrapper-plugin.ts
|
|
1383
|
-
var
|
|
1785
|
+
var import_vscode_languageserver_types9 = require("vscode-languageserver-types");
|
|
1384
1786
|
var getObjectTarget = (node) => {
|
|
1385
1787
|
if (isObjectNode(node)) {
|
|
1386
1788
|
return node;
|
|
@@ -1416,7 +1818,7 @@ var MissingAssetWrapperPlugin = class {
|
|
|
1416
1818
|
addFixableViolation(d, {
|
|
1417
1819
|
node: originalNode,
|
|
1418
1820
|
message: d.message,
|
|
1419
|
-
severity: d.severity ??
|
|
1821
|
+
severity: d.severity ?? import_vscode_languageserver_types9.DiagnosticSeverity.Error,
|
|
1420
1822
|
fix: () => ({
|
|
1421
1823
|
name: `Wrap in "asset"`,
|
|
1422
1824
|
edit: {
|
|
@@ -1440,7 +1842,7 @@ var MissingAssetWrapperPlugin = class {
|
|
|
1440
1842
|
};
|
|
1441
1843
|
|
|
1442
1844
|
// ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/json-language-service/src/plugins/nav-state-plugin.ts
|
|
1443
|
-
var
|
|
1845
|
+
var import_vscode_languageserver_types10 = require("vscode-languageserver-types");
|
|
1444
1846
|
var createValidationVisitor3 = (ctx) => {
|
|
1445
1847
|
const validTransitions = /* @__PURE__ */ new Map();
|
|
1446
1848
|
return {
|
|
@@ -1467,7 +1869,7 @@ var createValidationVisitor3 = (ctx) => {
|
|
|
1467
1869
|
if (!validTransitions.get(flowNodeId)?.has(transitionObjects.valueNode.value)) {
|
|
1468
1870
|
ctx.addViolation({
|
|
1469
1871
|
node: transitionObjects.valueNode,
|
|
1470
|
-
severity:
|
|
1872
|
+
severity: import_vscode_languageserver_types10.DiagnosticSeverity.Error,
|
|
1471
1873
|
message: `Node "${transitionObjects.valueNode.value}" not found`
|
|
1472
1874
|
});
|
|
1473
1875
|
}
|
|
@@ -1501,7 +1903,7 @@ var NavStatePlugin = class {
|
|
|
1501
1903
|
const flowNode = getFlowNode(ctx.node);
|
|
1502
1904
|
flowNode?.states.forEach((p) => {
|
|
1503
1905
|
completionCtx.addCompletionItem({
|
|
1504
|
-
kind:
|
|
1906
|
+
kind: import_vscode_languageserver_types10.CompletionItemKind.Value,
|
|
1505
1907
|
label: p.keyNode.value
|
|
1506
1908
|
});
|
|
1507
1909
|
});
|
|
@@ -1526,7 +1928,7 @@ var NavStatePlugin = class {
|
|
|
1526
1928
|
};
|
|
1527
1929
|
|
|
1528
1930
|
// ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/json-language-service/src/plugins/view-node-plugin.ts
|
|
1529
|
-
var
|
|
1931
|
+
var import_vscode_languageserver_types11 = require("vscode-languageserver-types");
|
|
1530
1932
|
var createValidationVisitor4 = (ctx, viewInfo) => {
|
|
1531
1933
|
return {
|
|
1532
1934
|
FlowStateNode: (flowState) => {
|
|
@@ -1542,7 +1944,7 @@ var createValidationVisitor4 = (ctx, viewInfo) => {
|
|
|
1542
1944
|
ctx.addViolation({
|
|
1543
1945
|
node: refNode.valueNode,
|
|
1544
1946
|
message: `View with id: ${refID} does not exist.`,
|
|
1545
|
-
severity:
|
|
1947
|
+
severity: import_vscode_languageserver_types11.DiagnosticSeverity.Error
|
|
1546
1948
|
});
|
|
1547
1949
|
}
|
|
1548
1950
|
},
|
|
@@ -1552,7 +1954,7 @@ var createValidationVisitor4 = (ctx, viewInfo) => {
|
|
|
1552
1954
|
ctx.addViolation({
|
|
1553
1955
|
node: viewNode.id.valueNode,
|
|
1554
1956
|
message: `View is not reachable`,
|
|
1555
|
-
severity:
|
|
1957
|
+
severity: import_vscode_languageserver_types11.DiagnosticSeverity.Warning
|
|
1556
1958
|
});
|
|
1557
1959
|
}
|
|
1558
1960
|
}
|
|
@@ -1614,14 +2016,14 @@ var ViewNodePlugin = class {
|
|
|
1614
2016
|
if (ctx.node.type === "string" && isPropertyNode(ctx.node.parent) && isStateNode(ctx.node.parent.parent) && ctx.node.parent.keyNode.value === "ref") {
|
|
1615
2017
|
Array.from(viewInfo?.views.keys() ?? []).forEach((vID) => {
|
|
1616
2018
|
completionCtx.addCompletionItem({
|
|
1617
|
-
kind:
|
|
2019
|
+
kind: import_vscode_languageserver_types11.CompletionItemKind.Value,
|
|
1618
2020
|
label: vID
|
|
1619
2021
|
});
|
|
1620
2022
|
});
|
|
1621
2023
|
} else if (ctx.node.type === "string" && isPropertyNode(ctx.node.parent) && isViewNode(ctx.node.parent.parent) && ctx.node.parent.keyNode.value === "id") {
|
|
1622
2024
|
Array.from(viewInfo?.nodes.keys() ?? []).forEach((vID) => {
|
|
1623
2025
|
completionCtx.addCompletionItem({
|
|
1624
|
-
kind:
|
|
2026
|
+
kind: import_vscode_languageserver_types11.CompletionItemKind.Value,
|
|
1625
2027
|
label: vID
|
|
1626
2028
|
});
|
|
1627
2029
|
});
|
|
@@ -1652,7 +2054,7 @@ var ViewNodePlugin = class {
|
|
|
1652
2054
|
|
|
1653
2055
|
// ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/json-language-service/src/xlr/transforms.ts
|
|
1654
2056
|
var import_xlr_sdk = require("@player-tools/xlr-sdk");
|
|
1655
|
-
var
|
|
2057
|
+
var import_xlr_utils2 = require("@player-tools/xlr-utils");
|
|
1656
2058
|
var applyCommonProps = (node, capability) => {
|
|
1657
2059
|
return (0, import_xlr_sdk.simpleTransformGenerator)("object", ["Assets", "Views"], (xlrNode) => {
|
|
1658
2060
|
if (!xlrNode.properties.applicability) {
|
|
@@ -1717,7 +2119,7 @@ var applyValueRefs = (node, capability) => {
|
|
|
1717
2119
|
type: "ref",
|
|
1718
2120
|
ref: "BindingRef"
|
|
1719
2121
|
});
|
|
1720
|
-
} else if ((0,
|
|
2122
|
+
} else if ((0, import_xlr_utils2.isPrimitiveTypeNode)(value.node)) {
|
|
1721
2123
|
const newUnionType = {
|
|
1722
2124
|
type: "or",
|
|
1723
2125
|
description: value.node.description,
|
|
@@ -1785,6 +2187,7 @@ var PLUGINS = [
|
|
|
1785
2187
|
new DuplicateIDPlugin(),
|
|
1786
2188
|
new ViewNodePlugin(),
|
|
1787
2189
|
new SchemaInfoPlugin(),
|
|
2190
|
+
new SchemaValidationPlugin(),
|
|
1788
2191
|
new AssetWrapperArrayPlugin(),
|
|
1789
2192
|
new NavStatePlugin(),
|
|
1790
2193
|
new MissingAssetWrapperPlugin(),
|
|
@@ -1802,6 +2205,7 @@ var TRANSFORM_FUNCTIONS = [
|
|
|
1802
2205
|
|
|
1803
2206
|
// ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/json-language-service/src/xlr/registry.ts
|
|
1804
2207
|
var import_xlr_sdk2 = require("@player-tools/xlr-sdk");
|
|
2208
|
+
var SINGLE_INSTANCE_CAPABILITIES = ["DataTypes", "Formatters", "Validators"];
|
|
1805
2209
|
var PlayerXLRRegistry = class extends import_xlr_sdk2.BasicXLRRegistry {
|
|
1806
2210
|
/** Keeps the mapping of how a type is referenced by Player to the underlying XLR */
|
|
1807
2211
|
registrationMap;
|
|
@@ -1832,7 +2236,7 @@ var PlayerXLRRegistry = class extends import_xlr_sdk2.BasicXLRRegistry {
|
|
|
1832
2236
|
this.registrationMap.set(registeredName, type.name);
|
|
1833
2237
|
registeredName = type.extends.genericArguments[0].const;
|
|
1834
2238
|
}
|
|
1835
|
-
if (this.registrationMap.has(registeredName)) {
|
|
2239
|
+
if (this.registrationMap.has(registeredName) && !SINGLE_INSTANCE_CAPABILITIES.includes(capability)) {
|
|
1836
2240
|
const current = this.registrationMap.get(registeredName);
|
|
1837
2241
|
if (Array.isArray(current)) {
|
|
1838
2242
|
current.push(registeredName);
|
|
@@ -2090,8 +2494,8 @@ var PlayerLanguageService = class {
|
|
|
2090
2494
|
}
|
|
2091
2495
|
return (0, import_jsonc_parser4.format)(document.getText(), formatRange, formattingOptions).map(
|
|
2092
2496
|
(edit) => {
|
|
2093
|
-
return
|
|
2094
|
-
|
|
2497
|
+
return import_vscode_languageserver_types12.TextEdit.replace(
|
|
2498
|
+
import_vscode_languageserver_types12.Range.create(
|
|
2095
2499
|
document.positionAt(edit.offset),
|
|
2096
2500
|
document.positionAt(edit.offset + edit.length)
|
|
2097
2501
|
),
|
|
@@ -2160,7 +2564,7 @@ var PlayerLanguageService = class {
|
|
|
2160
2564
|
async getCompletionsAtPosition(document, position) {
|
|
2161
2565
|
const ctxWithPos = await this.updateSourceWithPosition(document, position);
|
|
2162
2566
|
if (!ctxWithPos) {
|
|
2163
|
-
return
|
|
2567
|
+
return import_vscode_languageserver_types12.CompletionList.create();
|
|
2164
2568
|
}
|
|
2165
2569
|
const completionItems = [];
|
|
2166
2570
|
const completionContext = {
|
|
@@ -2169,7 +2573,7 @@ var PlayerLanguageService = class {
|
|
|
2169
2573
|
}
|
|
2170
2574
|
};
|
|
2171
2575
|
await this.hooks.complete.call(ctxWithPos, completionContext);
|
|
2172
|
-
return
|
|
2576
|
+
return import_vscode_languageserver_types12.CompletionList.create(completionItems);
|
|
2173
2577
|
}
|
|
2174
2578
|
async resolveCompletionItem(completionItem) {
|
|
2175
2579
|
return completionItem;
|
|
@@ -2199,7 +2603,7 @@ var PlayerLanguageService = class {
|
|
|
2199
2603
|
}
|
|
2200
2604
|
actions.push({
|
|
2201
2605
|
title: fixedAction.name,
|
|
2202
|
-
kind:
|
|
2606
|
+
kind: import_vscode_languageserver_types12.CodeActionKind.QuickFix,
|
|
2203
2607
|
edit: {
|
|
2204
2608
|
changes: {
|
|
2205
2609
|
[document.uri]: [toTextEdit(document, fixedAction.edit)]
|
|
@@ -2283,6 +2687,7 @@ var PlayerLanguageService = class {
|
|
|
2283
2687
|
applyTemplateProperty,
|
|
2284
2688
|
applyValueRefs,
|
|
2285
2689
|
containsRange,
|
|
2690
|
+
findErrorNode,
|
|
2286
2691
|
formatLikeNode,
|
|
2287
2692
|
getContentNode,
|
|
2288
2693
|
getLSLocationOfNode,
|