@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.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/index.ts
11
- import { isAstNode, URI as URI3 } from "langium";
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 path3 from "path";
15
- import { fileURLToPath as fileURLToPath2 } from "url";
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
- decl.mixins.forEach((mixin) => {
5217
- const baseDecl = mixin.ref;
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" && isFromStdlib(node.function.ref);
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((m) => hasAttribute(m, "@@auth"));
5428
+ let authModel = decls.find((d) => hasAttribute(d, "@@auth"));
5428
5429
  if (!authModel) {
5429
- authModel = decls.find((m) => m.name === "User");
5430
+ authModel = decls.find((d) => d.name === "User");
5430
5431
  }
5431
5432
  return authModel;
5432
5433
  }
5433
5434
  __name(getAuthDecl, "getAuthDecl");
5434
- function isFutureInvocation(node) {
5435
- return isInvocationExpr(node) && node.function.ref?.name === "future" && isFromStdlib(node.function.ref);
5435
+ function isBeforeInvocation(node) {
5436
+ return isInvocationExpr(node) && node.function.ref?.name === "before";
5436
5437
  }
5437
- __name(isFutureInvocation, "isFutureInvocation");
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
- invariant(mixin.ref, `Mixin ${mixin.$refText} is not resolved`);
5493
- fields.push(...getAllFields(mixin.ref, includeIgnored, seen));
5493
+ if (mixin.ref) {
5494
+ fields.push(...getAllFields(mixin.ref, includeIgnored, seen));
5495
+ }
5494
5496
  }
5495
5497
  if (isDataModel(decl) && decl.baseModel) {
5496
- invariant(decl.baseModel.ref, `Base model ${decl.baseModel.$refText} is not resolved`);
5497
- fields.push(...getAllFields(decl.baseModel.ref, includeIgnored, seen));
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
- invariant(mixin.ref, `Mixin ${mixin.$refText} is not resolved`);
5511
- attributes.push(...getAllAttributes(mixin.ref, seen));
5513
+ if (mixin.ref) {
5514
+ attributes.push(...getAllAttributes(mixin.ref, seen));
5515
+ }
5512
5516
  }
5513
5517
  if (isDataModel(decl) && decl.baseModel) {
5514
- invariant(decl.baseModel.ref, `Base model ${decl.baseModel.$refText} is not resolved`);
5515
- attributes.push(...getAllAttributes(decl.baseModel.ref, seen));
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
- this.rejectEncryptedFields(attr, accept);
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) => isFutureExpr(node))) {
5684
- accept("error", `"future()" is not allowed in field-level policy rules`, {
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
- _checkUnique(attr, accept) {
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", `\`@@unique\` expects at least one field reference`, {
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 \`@@unique\``, {
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, "_checkUnique", null);
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 as invariant2 } from "@zenstackhq/common-helpers";
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
- invariant2(model.baseModel.ref, "baseModel must be resolved");
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
- invariant2(current.baseModel.ref, "baseModel must be resolved");
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
- if (typeof expr.left.$resolvedType?.decl !== "string" || !supportedShapes.includes(expr.left.$resolvedType.decl)) {
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 expr.right.$resolvedType?.decl !== "string" || !supportedShapes.includes(expr.right.$resolvedType.decl)) {
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 (expr.left.$resolvedType.decl === "DateTime" && expr.right.$resolvedType.decl !== "DateTime") {
6658
+ if (leftResolvedDecl === "DateTime" && rightResolvedDecl && rightResolvedDecl !== "DateTime") {
6525
6659
  accept("error", "incompatible operand types", {
6526
6660
  node: expr
6527
6661
  });
6528
- } else if (expr.right.$resolvedType.decl === "DateTime" && expr.left.$resolvedType.decl !== "DateTime") {
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 model-typed fields are not supported", {
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 model-typed fields are not supported", {
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
- if (isFromStdlib(funcDecl)) {
6663
- let curr = expr.$container;
6664
- let containerAttribute;
6665
- while (curr) {
6666
- if (isDataModelAttribute(curr) || isDataFieldAttribute(curr)) {
6667
- containerAttribute = curr;
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
- const exprContext = match(containerAttribute?.decl.$refText).with("@default", () => ExpressionContext.DefaultValue).with(P.union("@@allow", "@@deny", "@allow", "@deny"), () => ExpressionContext.AccessPolicy).with("@@validate", () => ExpressionContext.ValidationRule).with("@@index", () => ExpressionContext.Index).otherwise(() => void 0);
6673
- const funcAllowedContext = getFunctionExpressionContext(funcDecl);
6674
- if (exprContext && !funcAllowedContext.includes(exprContext)) {
6675
- accept("error", `function "${funcDecl.name}" is not allowed in the current context: ${exprContext}`, {
6676
- node: expr
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
- this.shouldCheck(node) && new SchemaValidator(this.services.shared.workspace.LangiumDocuments).validate(node, accept);
7145
+ new SchemaValidator(this.services.shared.workspace.LangiumDocuments).validate(node, accept);
6958
7146
  }
6959
7147
  checkDataSource(node, accept) {
6960
- this.shouldCheck(node) && new DataSourceValidator().validate(node, accept);
7148
+ new DataSourceValidator().validate(node, accept);
6961
7149
  }
6962
7150
  checkDataModel(node, accept) {
6963
- this.shouldCheck(node) && new DataModelValidator().validate(node, accept);
7151
+ new DataModelValidator().validate(node, accept);
6964
7152
  }
6965
7153
  checkTypeDef(node, accept) {
6966
- this.shouldCheck(node) && new TypeDefValidator().validate(node, accept);
7154
+ new TypeDefValidator().validate(node, accept);
6967
7155
  }
6968
7156
  checkEnum(node, accept) {
6969
- this.shouldCheck(node) && new EnumValidator().validate(node, accept);
7157
+ new EnumValidator().validate(node, accept);
6970
7158
  }
6971
7159
  checkAttribute(node, accept) {
6972
- this.shouldCheck(node) && new AttributeValidator().validate(node, accept);
7160
+ new AttributeValidator().validate(node, accept);
6973
7161
  }
6974
7162
  checkExpression(node, accept) {
6975
- this.shouldCheck(node) && new ExpressionValidator().validate(node, accept);
7163
+ new ExpressionValidator().validate(node, accept);
6976
7164
  }
6977
7165
  checkFunctionInvocation(node, accept) {
6978
- this.shouldCheck(node) && new FunctionInvocationValidator().validate(node, accept);
7166
+ new FunctionInvocationValidator().validate(node, accept);
6979
7167
  }
6980
7168
  checkFunctionDecl(node, accept) {
6981
- this.shouldCheck(node) && new FunctionDeclValidator().validate(node, accept);
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, isReference } from "langium";
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(container, property, document, extraScopes) {
7009
- if (this.resolveFromScopeProviders(container, property, document, extraScopes)) {
7225
+ linkReference(refInfo, document, extraScopes) {
7226
+ const defaultRef = refInfo.reference;
7227
+ if (defaultRef._ref) {
7010
7228
  return;
7011
7229
  }
7012
- const reference = container[property];
7013
- this.doLink({
7014
- reference,
7015
- container,
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(node, property, document, providers) {
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(node, "function", document, extraScopes);
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 (isFutureExpr(node)) {
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, "target", document, [
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, "target", document, [
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
- for (const [property, value] of Object.entries(node)) {
7295
- if (!property.startsWith("$")) {
7296
- if (isReference(value)) {
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 (isFutureInvocation(operand)) {
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, UriUtils as UriUtils2 } from "langium";
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(fileURLToPath(import.meta.url));
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
- // src/index.ts
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
- var DocumentLoadError = class extends Error {
7663
- static {
7664
- __name(this, "DocumentLoadError");
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(path3.extname(fileName))) {
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 : path3.dirname(fileURLToPath2(import.meta.url));
7692
- const stdLib = await services.shared.workspace.LangiumDocuments.getOrCreateDocument(URI3.file(path3.resolve(path3.join(_dirname, "../res", STD_LIB_MODULE_NAME))));
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(URI3.file(path3.resolve(fileName)));
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
- ...pluginDocs,
7869
+ ...additionalDocs,
7704
7870
  document,
7705
7871
  ...importedDocuments
7706
7872
  ], {
7707
- validation: true
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 = `${path3.relative(process.cwd(), doc.uri.fsPath)}:${diag.range.start.line + 1}:${diag.range.start.character + 1} - ${diag.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) => URI3.parse(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,