@zenstackhq/language 3.0.0-beta.1 → 3.0.0-beta.11
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/index.cjs +442 -271
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -20
- package/dist/index.d.ts +19 -20
- package/dist/index.js +394 -225
- package/dist/index.js.map +1 -1
- package/dist/utils.cjs +106 -28
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +5 -5
- package/dist/utils.d.ts +5 -5
- package/dist/utils.js +100 -23
- package/dist/utils.js.map +1 -1
- package/package.json +8 -6
- package/res/stdlib.zmodel +39 -69
package/dist/index.js
CHANGED
|
@@ -7,12 +7,11 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
-
// src/
|
|
11
|
-
import { isAstNode, URI as
|
|
12
|
-
import { NodeFileSystem } from "langium/node";
|
|
10
|
+
// src/document.ts
|
|
11
|
+
import { isAstNode, URI as URI4 } from "langium";
|
|
13
12
|
import fs3 from "fs";
|
|
14
|
-
import
|
|
15
|
-
import { fileURLToPath as
|
|
13
|
+
import path4 from "path";
|
|
14
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
16
15
|
|
|
17
16
|
// src/generated/ast.ts
|
|
18
17
|
import * as langium from "langium";
|
|
@@ -1042,8 +1041,11 @@ var ExpressionContext = /* @__PURE__ */ function(ExpressionContext2) {
|
|
|
1042
1041
|
}({});
|
|
1043
1042
|
|
|
1044
1043
|
// src/module.ts
|
|
1045
|
-
import { inject } from "langium";
|
|
1044
|
+
import { DocumentState as DocumentState2, inject, URI as URI3 } from "langium";
|
|
1046
1045
|
import { createDefaultModule, createDefaultSharedModule } from "langium/lsp";
|
|
1046
|
+
import { NodeFileSystem } from "langium/node";
|
|
1047
|
+
import path3 from "path";
|
|
1048
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1047
1049
|
|
|
1048
1050
|
// src/generated/grammar.ts
|
|
1049
1051
|
import { loadGrammarFromJson } from "langium";
|
|
@@ -5104,15 +5106,12 @@ var ZModelGeneratedModule = {
|
|
|
5104
5106
|
parser: {}
|
|
5105
5107
|
};
|
|
5106
5108
|
|
|
5107
|
-
// src/validators/attribute-application-validator.ts
|
|
5108
|
-
import { AstUtils as AstUtils2 } from "langium";
|
|
5109
|
-
import pluralize from "pluralize";
|
|
5110
|
-
|
|
5111
5109
|
// src/utils.ts
|
|
5112
|
-
import { invariant } from "@zenstackhq/common-helpers";
|
|
5113
5110
|
import { AstUtils, URI } from "langium";
|
|
5114
5111
|
import fs from "fs";
|
|
5112
|
+
import { createRequire } from "module";
|
|
5115
5113
|
import path from "path";
|
|
5114
|
+
import { fileURLToPath, pathToFileURL } from "url";
|
|
5116
5115
|
function hasAttribute(decl, name) {
|
|
5117
5116
|
return !!getAttribute(decl, name);
|
|
5118
5117
|
}
|
|
@@ -5192,10 +5191,6 @@ function isRelationshipField(field) {
|
|
|
5192
5191
|
return isDataModel(field.type.reference?.ref);
|
|
5193
5192
|
}
|
|
5194
5193
|
__name(isRelationshipField, "isRelationshipField");
|
|
5195
|
-
function isFutureExpr(node) {
|
|
5196
|
-
return isInvocationExpr(node) && node.function.ref?.name === "future" && isFromStdlib(node.function.ref);
|
|
5197
|
-
}
|
|
5198
|
-
__name(isFutureExpr, "isFutureExpr");
|
|
5199
5194
|
function isDelegateModel(node) {
|
|
5200
5195
|
return isDataModel(node) && hasAttribute(node, "@@delegate");
|
|
5201
5196
|
}
|
|
@@ -5213,8 +5208,14 @@ function getRecursiveBases(decl, includeDelegate = true, seen = /* @__PURE__ */
|
|
|
5213
5208
|
return result;
|
|
5214
5209
|
}
|
|
5215
5210
|
seen.add(decl);
|
|
5216
|
-
|
|
5217
|
-
|
|
5211
|
+
const bases = [
|
|
5212
|
+
...decl.mixins,
|
|
5213
|
+
...isDataModel(decl) && decl.baseModel ? [
|
|
5214
|
+
decl.baseModel
|
|
5215
|
+
] : []
|
|
5216
|
+
];
|
|
5217
|
+
bases.forEach((base) => {
|
|
5218
|
+
const baseDecl = decl.$container.declarations.find((d) => isTypeDef(d) || isDataModel(d) && d.name === base.$refText);
|
|
5218
5219
|
if (baseDecl) {
|
|
5219
5220
|
if (!includeDelegate && isDelegateModel(baseDecl)) {
|
|
5220
5221
|
return;
|
|
@@ -5354,7 +5355,7 @@ function getFunctionExpressionContext(funcDecl) {
|
|
|
5354
5355
|
}
|
|
5355
5356
|
__name(getFunctionExpressionContext, "getFunctionExpressionContext");
|
|
5356
5357
|
function isCheckInvocation(node) {
|
|
5357
|
-
return isInvocationExpr(node) && node.function.ref?.name === "check"
|
|
5358
|
+
return isInvocationExpr(node) && node.function.ref?.name === "check";
|
|
5358
5359
|
}
|
|
5359
5360
|
__name(isCheckInvocation, "isCheckInvocation");
|
|
5360
5361
|
function resolveTransitiveImports(documents, model) {
|
|
@@ -5424,17 +5425,17 @@ function getAllDeclarationsIncludingImports(documents, model) {
|
|
|
5424
5425
|
}
|
|
5425
5426
|
__name(getAllDeclarationsIncludingImports, "getAllDeclarationsIncludingImports");
|
|
5426
5427
|
function getAuthDecl(decls) {
|
|
5427
|
-
let authModel = decls.find((
|
|
5428
|
+
let authModel = decls.find((d) => hasAttribute(d, "@@auth"));
|
|
5428
5429
|
if (!authModel) {
|
|
5429
|
-
authModel = decls.find((
|
|
5430
|
+
authModel = decls.find((d) => d.name === "User");
|
|
5430
5431
|
}
|
|
5431
5432
|
return authModel;
|
|
5432
5433
|
}
|
|
5433
5434
|
__name(getAuthDecl, "getAuthDecl");
|
|
5434
|
-
function
|
|
5435
|
-
return isInvocationExpr(node) && node.function.ref?.name === "
|
|
5435
|
+
function isBeforeInvocation(node) {
|
|
5436
|
+
return isInvocationExpr(node) && node.function.ref?.name === "before";
|
|
5436
5437
|
}
|
|
5437
|
-
__name(
|
|
5438
|
+
__name(isBeforeInvocation, "isBeforeInvocation");
|
|
5438
5439
|
function isCollectionPredicate(node) {
|
|
5439
5440
|
return isBinaryExpr(node) && [
|
|
5440
5441
|
"?",
|
|
@@ -5489,12 +5490,14 @@ function getAllFields(decl, includeIgnored = false, seen = /* @__PURE__ */ new S
|
|
|
5489
5490
|
seen.add(decl);
|
|
5490
5491
|
const fields = [];
|
|
5491
5492
|
for (const mixin of decl.mixins) {
|
|
5492
|
-
|
|
5493
|
-
|
|
5493
|
+
if (mixin.ref) {
|
|
5494
|
+
fields.push(...getAllFields(mixin.ref, includeIgnored, seen));
|
|
5495
|
+
}
|
|
5494
5496
|
}
|
|
5495
5497
|
if (isDataModel(decl) && decl.baseModel) {
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
+
if (decl.baseModel.ref) {
|
|
5499
|
+
fields.push(...getAllFields(decl.baseModel.ref, includeIgnored, seen));
|
|
5500
|
+
}
|
|
5498
5501
|
}
|
|
5499
5502
|
fields.push(...decl.fields.filter((f) => includeIgnored || !hasAttribute(f, "@ignore")));
|
|
5500
5503
|
return fields;
|
|
@@ -5507,12 +5510,14 @@ function getAllAttributes(decl, seen = /* @__PURE__ */ new Set()) {
|
|
|
5507
5510
|
seen.add(decl);
|
|
5508
5511
|
const attributes = [];
|
|
5509
5512
|
for (const mixin of decl.mixins) {
|
|
5510
|
-
|
|
5511
|
-
|
|
5513
|
+
if (mixin.ref) {
|
|
5514
|
+
attributes.push(...getAllAttributes(mixin.ref, seen));
|
|
5515
|
+
}
|
|
5512
5516
|
}
|
|
5513
5517
|
if (isDataModel(decl) && decl.baseModel) {
|
|
5514
|
-
|
|
5515
|
-
|
|
5518
|
+
if (decl.baseModel.ref) {
|
|
5519
|
+
attributes.push(...getAllAttributes(decl.baseModel.ref, seen));
|
|
5520
|
+
}
|
|
5516
5521
|
}
|
|
5517
5522
|
attributes.push(...decl.attributes);
|
|
5518
5523
|
return attributes;
|
|
@@ -5527,6 +5532,71 @@ function getDocument(node) {
|
|
|
5527
5532
|
return result;
|
|
5528
5533
|
}
|
|
5529
5534
|
__name(getDocument, "getDocument");
|
|
5535
|
+
function getPluginDocuments(model, schemaPath) {
|
|
5536
|
+
const result = [];
|
|
5537
|
+
for (const decl of model.declarations.filter(isPlugin)) {
|
|
5538
|
+
const providerField = decl.fields.find((f) => f.name === "provider");
|
|
5539
|
+
if (!providerField) {
|
|
5540
|
+
continue;
|
|
5541
|
+
}
|
|
5542
|
+
const provider = getLiteral(providerField.value);
|
|
5543
|
+
if (!provider) {
|
|
5544
|
+
continue;
|
|
5545
|
+
}
|
|
5546
|
+
let pluginModelFile;
|
|
5547
|
+
let providerPath = path.resolve(path.dirname(schemaPath), provider);
|
|
5548
|
+
if (fs.existsSync(providerPath)) {
|
|
5549
|
+
if (fs.statSync(providerPath).isDirectory()) {
|
|
5550
|
+
providerPath = path.join(providerPath, "index.js");
|
|
5551
|
+
}
|
|
5552
|
+
pluginModelFile = path.resolve(path.dirname(providerPath), PLUGIN_MODULE_NAME);
|
|
5553
|
+
if (!fs.existsSync(pluginModelFile)) {
|
|
5554
|
+
pluginModelFile = findUp([
|
|
5555
|
+
PLUGIN_MODULE_NAME
|
|
5556
|
+
], path.dirname(providerPath));
|
|
5557
|
+
}
|
|
5558
|
+
}
|
|
5559
|
+
if (!pluginModelFile) {
|
|
5560
|
+
if (typeof import.meta.resolve === "function") {
|
|
5561
|
+
try {
|
|
5562
|
+
const resolvedUrl = import.meta.resolve(`${provider}/${PLUGIN_MODULE_NAME}`);
|
|
5563
|
+
pluginModelFile = fileURLToPath(resolvedUrl);
|
|
5564
|
+
} catch {
|
|
5565
|
+
}
|
|
5566
|
+
}
|
|
5567
|
+
}
|
|
5568
|
+
if (!pluginModelFile) {
|
|
5569
|
+
try {
|
|
5570
|
+
const require2 = createRequire(pathToFileURL(schemaPath));
|
|
5571
|
+
pluginModelFile = require2.resolve(`${provider}/${PLUGIN_MODULE_NAME}`);
|
|
5572
|
+
} catch {
|
|
5573
|
+
}
|
|
5574
|
+
}
|
|
5575
|
+
if (pluginModelFile && fs.existsSync(pluginModelFile)) {
|
|
5576
|
+
result.push(pluginModelFile);
|
|
5577
|
+
}
|
|
5578
|
+
}
|
|
5579
|
+
return result;
|
|
5580
|
+
}
|
|
5581
|
+
__name(getPluginDocuments, "getPluginDocuments");
|
|
5582
|
+
function findUp(names, cwd = process.cwd(), multiple = false, result = []) {
|
|
5583
|
+
if (!names.some((name) => !!name)) {
|
|
5584
|
+
return void 0;
|
|
5585
|
+
}
|
|
5586
|
+
const target = names.find((name) => fs.existsSync(path.join(cwd, name)));
|
|
5587
|
+
if (multiple === false && target) {
|
|
5588
|
+
return path.join(cwd, target);
|
|
5589
|
+
}
|
|
5590
|
+
if (target) {
|
|
5591
|
+
result.push(path.join(cwd, target));
|
|
5592
|
+
}
|
|
5593
|
+
const up = path.resolve(cwd, "..");
|
|
5594
|
+
if (up === cwd) {
|
|
5595
|
+
return multiple && result.length > 0 ? result : void 0;
|
|
5596
|
+
}
|
|
5597
|
+
return findUp(names, up, multiple, result);
|
|
5598
|
+
}
|
|
5599
|
+
__name(findUp, "findUp");
|
|
5530
5600
|
function findRootNode(node) {
|
|
5531
5601
|
while (node.$container) {
|
|
5532
5602
|
node = node.$container;
|
|
@@ -5536,6 +5606,8 @@ function findRootNode(node) {
|
|
|
5536
5606
|
__name(findRootNode, "findRootNode");
|
|
5537
5607
|
|
|
5538
5608
|
// src/validators/attribute-application-validator.ts
|
|
5609
|
+
import { AstUtils as AstUtils2 } from "langium";
|
|
5610
|
+
import pluralize from "pluralize";
|
|
5539
5611
|
function _ts_decorate(decorators, target, key, desc) {
|
|
5540
5612
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
5541
5613
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -5649,6 +5721,7 @@ var AttributeApplicationValidator = class {
|
|
|
5649
5721
|
});
|
|
5650
5722
|
}
|
|
5651
5723
|
}
|
|
5724
|
+
// TODO: design a way to let plugin register validation
|
|
5652
5725
|
_checkModelLevelPolicy(attr, accept) {
|
|
5653
5726
|
const kind = getStringLiteral(attr.args[0]?.value);
|
|
5654
5727
|
if (!kind) {
|
|
@@ -5661,11 +5734,61 @@ var AttributeApplicationValidator = class {
|
|
|
5661
5734
|
"create",
|
|
5662
5735
|
"read",
|
|
5663
5736
|
"update",
|
|
5737
|
+
"post-update",
|
|
5664
5738
|
"delete",
|
|
5665
5739
|
"all"
|
|
5666
5740
|
], attr, accept);
|
|
5667
|
-
|
|
5741
|
+
if ((kind === "create" || kind === "all") && attr.args[1]?.value) {
|
|
5742
|
+
this.rejectNonOwnedRelationInExpression(attr.args[1].value, accept);
|
|
5743
|
+
}
|
|
5744
|
+
if (kind !== "post-update" && attr.args[1]?.value) {
|
|
5745
|
+
const beforeCall = AstUtils2.streamAst(attr.args[1]?.value).find(isBeforeInvocation);
|
|
5746
|
+
if (beforeCall) {
|
|
5747
|
+
accept("error", `"before()" is only allowed in "post-update" policy rules`, {
|
|
5748
|
+
node: beforeCall
|
|
5749
|
+
});
|
|
5750
|
+
}
|
|
5751
|
+
}
|
|
5668
5752
|
}
|
|
5753
|
+
rejectNonOwnedRelationInExpression(expr, accept) {
|
|
5754
|
+
const contextModel = AstUtils2.getContainerOfType(expr, isDataModel);
|
|
5755
|
+
if (!contextModel) {
|
|
5756
|
+
return;
|
|
5757
|
+
}
|
|
5758
|
+
if (AstUtils2.streamAst(expr).some((node) => {
|
|
5759
|
+
if (!isDataFieldReference(node)) {
|
|
5760
|
+
return false;
|
|
5761
|
+
}
|
|
5762
|
+
if (node.target.ref?.$container !== contextModel) {
|
|
5763
|
+
return false;
|
|
5764
|
+
}
|
|
5765
|
+
const field = node.target.ref;
|
|
5766
|
+
if (!isRelationshipField(field)) {
|
|
5767
|
+
return false;
|
|
5768
|
+
}
|
|
5769
|
+
if (isAuthOrAuthMemberAccess(node)) {
|
|
5770
|
+
return false;
|
|
5771
|
+
}
|
|
5772
|
+
const startNode = isCollectionPredicate(node.$container) && node.$container.left === node ? node.$container : node;
|
|
5773
|
+
const collectionPredicate = AstUtils2.getContainerOfType(startNode.$container, isCollectionPredicate);
|
|
5774
|
+
if (collectionPredicate && isAuthOrAuthMemberAccess(collectionPredicate.left)) {
|
|
5775
|
+
return false;
|
|
5776
|
+
}
|
|
5777
|
+
const relationAttr = field.attributes.find((attr) => attr.decl.ref?.name === "@relation");
|
|
5778
|
+
if (!relationAttr) {
|
|
5779
|
+
return true;
|
|
5780
|
+
}
|
|
5781
|
+
if (!relationAttr.args.some((arg) => arg.name === "fields")) {
|
|
5782
|
+
return true;
|
|
5783
|
+
}
|
|
5784
|
+
return false;
|
|
5785
|
+
})) {
|
|
5786
|
+
accept("error", `non-owned relation fields are not allowed in "create" rules`, {
|
|
5787
|
+
node: expr
|
|
5788
|
+
});
|
|
5789
|
+
}
|
|
5790
|
+
}
|
|
5791
|
+
// TODO: design a way to let plugin register validation
|
|
5669
5792
|
_checkFieldLevelPolicy(attr, accept) {
|
|
5670
5793
|
const kind = getStringLiteral(attr.args[0]?.value);
|
|
5671
5794
|
if (!kind) {
|
|
@@ -5680,8 +5803,8 @@ var AttributeApplicationValidator = class {
|
|
|
5680
5803
|
"all"
|
|
5681
5804
|
], attr, accept);
|
|
5682
5805
|
const expr = attr.args[1]?.value;
|
|
5683
|
-
if (expr && AstUtils2.streamAst(expr).some((node) =>
|
|
5684
|
-
accept("error", `"
|
|
5806
|
+
if (expr && AstUtils2.streamAst(expr).some((node) => isBeforeInvocation(node))) {
|
|
5807
|
+
accept("error", `"before()" is not allowed in field-level policy rules`, {
|
|
5685
5808
|
node: expr
|
|
5686
5809
|
});
|
|
5687
5810
|
}
|
|
@@ -5693,7 +5816,6 @@ var AttributeApplicationValidator = class {
|
|
|
5693
5816
|
});
|
|
5694
5817
|
}
|
|
5695
5818
|
}
|
|
5696
|
-
this.rejectEncryptedFields(attr, accept);
|
|
5697
5819
|
}
|
|
5698
5820
|
_checkValidate(attr, accept) {
|
|
5699
5821
|
const condition = attr.args[0]?.value;
|
|
@@ -5703,8 +5825,9 @@ var AttributeApplicationValidator = class {
|
|
|
5703
5825
|
});
|
|
5704
5826
|
}
|
|
5705
5827
|
}
|
|
5706
|
-
|
|
5828
|
+
_checkConstraint(attr, accept) {
|
|
5707
5829
|
const fields = attr.args[0]?.value;
|
|
5830
|
+
const attrName = attr.decl.ref?.name;
|
|
5708
5831
|
if (!fields) {
|
|
5709
5832
|
accept("error", `expects an array of field references`, {
|
|
5710
5833
|
node: attr.args[0]
|
|
@@ -5713,7 +5836,7 @@ var AttributeApplicationValidator = class {
|
|
|
5713
5836
|
}
|
|
5714
5837
|
if (isArrayExpr(fields)) {
|
|
5715
5838
|
if (fields.items.length === 0) {
|
|
5716
|
-
accept("error",
|
|
5839
|
+
accept("error", `\`${attrName}\` expects at least one field reference`, {
|
|
5717
5840
|
node: fields
|
|
5718
5841
|
});
|
|
5719
5842
|
return;
|
|
@@ -5732,7 +5855,7 @@ var AttributeApplicationValidator = class {
|
|
|
5732
5855
|
return;
|
|
5733
5856
|
}
|
|
5734
5857
|
if (item.target.ref.$container !== attr.$container && isDelegateModel(item.target.ref.$container)) {
|
|
5735
|
-
accept("error", `Cannot use fields inherited from a polymorphic base model in
|
|
5858
|
+
accept("error", `Cannot use fields inherited from a polymorphic base model in \`${attrName}\``, {
|
|
5736
5859
|
node: item
|
|
5737
5860
|
});
|
|
5738
5861
|
}
|
|
@@ -5743,15 +5866,6 @@ var AttributeApplicationValidator = class {
|
|
|
5743
5866
|
});
|
|
5744
5867
|
}
|
|
5745
5868
|
}
|
|
5746
|
-
rejectEncryptedFields(attr, accept) {
|
|
5747
|
-
AstUtils2.streamAllContents(attr).forEach((node) => {
|
|
5748
|
-
if (isDataFieldReference(node) && hasAttribute(node.target.ref, "@encrypted")) {
|
|
5749
|
-
accept("error", `Encrypted fields cannot be used in policy rules`, {
|
|
5750
|
-
node
|
|
5751
|
-
});
|
|
5752
|
-
}
|
|
5753
|
-
});
|
|
5754
|
-
}
|
|
5755
5869
|
validatePolicyKinds(kind, candidates, attr, accept) {
|
|
5756
5870
|
const items = kind.split(",").map((x) => x.trim());
|
|
5757
5871
|
items.forEach((item) => {
|
|
@@ -5794,15 +5908,16 @@ _ts_decorate([
|
|
|
5794
5908
|
_ts_metadata("design:returntype", void 0)
|
|
5795
5909
|
], AttributeApplicationValidator.prototype, "_checkValidate", null);
|
|
5796
5910
|
_ts_decorate([
|
|
5797
|
-
check("@@unique"),
|
|
5798
5911
|
check("@@id"),
|
|
5912
|
+
check("@@index"),
|
|
5913
|
+
check("@@unique"),
|
|
5799
5914
|
_ts_metadata("design:type", Function),
|
|
5800
5915
|
_ts_metadata("design:paramtypes", [
|
|
5801
5916
|
typeof AttributeApplication === "undefined" ? Object : AttributeApplication,
|
|
5802
5917
|
typeof ValidationAcceptor === "undefined" ? Object : ValidationAcceptor
|
|
5803
5918
|
]),
|
|
5804
5919
|
_ts_metadata("design:returntype", void 0)
|
|
5805
|
-
], AttributeApplicationValidator.prototype, "
|
|
5920
|
+
], AttributeApplicationValidator.prototype, "_checkConstraint", null);
|
|
5806
5921
|
function assignableToAttributeParam(arg, param, attr) {
|
|
5807
5922
|
const argResolvedType = arg.$resolvedType;
|
|
5808
5923
|
if (!argResolvedType) {
|
|
@@ -5812,6 +5927,10 @@ function assignableToAttributeParam(arg, param, attr) {
|
|
|
5812
5927
|
let dstIsArray = param.type.array;
|
|
5813
5928
|
if (dstType === "ContextType") {
|
|
5814
5929
|
if (isDataField(attr.$container)) {
|
|
5930
|
+
const dstIsTypedJson = hasAttribute(attr.$container, "@json");
|
|
5931
|
+
if (dstIsTypedJson && attr.decl.ref?.name === "@default") {
|
|
5932
|
+
return argResolvedType.decl === "String";
|
|
5933
|
+
}
|
|
5815
5934
|
dstIsArray = attr.$container.type.array;
|
|
5816
5935
|
}
|
|
5817
5936
|
}
|
|
@@ -5903,6 +6022,9 @@ function isValidAttributeTarget(attrDecl, targetDecl) {
|
|
|
5903
6022
|
case "TypeDefField":
|
|
5904
6023
|
allowed = allowed || isTypeDef(targetDecl.type.reference?.ref);
|
|
5905
6024
|
break;
|
|
6025
|
+
case "ListField":
|
|
6026
|
+
allowed = allowed || !isDataModel(targetDecl.type.reference?.ref) && targetDecl.type.array;
|
|
6027
|
+
break;
|
|
5906
6028
|
default:
|
|
5907
6029
|
break;
|
|
5908
6030
|
}
|
|
@@ -5929,7 +6051,7 @@ var AttributeValidator = class {
|
|
|
5929
6051
|
};
|
|
5930
6052
|
|
|
5931
6053
|
// src/validators/datamodel-validator.ts
|
|
5932
|
-
import { invariant
|
|
6054
|
+
import { invariant } from "@zenstackhq/common-helpers";
|
|
5933
6055
|
import { AstUtils as AstUtils3 } from "langium";
|
|
5934
6056
|
|
|
5935
6057
|
// src/validators/common.ts
|
|
@@ -6300,7 +6422,7 @@ var DataModelValidator = class {
|
|
|
6300
6422
|
if (!model.baseModel) {
|
|
6301
6423
|
return;
|
|
6302
6424
|
}
|
|
6303
|
-
|
|
6425
|
+
invariant(model.baseModel.ref, "baseModel must be resolved");
|
|
6304
6426
|
if (!isDelegateModel(model.baseModel.ref)) {
|
|
6305
6427
|
accept("error", `Model ${model.baseModel.$refText} cannot be extended because it's not a delegate model`, {
|
|
6306
6428
|
node: model,
|
|
@@ -6322,7 +6444,7 @@ var DataModelValidator = class {
|
|
|
6322
6444
|
}
|
|
6323
6445
|
seen.push(current);
|
|
6324
6446
|
if (current.baseModel) {
|
|
6325
|
-
|
|
6447
|
+
invariant(current.baseModel.ref, "baseModel must be resolved");
|
|
6326
6448
|
todo.push(current.baseModel.ref);
|
|
6327
6449
|
}
|
|
6328
6450
|
}
|
|
@@ -6452,11 +6574,21 @@ var ExpressionValidator = class {
|
|
|
6452
6574
|
}
|
|
6453
6575
|
}
|
|
6454
6576
|
switch (expr.$type) {
|
|
6577
|
+
case "MemberAccessExpr":
|
|
6578
|
+
this.validateMemberAccessExpr(expr, accept);
|
|
6579
|
+
break;
|
|
6455
6580
|
case "BinaryExpr":
|
|
6456
6581
|
this.validateBinaryExpr(expr, accept);
|
|
6457
6582
|
break;
|
|
6458
6583
|
}
|
|
6459
6584
|
}
|
|
6585
|
+
validateMemberAccessExpr(expr, accept) {
|
|
6586
|
+
if (isBeforeInvocation(expr.operand) && isDataModel(expr.$resolvedType?.decl)) {
|
|
6587
|
+
accept("error", "relation fields cannot be accessed from `before()`", {
|
|
6588
|
+
node: expr
|
|
6589
|
+
});
|
|
6590
|
+
}
|
|
6591
|
+
}
|
|
6460
6592
|
validateBinaryExpr(expr, accept) {
|
|
6461
6593
|
switch (expr.operator) {
|
|
6462
6594
|
case "in": {
|
|
@@ -6509,23 +6641,25 @@ var ExpressionValidator = class {
|
|
|
6509
6641
|
"Any"
|
|
6510
6642
|
];
|
|
6511
6643
|
}
|
|
6512
|
-
|
|
6644
|
+
const leftResolvedDecl = expr.left.$resolvedType?.decl;
|
|
6645
|
+
const rightResolvedDecl = expr.right.$resolvedType?.decl;
|
|
6646
|
+
if (leftResolvedDecl && (typeof leftResolvedDecl !== "string" || !supportedShapes.includes(leftResolvedDecl))) {
|
|
6513
6647
|
accept("error", `invalid operand type for "${expr.operator}" operator`, {
|
|
6514
6648
|
node: expr.left
|
|
6515
6649
|
});
|
|
6516
6650
|
return;
|
|
6517
6651
|
}
|
|
6518
|
-
if (typeof
|
|
6652
|
+
if (rightResolvedDecl && (typeof rightResolvedDecl !== "string" || !supportedShapes.includes(rightResolvedDecl))) {
|
|
6519
6653
|
accept("error", `invalid operand type for "${expr.operator}" operator`, {
|
|
6520
6654
|
node: expr.right
|
|
6521
6655
|
});
|
|
6522
6656
|
return;
|
|
6523
6657
|
}
|
|
6524
|
-
if (
|
|
6658
|
+
if (leftResolvedDecl === "DateTime" && rightResolvedDecl && rightResolvedDecl !== "DateTime") {
|
|
6525
6659
|
accept("error", "incompatible operand types", {
|
|
6526
6660
|
node: expr
|
|
6527
6661
|
});
|
|
6528
|
-
} else if (
|
|
6662
|
+
} else if (rightResolvedDecl === "DateTime" && leftResolvedDecl && leftResolvedDecl !== "DateTime") {
|
|
6529
6663
|
accept("error", "incompatible operand types", {
|
|
6530
6664
|
node: expr
|
|
6531
6665
|
});
|
|
@@ -6565,11 +6699,11 @@ var ExpressionValidator = class {
|
|
|
6565
6699
|
});
|
|
6566
6700
|
}
|
|
6567
6701
|
if (isDataFieldReference(expr.left) && (isThisExpr(expr.right) || isDataFieldReference(expr.right))) {
|
|
6568
|
-
accept("error", "comparison between
|
|
6702
|
+
accept("error", "comparison between models is not supported", {
|
|
6569
6703
|
node: expr
|
|
6570
6704
|
});
|
|
6571
6705
|
} else if (isDataFieldReference(expr.right) && (isThisExpr(expr.left) || isDataFieldReference(expr.left))) {
|
|
6572
|
-
accept("error", "comparison between
|
|
6706
|
+
accept("error", "comparison between models is not supported", {
|
|
6573
6707
|
node: expr
|
|
6574
6708
|
});
|
|
6575
6709
|
}
|
|
@@ -6659,41 +6793,39 @@ var FunctionInvocationValidator = class {
|
|
|
6659
6793
|
if (!this.validateArgs(funcDecl, expr.args, accept)) {
|
|
6660
6794
|
return;
|
|
6661
6795
|
}
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
break;
|
|
6669
|
-
}
|
|
6670
|
-
curr = curr.$container;
|
|
6796
|
+
let curr = expr.$container;
|
|
6797
|
+
let containerAttribute;
|
|
6798
|
+
while (curr) {
|
|
6799
|
+
if (isDataModelAttribute(curr) || isDataFieldAttribute(curr)) {
|
|
6800
|
+
containerAttribute = curr;
|
|
6801
|
+
break;
|
|
6671
6802
|
}
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6803
|
+
curr = curr.$container;
|
|
6804
|
+
}
|
|
6805
|
+
const exprContext = this.getExpressionContext(containerAttribute);
|
|
6806
|
+
const funcAllowedContext = getFunctionExpressionContext(funcDecl);
|
|
6807
|
+
if (exprContext && !funcAllowedContext.includes(exprContext)) {
|
|
6808
|
+
accept("error", `function "${funcDecl.name}" is not allowed in the current context: ${exprContext}`, {
|
|
6809
|
+
node: expr
|
|
6810
|
+
});
|
|
6811
|
+
return;
|
|
6812
|
+
}
|
|
6813
|
+
const allCasing = [
|
|
6814
|
+
"original",
|
|
6815
|
+
"upper",
|
|
6816
|
+
"lower",
|
|
6817
|
+
"capitalize",
|
|
6818
|
+
"uncapitalize"
|
|
6819
|
+
];
|
|
6820
|
+
if ([
|
|
6821
|
+
"currentModel",
|
|
6822
|
+
"currentOperation"
|
|
6823
|
+
].includes(funcDecl.name)) {
|
|
6824
|
+
const arg = getLiteral(expr.args[0]?.value);
|
|
6825
|
+
if (arg && !allCasing.includes(arg)) {
|
|
6826
|
+
accept("error", `argument must be one of: ${allCasing.map((c) => '"' + c + '"').join(", ")}`, {
|
|
6827
|
+
node: expr.args[0]
|
|
6677
6828
|
});
|
|
6678
|
-
return;
|
|
6679
|
-
}
|
|
6680
|
-
const allCasing = [
|
|
6681
|
-
"original",
|
|
6682
|
-
"upper",
|
|
6683
|
-
"lower",
|
|
6684
|
-
"capitalize",
|
|
6685
|
-
"uncapitalize"
|
|
6686
|
-
];
|
|
6687
|
-
if ([
|
|
6688
|
-
"currentModel",
|
|
6689
|
-
"currentOperation"
|
|
6690
|
-
].includes(funcDecl.name)) {
|
|
6691
|
-
const arg = getLiteral(expr.args[0]?.value);
|
|
6692
|
-
if (arg && !allCasing.includes(arg)) {
|
|
6693
|
-
accept("error", `argument must be one of: ${allCasing.map((c) => '"' + c + '"').join(", ")}`, {
|
|
6694
|
-
node: expr.args[0]
|
|
6695
|
-
});
|
|
6696
|
-
}
|
|
6697
6829
|
}
|
|
6698
6830
|
}
|
|
6699
6831
|
const checker = invocationCheckers.get(expr.function.$refText);
|
|
@@ -6701,6 +6833,18 @@ var FunctionInvocationValidator = class {
|
|
|
6701
6833
|
checker.value.call(this, expr, accept);
|
|
6702
6834
|
}
|
|
6703
6835
|
}
|
|
6836
|
+
getExpressionContext(containerAttribute) {
|
|
6837
|
+
if (!containerAttribute) {
|
|
6838
|
+
return void 0;
|
|
6839
|
+
}
|
|
6840
|
+
if (this.isValidationAttribute(containerAttribute)) {
|
|
6841
|
+
return ExpressionContext.ValidationRule;
|
|
6842
|
+
}
|
|
6843
|
+
return match(containerAttribute?.decl.$refText).with("@default", () => ExpressionContext.DefaultValue).with(P.union("@@allow", "@@deny", "@allow", "@deny"), () => ExpressionContext.AccessPolicy).with("@@index", () => ExpressionContext.Index).otherwise(() => void 0);
|
|
6844
|
+
}
|
|
6845
|
+
isValidationAttribute(attr) {
|
|
6846
|
+
return !!attr.decl.ref?.attributes.some((attr2) => attr2.decl.$refText === "@@@validation");
|
|
6847
|
+
}
|
|
6704
6848
|
validateArgs(funcDecl, args, accept) {
|
|
6705
6849
|
let success = true;
|
|
6706
6850
|
for (let i = 0; i < funcDecl.params.length; i++) {
|
|
@@ -6761,6 +6905,44 @@ var FunctionInvocationValidator = class {
|
|
|
6761
6905
|
}
|
|
6762
6906
|
return true;
|
|
6763
6907
|
}
|
|
6908
|
+
_checkLength(expr, accept) {
|
|
6909
|
+
const msg = "argument must be a string or list field";
|
|
6910
|
+
const fieldArg = expr.args[0].value;
|
|
6911
|
+
if (!isDataFieldReference(fieldArg)) {
|
|
6912
|
+
accept("error", msg, {
|
|
6913
|
+
node: expr.args[0]
|
|
6914
|
+
});
|
|
6915
|
+
return;
|
|
6916
|
+
}
|
|
6917
|
+
if (isDataModel(fieldArg.$resolvedType?.decl)) {
|
|
6918
|
+
accept("error", msg, {
|
|
6919
|
+
node: expr.args[0]
|
|
6920
|
+
});
|
|
6921
|
+
return;
|
|
6922
|
+
}
|
|
6923
|
+
if (!fieldArg.$resolvedType?.array && fieldArg.$resolvedType?.decl !== "String") {
|
|
6924
|
+
accept("error", msg, {
|
|
6925
|
+
node: expr.args[0]
|
|
6926
|
+
});
|
|
6927
|
+
}
|
|
6928
|
+
}
|
|
6929
|
+
_checkRegex(expr, accept) {
|
|
6930
|
+
const regex = expr.args[1]?.value;
|
|
6931
|
+
if (!isStringLiteral(regex)) {
|
|
6932
|
+
accept("error", "second argument must be a string literal", {
|
|
6933
|
+
node: expr.args[1]
|
|
6934
|
+
});
|
|
6935
|
+
return;
|
|
6936
|
+
}
|
|
6937
|
+
try {
|
|
6938
|
+
new RegExp(regex.value);
|
|
6939
|
+
} catch (e) {
|
|
6940
|
+
accept("error", "invalid regular expression: " + e.message, {
|
|
6941
|
+
node: expr.args[1]
|
|
6942
|
+
});
|
|
6943
|
+
}
|
|
6944
|
+
}
|
|
6945
|
+
// TODO: move this to policy plugin
|
|
6764
6946
|
_checkCheck(expr, accept) {
|
|
6765
6947
|
let valid = true;
|
|
6766
6948
|
const fieldArg = expr.args[0].value;
|
|
@@ -6832,6 +7014,24 @@ var FunctionInvocationValidator = class {
|
|
|
6832
7014
|
}
|
|
6833
7015
|
}
|
|
6834
7016
|
};
|
|
7017
|
+
_ts_decorate2([
|
|
7018
|
+
func("length"),
|
|
7019
|
+
_ts_metadata2("design:type", Function),
|
|
7020
|
+
_ts_metadata2("design:paramtypes", [
|
|
7021
|
+
typeof InvocationExpr === "undefined" ? Object : InvocationExpr,
|
|
7022
|
+
typeof ValidationAcceptor === "undefined" ? Object : ValidationAcceptor
|
|
7023
|
+
]),
|
|
7024
|
+
_ts_metadata2("design:returntype", void 0)
|
|
7025
|
+
], FunctionInvocationValidator.prototype, "_checkLength", null);
|
|
7026
|
+
_ts_decorate2([
|
|
7027
|
+
func("regex"),
|
|
7028
|
+
_ts_metadata2("design:type", Function),
|
|
7029
|
+
_ts_metadata2("design:paramtypes", [
|
|
7030
|
+
typeof InvocationExpr === "undefined" ? Object : InvocationExpr,
|
|
7031
|
+
typeof ValidationAcceptor === "undefined" ? Object : ValidationAcceptor
|
|
7032
|
+
]),
|
|
7033
|
+
_ts_metadata2("design:returntype", void 0)
|
|
7034
|
+
], FunctionInvocationValidator.prototype, "_checkRegex", null);
|
|
6835
7035
|
_ts_decorate2([
|
|
6836
7036
|
func("check"),
|
|
6837
7037
|
_ts_metadata2("design:type", Function),
|
|
@@ -6941,49 +7141,66 @@ var ZModelValidator = class {
|
|
|
6941
7141
|
constructor(services) {
|
|
6942
7142
|
this.services = services;
|
|
6943
7143
|
}
|
|
6944
|
-
shouldCheck(node) {
|
|
6945
|
-
let doc;
|
|
6946
|
-
let currNode = node;
|
|
6947
|
-
while (currNode) {
|
|
6948
|
-
if (currNode.$document) {
|
|
6949
|
-
doc = currNode.$document;
|
|
6950
|
-
break;
|
|
6951
|
-
}
|
|
6952
|
-
currNode = currNode.$container;
|
|
6953
|
-
}
|
|
6954
|
-
return doc?.parseResult.lexerErrors.length === 0 && doc?.parseResult.parserErrors.length === 0;
|
|
6955
|
-
}
|
|
6956
7144
|
checkModel(node, accept) {
|
|
6957
|
-
|
|
7145
|
+
new SchemaValidator(this.services.shared.workspace.LangiumDocuments).validate(node, accept);
|
|
6958
7146
|
}
|
|
6959
7147
|
checkDataSource(node, accept) {
|
|
6960
|
-
|
|
7148
|
+
new DataSourceValidator().validate(node, accept);
|
|
6961
7149
|
}
|
|
6962
7150
|
checkDataModel(node, accept) {
|
|
6963
|
-
|
|
7151
|
+
new DataModelValidator().validate(node, accept);
|
|
6964
7152
|
}
|
|
6965
7153
|
checkTypeDef(node, accept) {
|
|
6966
|
-
|
|
7154
|
+
new TypeDefValidator().validate(node, accept);
|
|
6967
7155
|
}
|
|
6968
7156
|
checkEnum(node, accept) {
|
|
6969
|
-
|
|
7157
|
+
new EnumValidator().validate(node, accept);
|
|
6970
7158
|
}
|
|
6971
7159
|
checkAttribute(node, accept) {
|
|
6972
|
-
|
|
7160
|
+
new AttributeValidator().validate(node, accept);
|
|
6973
7161
|
}
|
|
6974
7162
|
checkExpression(node, accept) {
|
|
6975
|
-
|
|
7163
|
+
new ExpressionValidator().validate(node, accept);
|
|
6976
7164
|
}
|
|
6977
7165
|
checkFunctionInvocation(node, accept) {
|
|
6978
|
-
|
|
7166
|
+
new FunctionInvocationValidator().validate(node, accept);
|
|
6979
7167
|
}
|
|
6980
7168
|
checkFunctionDecl(node, accept) {
|
|
6981
|
-
|
|
7169
|
+
new FunctionDeclValidator().validate(node, accept);
|
|
7170
|
+
}
|
|
7171
|
+
};
|
|
7172
|
+
|
|
7173
|
+
// src/zmodel-document-builder.ts
|
|
7174
|
+
import { DefaultDocumentBuilder } from "langium";
|
|
7175
|
+
var ZModelDocumentBuilder = class extends DefaultDocumentBuilder {
|
|
7176
|
+
static {
|
|
7177
|
+
__name(this, "ZModelDocumentBuilder");
|
|
7178
|
+
}
|
|
7179
|
+
constructor(services) {
|
|
7180
|
+
super(services);
|
|
7181
|
+
let validationOptions = this.updateBuildOptions.validation;
|
|
7182
|
+
const stopFlags = {
|
|
7183
|
+
stopAfterLinkingErrors: true,
|
|
7184
|
+
stopAfterLexingErrors: true,
|
|
7185
|
+
stopAfterParsingErrors: true
|
|
7186
|
+
};
|
|
7187
|
+
if (validationOptions === true) {
|
|
7188
|
+
validationOptions = stopFlags;
|
|
7189
|
+
} else if (typeof validationOptions === "object") {
|
|
7190
|
+
validationOptions = {
|
|
7191
|
+
...validationOptions,
|
|
7192
|
+
...stopFlags
|
|
7193
|
+
};
|
|
7194
|
+
}
|
|
7195
|
+
this.updateBuildOptions = {
|
|
7196
|
+
...this.updateBuildOptions,
|
|
7197
|
+
validation: validationOptions
|
|
7198
|
+
};
|
|
6982
7199
|
}
|
|
6983
7200
|
};
|
|
6984
7201
|
|
|
6985
7202
|
// src/zmodel-linker.ts
|
|
6986
|
-
import { AstUtils as AstUtils6, Cancellation, DefaultLinker, DocumentState, interruptAndCheck
|
|
7203
|
+
import { AstUtils as AstUtils6, Cancellation, DefaultLinker, DocumentState, interruptAndCheck } from "langium";
|
|
6987
7204
|
import { match as match2 } from "ts-pattern";
|
|
6988
7205
|
var ZModelLinker = class extends DefaultLinker {
|
|
6989
7206
|
static {
|
|
@@ -7005,21 +7222,19 @@ var ZModelLinker = class extends DefaultLinker {
|
|
|
7005
7222
|
}
|
|
7006
7223
|
document.state = DocumentState.Linked;
|
|
7007
7224
|
}
|
|
7008
|
-
linkReference(
|
|
7009
|
-
|
|
7225
|
+
linkReference(refInfo, document, extraScopes) {
|
|
7226
|
+
const defaultRef = refInfo.reference;
|
|
7227
|
+
if (defaultRef._ref) {
|
|
7010
7228
|
return;
|
|
7011
7229
|
}
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
property
|
|
7017
|
-
}, document);
|
|
7230
|
+
if (this.resolveFromScopeProviders(refInfo.reference, document, extraScopes)) {
|
|
7231
|
+
return;
|
|
7232
|
+
}
|
|
7233
|
+
this.doLink(refInfo, document);
|
|
7018
7234
|
}
|
|
7019
7235
|
//#endregion
|
|
7020
7236
|
//#region Expression type resolving
|
|
7021
|
-
resolveFromScopeProviders(
|
|
7022
|
-
const reference = node[property];
|
|
7237
|
+
resolveFromScopeProviders(reference, document, providers) {
|
|
7023
7238
|
for (const provider of providers) {
|
|
7024
7239
|
const target = provider(reference.$refText);
|
|
7025
7240
|
if (target) {
|
|
@@ -7148,7 +7363,11 @@ var ZModelLinker = class extends DefaultLinker {
|
|
|
7148
7363
|
}
|
|
7149
7364
|
}
|
|
7150
7365
|
resolveInvocation(node, document, extraScopes) {
|
|
7151
|
-
this.linkReference(
|
|
7366
|
+
this.linkReference({
|
|
7367
|
+
reference: node.function,
|
|
7368
|
+
container: node,
|
|
7369
|
+
property: "function"
|
|
7370
|
+
}, document, extraScopes);
|
|
7152
7371
|
node.args.forEach((arg) => this.resolve(arg, document, extraScopes));
|
|
7153
7372
|
if (node.function.ref) {
|
|
7154
7373
|
const funcDecl = node.function.ref;
|
|
@@ -7161,7 +7380,7 @@ var ZModelLinker = class extends DefaultLinker {
|
|
|
7161
7380
|
nullable: true
|
|
7162
7381
|
};
|
|
7163
7382
|
}
|
|
7164
|
-
} else if (
|
|
7383
|
+
} else if (isBeforeInvocation(node)) {
|
|
7165
7384
|
node.$resolvedType = {
|
|
7166
7385
|
decl: getContainingDataModel(node)
|
|
7167
7386
|
};
|
|
@@ -7225,7 +7444,7 @@ var ZModelLinker = class extends DefaultLinker {
|
|
|
7225
7444
|
if (isArrayExpr(node.value)) {
|
|
7226
7445
|
node.value.items.forEach((item) => {
|
|
7227
7446
|
if (isReferenceExpr(item)) {
|
|
7228
|
-
const resolved2 = this.resolveFromScopeProviders(item
|
|
7447
|
+
const resolved2 = this.resolveFromScopeProviders(item.target, document, [
|
|
7229
7448
|
scopeProvider
|
|
7230
7449
|
]);
|
|
7231
7450
|
if (resolved2) {
|
|
@@ -7239,7 +7458,7 @@ var ZModelLinker = class extends DefaultLinker {
|
|
|
7239
7458
|
this.resolveToBuiltinTypeOrDecl(node.value, node.value.items[0].$resolvedType.decl, true);
|
|
7240
7459
|
}
|
|
7241
7460
|
} else if (isReferenceExpr(node.value)) {
|
|
7242
|
-
const resolved2 = this.resolveFromScopeProviders(node.value
|
|
7461
|
+
const resolved2 = this.resolveFromScopeProviders(node.value.target, document, [
|
|
7243
7462
|
scopeProvider
|
|
7244
7463
|
]);
|
|
7245
7464
|
if (resolved2) {
|
|
@@ -7291,13 +7510,9 @@ var ZModelLinker = class extends DefaultLinker {
|
|
|
7291
7510
|
this.resolveDefault(node, document, scopes);
|
|
7292
7511
|
}
|
|
7293
7512
|
resolveDefault(node, document, extraScopes) {
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
this.linkReference(node, property, document, extraScopes);
|
|
7298
|
-
}
|
|
7299
|
-
}
|
|
7300
|
-
}
|
|
7513
|
+
AstUtils6.streamReferences(node).forEach((ref) => {
|
|
7514
|
+
this.linkReference(ref, document, extraScopes);
|
|
7515
|
+
});
|
|
7301
7516
|
for (const child of AstUtils6.streamContents(node)) {
|
|
7302
7517
|
this.resolve(child, document, extraScopes);
|
|
7303
7518
|
}
|
|
@@ -7367,7 +7582,7 @@ var ZModelScopeComputation = class extends DefaultScopeComputation {
|
|
|
7367
7582
|
}
|
|
7368
7583
|
processNode(node, document, scopes) {
|
|
7369
7584
|
super.processNode(node, document, scopes);
|
|
7370
|
-
if (isDataModel(node)) {
|
|
7585
|
+
if (isDataModel(node) || isTypeDef(node)) {
|
|
7371
7586
|
const bases = getRecursiveBases(node);
|
|
7372
7587
|
for (const base of bases) {
|
|
7373
7588
|
for (const field of base.fields) {
|
|
@@ -7438,7 +7653,7 @@ var ZModelScopeProvider = class extends DefaultScopeProvider {
|
|
|
7438
7653
|
if (isAuthInvocation(operand)) {
|
|
7439
7654
|
return this.createScopeForAuth(node, globalScope);
|
|
7440
7655
|
}
|
|
7441
|
-
if (
|
|
7656
|
+
if (isBeforeInvocation(operand)) {
|
|
7442
7657
|
return this.createScopeForContainingModel(node, globalScope);
|
|
7443
7658
|
}
|
|
7444
7659
|
return EMPTY_SCOPE;
|
|
@@ -7512,10 +7727,10 @@ function getCollectionPredicateContext(node) {
|
|
|
7512
7727
|
__name(getCollectionPredicateContext, "getCollectionPredicateContext");
|
|
7513
7728
|
|
|
7514
7729
|
// src/zmodel-workspace-manager.ts
|
|
7515
|
-
import { DefaultWorkspaceManager, URI as URI2
|
|
7730
|
+
import { DefaultWorkspaceManager, URI as URI2 } from "langium";
|
|
7516
7731
|
import fs2 from "fs";
|
|
7517
7732
|
import path2 from "path";
|
|
7518
|
-
import { fileURLToPath } from "url";
|
|
7733
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7519
7734
|
var ZModelWorkspaceManager = class extends DefaultWorkspaceManager {
|
|
7520
7735
|
static {
|
|
7521
7736
|
__name(this, "ZModelWorkspaceManager");
|
|
@@ -7551,73 +7766,12 @@ var ZModelWorkspaceManager = class extends DefaultWorkspaceManager {
|
|
|
7551
7766
|
if (installedStdlibPath) {
|
|
7552
7767
|
stdLibPath = installedStdlibPath;
|
|
7553
7768
|
} else {
|
|
7554
|
-
const _dirname = typeof __dirname !== "undefined" ? __dirname : path2.dirname(
|
|
7769
|
+
const _dirname = typeof __dirname !== "undefined" ? __dirname : path2.dirname(fileURLToPath2(import.meta.url));
|
|
7555
7770
|
stdLibPath = path2.join(_dirname, "../res", STD_LIB_MODULE_NAME);
|
|
7556
7771
|
console.log(`Using bundled stdlib in extension:`, stdLibPath);
|
|
7557
7772
|
}
|
|
7558
7773
|
const stdlib = await this.documentFactory.fromUri(URI2.file(stdLibPath));
|
|
7559
7774
|
collector(stdlib);
|
|
7560
|
-
const documents = this.langiumDocuments.all;
|
|
7561
|
-
const pluginModels = /* @__PURE__ */ new Set();
|
|
7562
|
-
documents.forEach((doc) => {
|
|
7563
|
-
const parsed = doc.parseResult.value;
|
|
7564
|
-
parsed.declarations.forEach((decl) => {
|
|
7565
|
-
if (isPlugin(decl)) {
|
|
7566
|
-
const providerField = decl.fields.find((f) => f.name === "provider");
|
|
7567
|
-
if (providerField) {
|
|
7568
|
-
const provider = getLiteral(providerField.value);
|
|
7569
|
-
if (provider) {
|
|
7570
|
-
pluginModels.add(provider);
|
|
7571
|
-
}
|
|
7572
|
-
}
|
|
7573
|
-
}
|
|
7574
|
-
});
|
|
7575
|
-
});
|
|
7576
|
-
if (pluginModels.size > 0) {
|
|
7577
|
-
console.log(`Used plugin modules: ${Array.from(pluginModels)}`);
|
|
7578
|
-
const pendingPluginModules = new Set(pluginModels);
|
|
7579
|
-
await Promise.all(folders.map((wf) => [
|
|
7580
|
-
wf,
|
|
7581
|
-
this.getRootFolder(wf)
|
|
7582
|
-
]).map(async (entry) => this.loadPluginModels(...entry, pendingPluginModules, collector)));
|
|
7583
|
-
}
|
|
7584
|
-
}
|
|
7585
|
-
async loadPluginModels(workspaceFolder, folderPath, pendingPluginModels, collector) {
|
|
7586
|
-
const content = (await this.fileSystemProvider.readDirectory(folderPath)).sort((a, b) => {
|
|
7587
|
-
if (a.isDirectory && b.isDirectory) {
|
|
7588
|
-
const aName = UriUtils2.basename(a.uri);
|
|
7589
|
-
if (aName === "node_modules") {
|
|
7590
|
-
return -1;
|
|
7591
|
-
} else {
|
|
7592
|
-
return 1;
|
|
7593
|
-
}
|
|
7594
|
-
} else {
|
|
7595
|
-
return 0;
|
|
7596
|
-
}
|
|
7597
|
-
});
|
|
7598
|
-
for (const entry of content) {
|
|
7599
|
-
if (entry.isDirectory) {
|
|
7600
|
-
const name = UriUtils2.basename(entry.uri);
|
|
7601
|
-
if (name === "node_modules") {
|
|
7602
|
-
for (const plugin of Array.from(pendingPluginModels)) {
|
|
7603
|
-
const path4 = UriUtils2.joinPath(entry.uri, plugin, PLUGIN_MODULE_NAME);
|
|
7604
|
-
try {
|
|
7605
|
-
await this.fileSystemProvider.readFile(path4);
|
|
7606
|
-
const document = await this.langiumDocuments.getOrCreateDocument(path4);
|
|
7607
|
-
collector(document);
|
|
7608
|
-
console.log(`Adding plugin document from ${path4.path}`);
|
|
7609
|
-
pendingPluginModels.delete(plugin);
|
|
7610
|
-
if (pendingPluginModels.size === 0) {
|
|
7611
|
-
return;
|
|
7612
|
-
}
|
|
7613
|
-
} catch {
|
|
7614
|
-
}
|
|
7615
|
-
}
|
|
7616
|
-
} else {
|
|
7617
|
-
await this.loadPluginModels(workspaceFolder, entry.uri, pendingPluginModels, collector);
|
|
7618
|
-
}
|
|
7619
|
-
}
|
|
7620
|
-
}
|
|
7621
7775
|
}
|
|
7622
7776
|
};
|
|
7623
7777
|
|
|
@@ -7634,10 +7788,11 @@ var ZModelLanguageModule = {
|
|
|
7634
7788
|
};
|
|
7635
7789
|
var ZModelSharedModule = {
|
|
7636
7790
|
workspace: {
|
|
7791
|
+
DocumentBuilder: /* @__PURE__ */ __name((services) => new ZModelDocumentBuilder(services), "DocumentBuilder"),
|
|
7637
7792
|
WorkspaceManager: /* @__PURE__ */ __name((services) => new ZModelWorkspaceManager(services), "WorkspaceManager")
|
|
7638
7793
|
}
|
|
7639
7794
|
};
|
|
7640
|
-
function createZModelLanguageServices(context) {
|
|
7795
|
+
function createZModelLanguageServices(context, logToConsole = false) {
|
|
7641
7796
|
const shared = inject(createDefaultSharedModule(context), ZModelGeneratedSharedModule, ZModelSharedModule);
|
|
7642
7797
|
const ZModelLanguage = inject(createDefaultModule({
|
|
7643
7798
|
shared
|
|
@@ -7647,30 +7802,41 @@ function createZModelLanguageServices(context) {
|
|
|
7647
7802
|
if (!context.connection) {
|
|
7648
7803
|
shared.workspace.ConfigurationProvider.initialized({});
|
|
7649
7804
|
}
|
|
7805
|
+
shared.workspace.DocumentBuilder.onBuildPhase(DocumentState2.Parsed, async (documents) => {
|
|
7806
|
+
for (const doc of documents) {
|
|
7807
|
+
if (doc.parseResult.lexerErrors.length > 0 || doc.parseResult.parserErrors.length > 0) {
|
|
7808
|
+
continue;
|
|
7809
|
+
}
|
|
7810
|
+
if (doc.uri.scheme !== "file") {
|
|
7811
|
+
continue;
|
|
7812
|
+
}
|
|
7813
|
+
const schemaPath = fileURLToPath3(doc.uri.toString());
|
|
7814
|
+
const pluginSchemas = getPluginDocuments(doc.parseResult.value, schemaPath);
|
|
7815
|
+
for (const plugin of pluginSchemas) {
|
|
7816
|
+
const pluginDoc = await shared.workspace.LangiumDocuments.getOrCreateDocument(URI3.file(path3.resolve(plugin)));
|
|
7817
|
+
shared.workspace.IndexManager.updateContent(pluginDoc);
|
|
7818
|
+
if (logToConsole) {
|
|
7819
|
+
console.log(`Loaded plugin model: ${plugin}`);
|
|
7820
|
+
}
|
|
7821
|
+
}
|
|
7822
|
+
}
|
|
7823
|
+
});
|
|
7650
7824
|
return {
|
|
7651
7825
|
shared,
|
|
7652
7826
|
ZModelLanguage
|
|
7653
7827
|
};
|
|
7654
7828
|
}
|
|
7655
7829
|
__name(createZModelLanguageServices, "createZModelLanguageServices");
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
function createZModelServices() {
|
|
7659
|
-
return createZModelLanguageServices(NodeFileSystem);
|
|
7830
|
+
function createZModelServices(logToConsole = false) {
|
|
7831
|
+
return createZModelLanguageServices(NodeFileSystem, logToConsole);
|
|
7660
7832
|
}
|
|
7661
7833
|
__name(createZModelServices, "createZModelServices");
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
}
|
|
7666
|
-
constructor(message) {
|
|
7667
|
-
super(message);
|
|
7668
|
-
}
|
|
7669
|
-
};
|
|
7670
|
-
async function loadDocument(fileName, pluginModelFiles = []) {
|
|
7671
|
-
const { ZModelLanguage: services } = createZModelServices();
|
|
7834
|
+
|
|
7835
|
+
// src/document.ts
|
|
7836
|
+
async function loadDocument(fileName, additionalModelFiles = []) {
|
|
7837
|
+
const { ZModelLanguage: services } = createZModelServices(false);
|
|
7672
7838
|
const extensions = services.LanguageMetaData.fileExtensions;
|
|
7673
|
-
if (!extensions.includes(
|
|
7839
|
+
if (!extensions.includes(path4.extname(fileName))) {
|
|
7674
7840
|
return {
|
|
7675
7841
|
success: false,
|
|
7676
7842
|
errors: [
|
|
@@ -7688,23 +7854,27 @@ async function loadDocument(fileName, pluginModelFiles = []) {
|
|
|
7688
7854
|
warnings: []
|
|
7689
7855
|
};
|
|
7690
7856
|
}
|
|
7691
|
-
const _dirname = typeof __dirname !== "undefined" ? __dirname :
|
|
7692
|
-
const stdLib = await services.shared.workspace.LangiumDocuments.getOrCreateDocument(
|
|
7693
|
-
const pluginDocs = await Promise.all(pluginModelFiles.map((file) => services.shared.workspace.LangiumDocuments.getOrCreateDocument(URI3.file(path3.resolve(file)))));
|
|
7857
|
+
const _dirname = typeof __dirname !== "undefined" ? __dirname : path4.dirname(fileURLToPath4(import.meta.url));
|
|
7858
|
+
const stdLib = await services.shared.workspace.LangiumDocuments.getOrCreateDocument(URI4.file(path4.resolve(path4.join(_dirname, "../res", STD_LIB_MODULE_NAME))));
|
|
7694
7859
|
const langiumDocuments = services.shared.workspace.LangiumDocuments;
|
|
7695
|
-
const document = await langiumDocuments.getOrCreateDocument(
|
|
7860
|
+
const document = await langiumDocuments.getOrCreateDocument(URI4.file(path4.resolve(fileName)));
|
|
7696
7861
|
const importedURIs = await loadImports(document, langiumDocuments);
|
|
7697
7862
|
const importedDocuments = [];
|
|
7698
7863
|
for (const uri of importedURIs) {
|
|
7699
7864
|
importedDocuments.push(await langiumDocuments.getOrCreateDocument(uri));
|
|
7700
7865
|
}
|
|
7866
|
+
const additionalDocs = await Promise.all(additionalModelFiles.map((file) => services.shared.workspace.LangiumDocuments.getOrCreateDocument(URI4.file(path4.resolve(file)))));
|
|
7701
7867
|
await services.shared.workspace.DocumentBuilder.build([
|
|
7702
7868
|
stdLib,
|
|
7703
|
-
...
|
|
7869
|
+
...additionalDocs,
|
|
7704
7870
|
document,
|
|
7705
7871
|
...importedDocuments
|
|
7706
7872
|
], {
|
|
7707
|
-
validation:
|
|
7873
|
+
validation: {
|
|
7874
|
+
stopAfterLexingErrors: true,
|
|
7875
|
+
stopAfterParsingErrors: true,
|
|
7876
|
+
stopAfterLinkingErrors: true
|
|
7877
|
+
}
|
|
7708
7878
|
});
|
|
7709
7879
|
const diagnostics = langiumDocuments.all.flatMap((doc) => (doc.diagnostics ?? []).map((diag) => ({
|
|
7710
7880
|
doc,
|
|
@@ -7714,7 +7884,7 @@ async function loadDocument(fileName, pluginModelFiles = []) {
|
|
|
7714
7884
|
const warnings = [];
|
|
7715
7885
|
if (diagnostics.length > 0) {
|
|
7716
7886
|
for (const { doc, diag } of diagnostics) {
|
|
7717
|
-
const message = `${
|
|
7887
|
+
const message = `${path4.relative(process.cwd(), doc.uri.fsPath)}:${diag.range.start.line + 1}:${diag.range.start.character + 1} - ${diag.message}`;
|
|
7718
7888
|
if (diag.severity === 1) {
|
|
7719
7889
|
errors.push(message);
|
|
7720
7890
|
} else {
|
|
@@ -7763,7 +7933,7 @@ async function loadImports(document, documents, uris = /* @__PURE__ */ new Set()
|
|
|
7763
7933
|
}
|
|
7764
7934
|
}
|
|
7765
7935
|
}
|
|
7766
|
-
return Array.from(uris).filter((x) => uriString != x).map((e) =>
|
|
7936
|
+
return Array.from(uris).filter((x) => uriString != x).map((e) => URI4.parse(e));
|
|
7767
7937
|
}
|
|
7768
7938
|
__name(loadImports, "loadImports");
|
|
7769
7939
|
function mergeImportsDeclarations(documents, model) {
|
|
@@ -7813,7 +7983,6 @@ function validationAfterImportMerge(model) {
|
|
|
7813
7983
|
}
|
|
7814
7984
|
__name(validationAfterImportMerge, "validationAfterImportMerge");
|
|
7815
7985
|
export {
|
|
7816
|
-
DocumentLoadError,
|
|
7817
7986
|
ZModelLanguageMetaData,
|
|
7818
7987
|
ZModelLanguageModule,
|
|
7819
7988
|
ZModelSharedModule,
|