zenstack 1.0.16 → 1.1.1

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.
Files changed (154) hide show
  1. package/README.md +93 -24
  2. package/bin/post-install.js +1 -1
  3. package/cli/actions/generate.d.ts +13 -0
  4. package/cli/actions/generate.js +71 -0
  5. package/cli/actions/generate.js.map +1 -0
  6. package/cli/actions/index.d.ts +3 -0
  7. package/cli/actions/index.js +20 -0
  8. package/cli/actions/index.js.map +1 -0
  9. package/cli/actions/info.d.ts +4 -0
  10. package/cli/actions/info.js +63 -0
  11. package/cli/actions/info.js.map +1 -0
  12. package/cli/actions/init.d.ts +12 -0
  13. package/cli/actions/init.js +83 -0
  14. package/cli/actions/init.js.map +1 -0
  15. package/cli/cli-util.d.ts +14 -11
  16. package/cli/cli-util.js +150 -82
  17. package/cli/cli-util.js.map +1 -1
  18. package/cli/config.d.ts +10 -0
  19. package/cli/config.js +62 -0
  20. package/cli/config.js.map +1 -0
  21. package/cli/index.d.ts +4 -12
  22. package/cli/index.js +36 -29
  23. package/cli/index.js.map +1 -1
  24. package/cli/plugin-runner.d.ts +13 -3
  25. package/cli/plugin-runner.js +165 -59
  26. package/cli/plugin-runner.js.map +1 -1
  27. package/constants.js +1 -1
  28. package/language-server/constants.d.ts +7 -0
  29. package/language-server/constants.js +8 -1
  30. package/language-server/constants.js.map +1 -1
  31. package/language-server/utils.d.ts +1 -14
  32. package/language-server/utils.js +2 -38
  33. package/language-server/utils.js.map +1 -1
  34. package/language-server/validator/attribute-application-validator.d.ts +15 -0
  35. package/language-server/validator/attribute-application-validator.js +246 -0
  36. package/language-server/validator/attribute-application-validator.js.map +1 -0
  37. package/language-server/validator/attribute-validator.d.ts +1 -1
  38. package/language-server/validator/attribute-validator.js +4 -1
  39. package/language-server/validator/attribute-validator.js.map +1 -1
  40. package/language-server/validator/datamodel-validator.d.ts +7 -0
  41. package/language-server/validator/datamodel-validator.js +84 -33
  42. package/language-server/validator/datamodel-validator.js.map +1 -1
  43. package/language-server/validator/enum-validator.js +3 -6
  44. package/language-server/validator/enum-validator.js.map +1 -1
  45. package/language-server/validator/expression-validator.d.ts +1 -1
  46. package/language-server/validator/expression-validator.js +108 -3
  47. package/language-server/validator/expression-validator.js.map +1 -1
  48. package/language-server/validator/function-decl-validator.d.ts +9 -0
  49. package/language-server/validator/function-decl-validator.js +13 -0
  50. package/language-server/validator/function-decl-validator.js.map +1 -0
  51. package/language-server/validator/function-invocation-validator.d.ts +11 -0
  52. package/language-server/validator/function-invocation-validator.js +135 -0
  53. package/language-server/validator/function-invocation-validator.js.map +1 -0
  54. package/language-server/validator/schema-validator.d.ts +4 -1
  55. package/language-server/validator/schema-validator.js +28 -7
  56. package/language-server/validator/schema-validator.js.map +1 -1
  57. package/language-server/validator/utils.d.ts +3 -4
  58. package/language-server/validator/utils.js +20 -123
  59. package/language-server/validator/utils.js.map +1 -1
  60. package/language-server/validator/zmodel-validator.d.ts +5 -1
  61. package/language-server/validator/zmodel-validator.js +18 -4
  62. package/language-server/validator/zmodel-validator.js.map +1 -1
  63. package/language-server/zmodel-code-action.d.ts +2 -1
  64. package/language-server/zmodel-code-action.js +46 -21
  65. package/language-server/zmodel-code-action.js.map +1 -1
  66. package/language-server/zmodel-definition.d.ts +7 -0
  67. package/language-server/zmodel-definition.js +31 -0
  68. package/language-server/zmodel-definition.js.map +1 -0
  69. package/language-server/zmodel-formatter.js +2 -2
  70. package/language-server/zmodel-formatter.js.map +1 -1
  71. package/language-server/zmodel-linker.d.ts +3 -0
  72. package/language-server/zmodel-linker.js +122 -41
  73. package/language-server/zmodel-linker.js.map +1 -1
  74. package/language-server/zmodel-module.js +4 -1
  75. package/language-server/zmodel-module.js.map +1 -1
  76. package/language-server/zmodel-scope.d.ts +7 -1
  77. package/language-server/zmodel-scope.js +57 -1
  78. package/language-server/zmodel-scope.js.map +1 -1
  79. package/language-server/zmodel-workspace-manager.d.ts +5 -1
  80. package/language-server/zmodel-workspace-manager.js +101 -0
  81. package/language-server/zmodel-workspace-manager.js.map +1 -1
  82. package/package.json +27 -20
  83. package/plugins/access-policy/expression-writer.d.ts +7 -0
  84. package/plugins/access-policy/expression-writer.js +325 -106
  85. package/plugins/access-policy/expression-writer.js.map +1 -1
  86. package/plugins/access-policy/index.d.ts +3 -3
  87. package/plugins/access-policy/index.js +3 -5
  88. package/plugins/access-policy/index.js.map +1 -1
  89. package/plugins/access-policy/policy-guard-generator.d.ts +10 -3
  90. package/plugins/access-policy/policy-guard-generator.js +406 -121
  91. package/plugins/access-policy/policy-guard-generator.js.map +1 -1
  92. package/plugins/model-meta/index.d.ts +3 -3
  93. package/plugins/model-meta/index.js +110 -46
  94. package/plugins/model-meta/index.js.map +1 -1
  95. package/plugins/plugin-utils.d.ts +8 -7
  96. package/plugins/plugin-utils.js +55 -21
  97. package/plugins/plugin-utils.js.map +1 -1
  98. package/plugins/prisma/index.d.ts +3 -3
  99. package/plugins/prisma/index.js +3 -5
  100. package/plugins/prisma/index.js.map +1 -1
  101. package/plugins/prisma/prisma-builder.d.ts +7 -14
  102. package/plugins/prisma/prisma-builder.js +29 -34
  103. package/plugins/prisma/prisma-builder.js.map +1 -1
  104. package/plugins/prisma/schema-generator.d.ts +7 -3
  105. package/plugins/prisma/schema-generator.js +146 -102
  106. package/plugins/prisma/schema-generator.js.map +1 -1
  107. package/plugins/prisma/zmodel-code-generator.d.ts +3 -1
  108. package/plugins/prisma/zmodel-code-generator.js +12 -2
  109. package/plugins/prisma/zmodel-code-generator.js.map +1 -1
  110. package/plugins/zod/generator.d.ts +4 -0
  111. package/plugins/zod/generator.js +298 -0
  112. package/plugins/zod/generator.js.map +1 -0
  113. package/plugins/zod/index.d.ts +4 -0
  114. package/plugins/zod/index.js +24 -0
  115. package/plugins/zod/index.js.map +1 -0
  116. package/plugins/zod/transformer.d.ts +68 -0
  117. package/plugins/zod/transformer.js +554 -0
  118. package/plugins/zod/transformer.js.map +1 -0
  119. package/plugins/zod/types.d.ts +25 -0
  120. package/plugins/zod/types.js.map +1 -0
  121. package/plugins/zod/utils/removeDir.d.ts +1 -0
  122. package/plugins/zod/utils/removeDir.js +30 -0
  123. package/plugins/zod/utils/removeDir.js.map +1 -0
  124. package/plugins/zod/utils/schema-gen.d.ts +3 -0
  125. package/plugins/zod/utils/schema-gen.js +188 -0
  126. package/plugins/zod/utils/schema-gen.js.map +1 -0
  127. package/res/starter.zmodel +6 -8
  128. package/res/stdlib.zmodel +238 -74
  129. package/telemetry.d.ts +2 -1
  130. package/telemetry.js +21 -11
  131. package/telemetry.js.map +1 -1
  132. package/utils/ast-utils.d.ts +12 -15
  133. package/utils/ast-utils.js +117 -66
  134. package/utils/ast-utils.js.map +1 -1
  135. package/utils/pkg-utils.d.ts +2 -2
  136. package/utils/pkg-utils.js +34 -16
  137. package/utils/pkg-utils.js.map +1 -1
  138. package/utils/typescript-expression-transformer.d.ts +54 -0
  139. package/utils/typescript-expression-transformer.js +326 -0
  140. package/utils/typescript-expression-transformer.js.map +1 -0
  141. package/utils/version-utils.js +7 -1
  142. package/utils/version-utils.js.map +1 -1
  143. package/plugins/access-policy/typescript-expression-transformer.d.ts +0 -26
  144. package/plugins/access-policy/typescript-expression-transformer.js +0 -111
  145. package/plugins/access-policy/typescript-expression-transformer.js.map +0 -1
  146. package/plugins/access-policy/utils.d.ts +0 -5
  147. package/plugins/access-policy/utils.js +0 -14
  148. package/plugins/access-policy/utils.js.map +0 -1
  149. package/plugins/access-policy/zod-schema-generator.d.ts +0 -12
  150. package/plugins/access-policy/zod-schema-generator.js +0 -158
  151. package/plugins/access-policy/zod-schema-generator.js.map +0 -1
  152. package/types.d.ts +0 -12
  153. package/types.js.map +0 -1
  154. /package/{types.js → plugins/zod/types.js} +0 -0
@@ -1,18 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ast_1 = require("@zenstackhq/language/ast");
4
+ const sdk_1 = require("@zenstackhq/sdk");
4
5
  const ast_utils_1 = require("../../utils/ast-utils");
5
6
  /**
6
7
  * Validates expressions.
7
8
  */
8
9
  class ExpressionValidator {
9
10
  validate(expr, accept) {
11
+ var _a;
12
+ // deal with a few cases where reference resolution fail silently
10
13
  if (!expr.$resolvedType) {
11
14
  if ((0, ast_utils_1.isAuthInvocation)(expr)) {
12
15
  // check was done at link time
13
16
  accept('error', 'auth() cannot be resolved because no "User" model is defined', { node: expr });
14
17
  }
15
- else if (this.isCollectionPredicate(expr)) {
18
+ else if ((0, ast_utils_1.isCollectionPredicate)(expr)) {
16
19
  accept('error', 'collection predicate can only be used on an array of model type', { node: expr });
17
20
  }
18
21
  else {
@@ -21,9 +24,111 @@ class ExpressionValidator {
21
24
  });
22
25
  }
23
26
  }
27
+ if (((_a = expr.$resolvedType) === null || _a === void 0 ? void 0 : _a.decl) === 'Unsupported') {
28
+ accept('error', 'Field of "Unsupported" type cannot be used in expressions', { node: expr });
29
+ }
30
+ // extra validations by expression type
31
+ switch (expr.$type) {
32
+ case 'BinaryExpr':
33
+ this.validateBinaryExpr(expr, accept);
34
+ break;
35
+ }
24
36
  }
25
- isCollectionPredicate(expr) {
26
- return (0, ast_1.isBinaryExpr)(expr) && ['?', '!', '^'].includes(expr.operator);
37
+ validateBinaryExpr(expr, accept) {
38
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
39
+ switch (expr.operator) {
40
+ case 'in': {
41
+ if (typeof ((_a = expr.left.$resolvedType) === null || _a === void 0 ? void 0 : _a.decl) !== 'string' && !(0, ast_1.isEnum)((_b = expr.left.$resolvedType) === null || _b === void 0 ? void 0 : _b.decl)) {
42
+ accept('error', 'left operand of "in" must be of scalar type', { node: expr.left });
43
+ }
44
+ if (!((_c = expr.right.$resolvedType) === null || _c === void 0 ? void 0 : _c.array)) {
45
+ accept('error', 'right operand of "in" must be an array', {
46
+ node: expr.right,
47
+ });
48
+ }
49
+ break;
50
+ }
51
+ case '>':
52
+ case '>=':
53
+ case '<':
54
+ case '<=':
55
+ case '&&':
56
+ case '||': {
57
+ if ((_d = expr.left.$resolvedType) === null || _d === void 0 ? void 0 : _d.array) {
58
+ accept('error', 'operand cannot be an array', { node: expr.left });
59
+ break;
60
+ }
61
+ if ((_e = expr.right.$resolvedType) === null || _e === void 0 ? void 0 : _e.array) {
62
+ accept('error', 'operand cannot be an array', { node: expr.right });
63
+ break;
64
+ }
65
+ let supportedShapes;
66
+ if (['>', '>=', '<', '<='].includes(expr.operator)) {
67
+ supportedShapes = ['Int', 'Float', 'DateTime', 'Any'];
68
+ }
69
+ else {
70
+ supportedShapes = ['Boolean', 'Any'];
71
+ }
72
+ if (typeof ((_f = expr.left.$resolvedType) === null || _f === void 0 ? void 0 : _f.decl) !== 'string' ||
73
+ !supportedShapes.includes(expr.left.$resolvedType.decl)) {
74
+ accept('error', `invalid operand type for "${expr.operator}" operator`, {
75
+ node: expr.left,
76
+ });
77
+ return;
78
+ }
79
+ if (typeof ((_g = expr.right.$resolvedType) === null || _g === void 0 ? void 0 : _g.decl) !== 'string' ||
80
+ !supportedShapes.includes(expr.right.$resolvedType.decl)) {
81
+ accept('error', `invalid operand type for "${expr.operator}" operator`, {
82
+ node: expr.right,
83
+ });
84
+ return;
85
+ }
86
+ // DateTime comparison is only allowed between two DateTime values
87
+ if (expr.left.$resolvedType.decl === 'DateTime' && expr.right.$resolvedType.decl !== 'DateTime') {
88
+ accept('error', 'incompatible operand types', { node: expr });
89
+ }
90
+ else if (expr.right.$resolvedType.decl === 'DateTime' &&
91
+ expr.left.$resolvedType.decl !== 'DateTime') {
92
+ accept('error', 'incompatible operand types', { node: expr });
93
+ }
94
+ break;
95
+ }
96
+ case '==':
97
+ case '!=': {
98
+ if (!!((_h = expr.left.$resolvedType) === null || _h === void 0 ? void 0 : _h.array) !== !!((_j = expr.right.$resolvedType) === null || _j === void 0 ? void 0 : _j.array)) {
99
+ accept('error', 'incompatible operand types', { node: expr });
100
+ break;
101
+ }
102
+ // disallow comparing model type with scalar type or comparison between
103
+ // incompatible model types
104
+ const leftType = (_k = expr.left.$resolvedType) === null || _k === void 0 ? void 0 : _k.decl;
105
+ const rightType = (_l = expr.right.$resolvedType) === null || _l === void 0 ? void 0 : _l.decl;
106
+ if ((0, ast_1.isDataModel)(leftType) && (0, ast_1.isDataModel)(rightType)) {
107
+ if (leftType != rightType) {
108
+ // incompatible model types
109
+ // TODO: inheritance case?
110
+ accept('error', 'incompatible operand types', { node: expr });
111
+ }
112
+ // not supported:
113
+ // - foo == bar
114
+ // - foo == this
115
+ if ((0, sdk_1.isDataModelFieldReference)(expr.left) &&
116
+ ((0, ast_1.isThisExpr)(expr.right) || (0, sdk_1.isDataModelFieldReference)(expr.right))) {
117
+ accept('error', 'comparison between model-typed fields are not supported', { node: expr });
118
+ }
119
+ else if ((0, sdk_1.isDataModelFieldReference)(expr.right) &&
120
+ ((0, ast_1.isThisExpr)(expr.left) || (0, sdk_1.isDataModelFieldReference)(expr.left))) {
121
+ accept('error', 'comparison between model-typed fields are not supported', { node: expr });
122
+ }
123
+ }
124
+ else if (((0, ast_1.isDataModel)(leftType) && !(0, ast_1.isNullExpr)(expr.right)) ||
125
+ ((0, ast_1.isDataModel)(rightType) && !(0, ast_1.isNullExpr)(expr.left))) {
126
+ // comparing model against scalar (except null)
127
+ accept('error', 'incompatible operand types', { node: expr });
128
+ }
129
+ break;
130
+ }
131
+ }
27
132
  }
28
133
  }
29
134
  exports.default = ExpressionValidator;
@@ -1 +1 @@
1
- {"version":3,"file":"expression-validator.js","sourceRoot":"","sources":["../../../src/language-server/validator/expression-validator.ts"],"names":[],"mappings":";;AAAA,kDAAoE;AAEpE,qDAAyD;AAGzD;;GAEG;AACH,MAAqB,mBAAmB;IACpC,QAAQ,CAAC,IAAgB,EAAE,MAA0B;QACjD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;YACrB,IAAI,IAAA,4BAAgB,EAAC,IAAI,CAAC,EAAE;gBACxB,8BAA8B;gBAC9B,MAAM,CAAC,OAAO,EAAE,8DAA8D,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;aACnG;iBAAM,IAAI,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE;gBACzC,MAAM,CAAC,OAAO,EAAE,iEAAiE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;aACtG;iBAAM;gBACH,MAAM,CAAC,OAAO,EAAE,+BAA+B,EAAE;oBAC7C,IAAI,EAAE,IAAI;iBACb,CAAC,CAAC;aACN;SACJ;IACL,CAAC;IAEO,qBAAqB,CAAC,IAAgB;QAC1C,OAAO,IAAA,kBAAY,EAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzE,CAAC;CACJ;AAnBD,sCAmBC"}
1
+ {"version":3,"file":"expression-validator.js","sourceRoot":"","sources":["../../../src/language-server/validator/expression-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { FunctionDecl } from '@zenstackhq/language/ast';
2
+ import { ValidationAcceptor } from 'langium';
3
+ import { AstValidator } from '../types';
4
+ /**
5
+ * Validates function declarations.
6
+ */
7
+ export default class FunctionDeclValidator implements AstValidator<FunctionDecl> {
8
+ validate(funcDecl: FunctionDecl, accept: ValidationAcceptor): void;
9
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const attribute_application_validator_1 = require("./attribute-application-validator");
4
+ /**
5
+ * Validates function declarations.
6
+ */
7
+ class FunctionDeclValidator {
8
+ validate(funcDecl, accept) {
9
+ funcDecl.attributes.forEach((attr) => (0, attribute_application_validator_1.validateAttributeApplication)(attr, accept));
10
+ }
11
+ }
12
+ exports.default = FunctionDeclValidator;
13
+ //# sourceMappingURL=function-decl-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"function-decl-validator.js","sourceRoot":"","sources":["../../../src/language-server/validator/function-decl-validator.ts"],"names":[],"mappings":";;AAGA,uFAAiF;AAEjF;;GAEG;AACH,MAAqB,qBAAqB;IACtC,QAAQ,CAAC,QAAsB,EAAE,MAA0B;QACvD,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,8DAA4B,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACtF,CAAC;CACJ;AAJD,wCAIC"}
@@ -0,0 +1,11 @@
1
+ import { Expression, InvocationExpr } from '@zenstackhq/language/ast';
2
+ import { ValidationAcceptor } from 'langium';
3
+ import { AstValidator } from '../types';
4
+ /**
5
+ * InvocationExpr validation
6
+ */
7
+ export default class FunctionInvocationValidator implements AstValidator<Expression> {
8
+ validate(expr: InvocationExpr, accept: ValidationAcceptor): void;
9
+ private validateArgs;
10
+ private validateInvocationArg;
11
+ }
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ast_1 = require("@zenstackhq/language/ast");
4
+ const sdk_1 = require("@zenstackhq/sdk");
5
+ const ts_pattern_1 = require("ts-pattern");
6
+ const ast_utils_1 = require("../../utils/ast-utils");
7
+ const utils_1 = require("./utils");
8
+ /**
9
+ * InvocationExpr validation
10
+ */
11
+ class FunctionInvocationValidator {
12
+ validate(expr, accept) {
13
+ var _a, _b, _c, _d;
14
+ const funcDecl = expr.function.ref;
15
+ if (!funcDecl) {
16
+ accept('error', 'function cannot be resolved', { node: expr });
17
+ return;
18
+ }
19
+ if (!this.validateArgs(funcDecl, expr.args, accept)) {
20
+ return;
21
+ }
22
+ if ((0, sdk_1.isFromStdlib)(funcDecl)) {
23
+ // validate standard library functions
24
+ // find the containing attribute context for the invocation
25
+ let curr = expr.$container;
26
+ let containerAttribute;
27
+ while (curr) {
28
+ if ((0, ast_1.isDataModelAttribute)(curr) || (0, ast_1.isDataModelFieldAttribute)(curr)) {
29
+ containerAttribute = curr;
30
+ break;
31
+ }
32
+ curr = curr.$container;
33
+ }
34
+ // validate the context allowed for the function
35
+ const exprContext = (0, ts_pattern_1.match)(containerAttribute === null || containerAttribute === void 0 ? void 0 : containerAttribute.decl.$refText)
36
+ .with('@default', () => sdk_1.ExpressionContext.DefaultValue)
37
+ .with(ts_pattern_1.P.union('@@allow', '@@deny'), () => sdk_1.ExpressionContext.AccessPolicy)
38
+ .with('@@validate', () => sdk_1.ExpressionContext.ValidationRule)
39
+ .otherwise(() => undefined);
40
+ // get the context allowed for the function
41
+ const funcAllowedContext = (0, sdk_1.getFunctionExpressionContext)(funcDecl);
42
+ if (exprContext && !funcAllowedContext.includes(exprContext)) {
43
+ accept('error', `function "${funcDecl.name}" is not allowed in the current context: ${exprContext}`, {
44
+ node: expr,
45
+ });
46
+ return;
47
+ }
48
+ if (funcAllowedContext.includes(sdk_1.ExpressionContext.AccessPolicy) ||
49
+ funcAllowedContext.includes(sdk_1.ExpressionContext.ValidationRule)) {
50
+ // filter operation functions validation
51
+ // first argument must refer to a model field
52
+ const firstArg = (_b = (_a = expr.args) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.value;
53
+ if (firstArg) {
54
+ if (!(0, ast_utils_1.getDataModelFieldReference)(firstArg)) {
55
+ accept('error', 'first argument must be a field reference', { node: firstArg });
56
+ }
57
+ }
58
+ // second argument must be a literal or array of literal
59
+ const secondArg = (_d = (_c = expr.args) === null || _c === void 0 ? void 0 : _c[1]) === null || _d === void 0 ? void 0 : _d.value;
60
+ if (secondArg &&
61
+ // literal
62
+ !(0, ast_1.isLiteralExpr)(secondArg) &&
63
+ // enum field
64
+ !(0, sdk_1.isEnumFieldReference)(secondArg) &&
65
+ // array of literal/enum
66
+ !((0, ast_1.isArrayExpr)(secondArg) &&
67
+ secondArg.items.every((item) => (0, ast_1.isLiteralExpr)(item) || (0, sdk_1.isEnumFieldReference)(item)))) {
68
+ accept('error', 'second argument must be a literal, an enum, or an array of them', {
69
+ node: secondArg,
70
+ });
71
+ }
72
+ }
73
+ }
74
+ }
75
+ validateArgs(funcDecl, args, accept) {
76
+ let success = true;
77
+ for (let i = 0; i < funcDecl.params.length; i++) {
78
+ const param = funcDecl.params[i];
79
+ const arg = args[i];
80
+ if (!arg) {
81
+ if (!param.optional) {
82
+ accept('error', `missing argument for parameter "${param.name}"`, { node: funcDecl });
83
+ success = false;
84
+ }
85
+ }
86
+ else {
87
+ if (!this.validateInvocationArg(arg, param, accept)) {
88
+ success = false;
89
+ }
90
+ }
91
+ }
92
+ // TODO: do we need to complain for extra arguments?
93
+ return success;
94
+ }
95
+ validateInvocationArg(arg, param, accept) {
96
+ var _a;
97
+ const argResolvedType = (_a = arg === null || arg === void 0 ? void 0 : arg.value) === null || _a === void 0 ? void 0 : _a.$resolvedType;
98
+ if (!argResolvedType) {
99
+ accept('error', 'argument type cannot be resolved', { node: arg });
100
+ return false;
101
+ }
102
+ const dstType = param.type.type;
103
+ if (!dstType) {
104
+ accept('error', 'parameter type cannot be resolved', { node: param });
105
+ return false;
106
+ }
107
+ const dstIsArray = param.type.array;
108
+ const dstRef = param.type.reference;
109
+ if (dstType === 'Any' && !dstIsArray) {
110
+ // scalar 'any' can be assigned with anything
111
+ return true;
112
+ }
113
+ if (typeof argResolvedType.decl === 'string') {
114
+ // scalar type
115
+ if (!(0, utils_1.typeAssignable)(dstType, argResolvedType.decl, arg.value) || dstIsArray !== argResolvedType.array) {
116
+ accept('error', `argument is not assignable to parameter`, {
117
+ node: arg,
118
+ });
119
+ return false;
120
+ }
121
+ }
122
+ else {
123
+ // enum or model type
124
+ if (((dstRef === null || dstRef === void 0 ? void 0 : dstRef.ref) !== argResolvedType.decl && dstType !== 'Any') || dstIsArray !== argResolvedType.array) {
125
+ accept('error', `argument is not assignable to parameter`, {
126
+ node: arg,
127
+ });
128
+ return false;
129
+ }
130
+ }
131
+ return true;
132
+ }
133
+ }
134
+ exports.default = FunctionInvocationValidator;
135
+ //# sourceMappingURL=function-invocation-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"function-invocation-validator.js","sourceRoot":"","sources":["../../../src/language-server/validator/function-invocation-validator.ts"],"names":[],"mappings":";;AAAA,kDAYkC;AAClC,yCAAsH;AAEtH,2CAAsC;AACtC,qDAAmE;AAEnE,mCAAyC;AAEzC;;GAEG;AACH,MAAqB,2BAA2B;IAC5C,QAAQ,CAAC,IAAoB,EAAE,MAA0B;;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QACnC,IAAI,CAAC,QAAQ,EAAE;YACX,MAAM,CAAC,OAAO,EAAE,6BAA6B,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/D,OAAO;SACV;QAED,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;YACjD,OAAO;SACV;QAED,IAAI,IAAA,kBAAY,EAAC,QAAQ,CAAC,EAAE;YACxB,sCAAsC;YAEtC,2DAA2D;YAC3D,IAAI,IAAI,GAAwB,IAAI,CAAC,UAAU,CAAC;YAChD,IAAI,kBAA4E,CAAC;YACjF,OAAO,IAAI,EAAE;gBACT,IAAI,IAAA,0BAAoB,EAAC,IAAI,CAAC,IAAI,IAAA,+BAAyB,EAAC,IAAI,CAAC,EAAE;oBAC/D,kBAAkB,GAAG,IAAI,CAAC;oBAC1B,MAAM;iBACT;gBACD,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;aAC1B;YAED,gDAAgD;YAChD,MAAM,WAAW,GAAG,IAAA,kBAAK,EAAC,kBAAkB,aAAlB,kBAAkB,uBAAlB,kBAAkB,CAAE,IAAI,CAAC,QAAQ,CAAC;iBACvD,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,uBAAiB,CAAC,YAAY,CAAC;iBACtD,IAAI,CAAC,cAAC,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,uBAAiB,CAAC,YAAY,CAAC;iBACxE,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,uBAAiB,CAAC,cAAc,CAAC;iBAC1D,SAAS,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAEhC,2CAA2C;YAC3C,MAAM,kBAAkB,GAAG,IAAA,kCAA4B,EAAC,QAAQ,CAAC,CAAC;YAElE,IAAI,WAAW,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;gBAC1D,MAAM,CAAC,OAAO,EAAE,aAAa,QAAQ,CAAC,IAAI,4CAA4C,WAAW,EAAE,EAAE;oBACjG,IAAI,EAAE,IAAI;iBACb,CAAC,CAAC;gBACH,OAAO;aACV;YAED,IACI,kBAAkB,CAAC,QAAQ,CAAC,uBAAiB,CAAC,YAAY,CAAC;gBAC3D,kBAAkB,CAAC,QAAQ,CAAC,uBAAiB,CAAC,cAAc,CAAC,EAC/D;gBACE,wCAAwC;gBAExC,6CAA6C;gBAC7C,MAAM,QAAQ,GAAG,MAAA,MAAA,IAAI,CAAC,IAAI,0CAAG,CAAC,CAAC,0CAAE,KAAK,CAAC;gBACvC,IAAI,QAAQ,EAAE;oBACV,IAAI,CAAC,IAAA,sCAA0B,EAAC,QAAQ,CAAC,EAAE;wBACvC,MAAM,CAAC,OAAO,EAAE,0CAA0C,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;qBACnF;iBACJ;gBAED,wDAAwD;gBACxD,MAAM,SAAS,GAAG,MAAA,MAAA,IAAI,CAAC,IAAI,0CAAG,CAAC,CAAC,0CAAE,KAAK,CAAC;gBACxC,IACI,SAAS;oBACT,UAAU;oBACV,CAAC,IAAA,mBAAa,EAAC,SAAS,CAAC;oBACzB,aAAa;oBACb,CAAC,IAAA,0BAAoB,EAAC,SAAS,CAAC;oBAChC,wBAAwB;oBACxB,CAAC,CACG,IAAA,iBAAW,EAAC,SAAS,CAAC;wBACtB,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,mBAAa,EAAC,IAAI,CAAC,IAAI,IAAA,0BAAoB,EAAC,IAAI,CAAC,CAAC,CACrF,EACH;oBACE,MAAM,CAAC,OAAO,EAAE,iEAAiE,EAAE;wBAC/E,IAAI,EAAE,SAAS;qBAClB,CAAC,CAAC;iBACN;aACJ;SACJ;IACL,CAAC;IAEO,YAAY,CAAC,QAAsB,EAAE,IAAgB,EAAE,MAA0B;QACrF,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC7C,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACjC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACpB,IAAI,CAAC,GAAG,EAAE;gBACN,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;oBACjB,MAAM,CAAC,OAAO,EAAE,mCAAmC,KAAK,CAAC,IAAI,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;oBACtF,OAAO,GAAG,KAAK,CAAC;iBACnB;aACJ;iBAAM;gBACH,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE;oBACjD,OAAO,GAAG,KAAK,CAAC;iBACnB;aACJ;SACJ;QACD,oDAAoD;QACpD,OAAO,OAAO,CAAC;IACnB,CAAC;IAEO,qBAAqB,CAAC,GAAa,EAAE,KAAoB,EAAE,MAA0B;;QACzF,MAAM,eAAe,GAAG,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,KAAK,0CAAE,aAAa,CAAC;QAClD,IAAI,CAAC,eAAe,EAAE;YAClB,MAAM,CAAC,OAAO,EAAE,kCAAkC,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;YACnE,OAAO,KAAK,CAAC;SAChB;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAChC,IAAI,CAAC,OAAO,EAAE;YACV,MAAM,CAAC,OAAO,EAAE,mCAAmC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACtE,OAAO,KAAK,CAAC;SAChB;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QACpC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;QAEpC,IAAI,OAAO,KAAK,KAAK,IAAI,CAAC,UAAU,EAAE;YAClC,6CAA6C;YAC7C,OAAO,IAAI,CAAC;SACf;QAED,IAAI,OAAO,eAAe,CAAC,IAAI,KAAK,QAAQ,EAAE;YAC1C,cAAc;YACd,IAAI,CAAC,IAAA,sBAAc,EAAC,OAAO,EAAE,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,UAAU,KAAK,eAAe,CAAC,KAAK,EAAE;gBACnG,MAAM,CAAC,OAAO,EAAE,yCAAyC,EAAE;oBACvD,IAAI,EAAE,GAAG;iBACZ,CAAC,CAAC;gBACH,OAAO,KAAK,CAAC;aAChB;SACJ;aAAM;YACH,qBAAqB;YACrB,IAAI,CAAC,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,GAAG,MAAK,eAAe,CAAC,IAAI,IAAI,OAAO,KAAK,KAAK,CAAC,IAAI,UAAU,KAAK,eAAe,CAAC,KAAK,EAAE;gBACrG,MAAM,CAAC,OAAO,EAAE,yCAAyC,EAAE;oBACvD,IAAI,EAAE,GAAG;iBACZ,CAAC,CAAC;gBACH,OAAO,KAAK,CAAC;aAChB;SACJ;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ;AA5ID,8CA4IC"}
@@ -1,10 +1,13 @@
1
1
  import { Model } from '@zenstackhq/language/ast';
2
2
  import { AstValidator } from '../types';
3
- import { ValidationAcceptor } from 'langium';
3
+ import { LangiumDocuments, ValidationAcceptor } from 'langium';
4
4
  /**
5
5
  * Validates toplevel schema.
6
6
  */
7
7
  export default class SchemaValidator implements AstValidator<Model> {
8
+ protected readonly documents: LangiumDocuments;
9
+ constructor(documents: LangiumDocuments);
8
10
  validate(model: Model, accept: ValidationAcceptor): void;
9
11
  private validateDataSources;
12
+ private validateImports;
10
13
  }
@@ -3,26 +3,47 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const constants_1 = require("../constants");
4
4
  const ast_1 = require("@zenstackhq/language/ast");
5
5
  const utils_1 = require("./utils");
6
+ const ast_utils_1 = require("../../utils/ast-utils");
6
7
  /**
7
8
  * Validates toplevel schema.
8
9
  */
9
10
  class SchemaValidator {
11
+ constructor(documents) {
12
+ this.documents = documents;
13
+ }
10
14
  validate(model, accept) {
11
- var _a;
15
+ var _a, _b;
16
+ this.validateImports(model, accept);
12
17
  (0, utils_1.validateDuplicatedDeclarations)(model.declarations, accept);
13
- if (!((_a = model.$document) === null || _a === void 0 ? void 0 : _a.uri.path.endsWith(constants_1.STD_LIB_MODULE_NAME))) {
18
+ const importedModels = (0, ast_utils_1.resolveTransitiveImports)(this.documents, model);
19
+ const importedNames = new Set(importedModels.flatMap((m) => m.declarations.map((d) => d.name)));
20
+ for (const declaration of model.declarations) {
21
+ if (importedNames.has(declaration.name)) {
22
+ accept('error', `A ${declaration.name} already exists in an imported module`, {
23
+ node: declaration,
24
+ property: 'name',
25
+ });
26
+ }
27
+ }
28
+ if (!((_a = model.$document) === null || _a === void 0 ? void 0 : _a.uri.path.endsWith(constants_1.STD_LIB_MODULE_NAME)) &&
29
+ !((_b = model.$document) === null || _b === void 0 ? void 0 : _b.uri.path.endsWith(constants_1.PLUGIN_MODULE_NAME))) {
14
30
  this.validateDataSources(model, accept);
15
31
  }
16
32
  }
17
33
  validateDataSources(model, accept) {
18
- const dataSources = model.declarations.filter((d) => (0, ast_1.isDataSource)(d));
19
- if (dataSources.length === 0) {
20
- accept('error', 'Model must define a datasource', { node: model });
21
- }
22
- else if (dataSources.length > 1) {
34
+ const dataSources = (0, ast_utils_1.getAllDeclarationsFromImports)(this.documents, model).filter((d) => (0, ast_1.isDataSource)(d));
35
+ if (dataSources.length > 1) {
23
36
  accept('error', 'Multiple datasource declarations are not allowed', { node: dataSources[1] });
24
37
  }
25
38
  }
39
+ validateImports(model, accept) {
40
+ model.imports.forEach((imp) => {
41
+ const importedModel = (0, ast_utils_1.resolveImport)(this.documents, imp);
42
+ if (!importedModel) {
43
+ accept('error', `Cannot find model file ${imp.path}.zmodel`, { node: imp });
44
+ }
45
+ });
46
+ }
26
47
  }
27
48
  exports.default = SchemaValidator;
28
49
  //# sourceMappingURL=schema-validator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema-validator.js","sourceRoot":"","sources":["../../../src/language-server/validator/schema-validator.ts"],"names":[],"mappings":";;AAAA,4CAAmD;AACnD,kDAA+D;AAG/D,mCAAyD;AAEzD;;GAEG;AACH,MAAqB,eAAe;IAChC,QAAQ,CAAC,KAAY,EAAE,MAA0B;;QAC7C,IAAA,sCAA8B,EAAC,KAAK,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAE3D,IAAI,CAAC,CAAA,MAAA,KAAK,CAAC,SAAS,0CAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,+BAAmB,CAAC,CAAA,EAAE;YAC1D,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;SAC3C;IACL,CAAC;IAEO,mBAAmB,CAAC,KAAY,EAAE,MAA0B;QAChE,MAAM,WAAW,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,kBAAY,EAAC,CAAC,CAAC,CAAC,CAAC;QACtE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE;YAC1B,MAAM,CAAC,OAAO,EAAE,gCAAgC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;SACtE;aAAM,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE;YAC/B,MAAM,CAAC,OAAO,EAAE,kDAAkD,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SACjG;IACL,CAAC;CACJ;AAjBD,kCAiBC"}
1
+ {"version":3,"file":"schema-validator.js","sourceRoot":"","sources":["../../../src/language-server/validator/schema-validator.ts"],"names":[],"mappings":";;AAAA,4CAAuE;AACvE,kDAA+D;AAG/D,mCAAyD;AACzD,qDAA+G;AAE/G;;GAEG;AACH,MAAqB,eAAe;IAChC,YAA+B,SAA2B;QAA3B,cAAS,GAAT,SAAS,CAAkB;IAAG,CAAC;IAC9D,QAAQ,CAAC,KAAY,EAAE,MAA0B;;QAC7C,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACpC,IAAA,sCAA8B,EAAC,KAAK,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAE3D,MAAM,cAAc,GAAG,IAAA,oCAAwB,EAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAEvE,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEhG,KAAK,MAAM,WAAW,IAAI,KAAK,CAAC,YAAY,EAAE;YAC1C,IAAI,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;gBACrC,MAAM,CAAC,OAAO,EAAE,KAAK,WAAW,CAAC,IAAI,uCAAuC,EAAE;oBAC1E,IAAI,EAAE,WAAW;oBACjB,QAAQ,EAAE,MAAM;iBACnB,CAAC,CAAC;aACN;SACJ;QAED,IACI,CAAC,CAAA,MAAA,KAAK,CAAC,SAAS,0CAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,+BAAmB,CAAC,CAAA;YACxD,CAAC,CAAA,MAAA,KAAK,CAAC,SAAS,0CAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,8BAAkB,CAAC,CAAA,EACzD;YACE,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;SAC3C;IACL,CAAC;IAEO,mBAAmB,CAAC,KAAY,EAAE,MAA0B;QAChE,MAAM,WAAW,GAAG,IAAA,yCAA6B,EAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,kBAAY,EAAC,CAAC,CAAC,CAAC,CAAC;QACxG,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE;YACxB,MAAM,CAAC,OAAO,EAAE,kDAAkD,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SACjG;IACL,CAAC;IAEO,eAAe,CAAC,KAAY,EAAE,MAA0B;QAC5D,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAC1B,MAAM,aAAa,GAAG,IAAA,yBAAa,EAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YACzD,IAAI,CAAC,aAAa,EAAE;gBAChB,MAAM,CAAC,OAAO,EAAE,0BAA0B,GAAG,CAAC,IAAI,SAAS,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;aAC/E;QACL,CAAC,CAAC,CAAC;IACP,CAAC;CACJ;AA1CD,kCA0CC"}
@@ -1,4 +1,4 @@
1
- import { AttributeArg, AttributeParam, BuiltinType, DataModelAttribute, DataModelFieldAttribute, Expression, ExpressionType } from '@zenstackhq/language/ast';
1
+ import { AttributeArg, AttributeParam, BuiltinType, DataModelAttribute, DataModelFieldAttribute, Expression, ExpressionType, InternalAttribute } from '@zenstackhq/language/ast';
2
2
  import { AstNode, ValidationAcceptor } from 'langium';
3
3
  /**
4
4
  * Checks if the given declarations have duplicated names
@@ -17,9 +17,8 @@ export declare function typeAssignable(destType: ExpressionType, sourceType: Exp
17
17
  /**
18
18
  * Maps a ZModel builtin type to expression type
19
19
  */
20
- export declare function mapBuiltinTypeToExpressionType(type: BuiltinType | 'Any' | 'Null'): ExpressionType | 'Any';
20
+ export declare function mapBuiltinTypeToExpressionType(type: BuiltinType | 'Any' | 'Object' | 'Null' | 'Unsupported'): ExpressionType | 'Any';
21
21
  /**
22
22
  * Determines if the given attribute argument is assignable to the given attribute parameter
23
23
  */
24
- export declare function assignableToAttributeParam(arg: AttributeArg, param: AttributeParam, attr: DataModelAttribute | DataModelFieldAttribute): boolean;
25
- export declare function validateAttributeApplication(attr: DataModelAttribute | DataModelFieldAttribute, accept: ValidationAcceptor): boolean | undefined;
24
+ export declare function assignableToAttributeParam(arg: AttributeArg, param: AttributeParam, attr: DataModelAttribute | DataModelFieldAttribute | InternalAttribute): boolean;
@@ -1,12 +1,8 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.validateAttributeApplication = exports.assignableToAttributeParam = exports.mapBuiltinTypeToExpressionType = exports.typeAssignable = exports.getStringLiteral = exports.validateDuplicatedDeclarations = void 0;
3
+ exports.assignableToAttributeParam = exports.mapBuiltinTypeToExpressionType = exports.typeAssignable = exports.getStringLiteral = exports.validateDuplicatedDeclarations = void 0;
7
4
  const ast_1 = require("@zenstackhq/language/ast");
8
5
  const sdk_1 = require("@zenstackhq/sdk");
9
- const pluralize_1 = __importDefault(require("pluralize"));
10
6
  /**
11
7
  * Checks if the given declarations have duplicated names
12
8
  */
@@ -19,8 +15,15 @@ function validateDuplicatedDeclarations(decls, accept) {
19
15
  }, {});
20
16
  for (const [name, decls] of Object.entries(groupByName)) {
21
17
  if (decls.length > 1) {
18
+ let errorField = decls[1];
19
+ if (decls[0].$type === 'DataModelField') {
20
+ const nonInheritedFields = decls.filter((x) => !x.$isInherited);
21
+ if (nonInheritedFields.length > 0) {
22
+ errorField = nonInheritedFields.slice(-1)[0];
23
+ }
24
+ }
22
25
  accept('error', `Duplicated declaration name "${name}"`, {
23
- node: decls[1],
26
+ node: errorField,
24
27
  });
25
28
  }
26
29
  }
@@ -30,12 +33,7 @@ exports.validateDuplicatedDeclarations = validateDuplicatedDeclarations;
30
33
  * Try getting string value from a potential string literal expression
31
34
  */
32
35
  function getStringLiteral(node) {
33
- if ((0, ast_1.isLiteralExpr)(node) && typeof node.value === 'string') {
34
- return node.value;
35
- }
36
- else {
37
- return undefined;
38
- }
36
+ return (0, ast_1.isStringLiteral)(node) ? node.value : undefined;
39
37
  }
40
38
  exports.getStringLiteral = getStringLiteral;
41
39
  const isoDateTimeRegex = /^\d{4}(-\d\d(-\d\d(T\d\d:\d\d(:\d\d)?(\.\d+)?(([+-]\d\d:\d\d)|Z)?)?)?)?$/i;
@@ -44,7 +42,7 @@ const isoDateTimeRegex = /^\d{4}(-\d\d(-\d\d(T\d\d:\d\d(:\d\d)?(\.\d+)?(([+-]\d\
44
42
  */
45
43
  function typeAssignable(destType, sourceType, sourceExpr) {
46
44
  // implicit conversion from ISO datetime string to datetime
47
- if (destType === 'DateTime' && sourceType === 'String' && sourceExpr && (0, ast_1.isLiteralExpr)(sourceExpr)) {
45
+ if (destType === 'DateTime' && sourceType === 'String' && sourceExpr && (0, ast_1.isStringLiteral)(sourceExpr)) {
48
46
  const literal = getStringLiteral(sourceExpr);
49
47
  if (literal && isoDateTimeRegex.test(literal)) {
50
48
  // implicitly convert to DateTime
@@ -81,6 +79,10 @@ function mapBuiltinTypeToExpressionType(type) {
81
79
  case 'Json':
82
80
  case 'Bytes':
83
81
  return 'Any';
82
+ case 'Object':
83
+ return 'Object';
84
+ case 'Unsupported':
85
+ return 'Unsupported';
84
86
  }
85
87
  }
86
88
  exports.mapBuiltinTypeToExpressionType = mapBuiltinTypeToExpressionType;
@@ -96,6 +98,9 @@ function assignableToAttributeParam(arg, param, attr) {
96
98
  let dstType = param.type.type;
97
99
  let dstIsArray = param.type.array;
98
100
  const dstRef = param.type.reference;
101
+ if (dstType === 'Any' && !dstIsArray) {
102
+ return true;
103
+ }
99
104
  // destination is field reference or transitive field reference, check if
100
105
  // argument is reference or array or reference
101
106
  if (dstType === 'FieldReference' || dstType === 'TransitiveFieldReference') {
@@ -138,120 +143,12 @@ function assignableToAttributeParam(arg, param, attr) {
138
143
  dstType = 'Any';
139
144
  }
140
145
  }
141
- return (typeAssignable(dstType, argResolvedType.decl, arg.value) &&
142
- (dstType === 'Any' || dstIsArray === argResolvedType.array));
146
+ return typeAssignable(dstType, argResolvedType.decl, arg.value) && dstIsArray === argResolvedType.array;
143
147
  }
144
148
  else {
145
149
  // reference type
146
- return (dstRef === null || dstRef === void 0 ? void 0 : dstRef.ref) === argResolvedType.decl && dstIsArray === argResolvedType.array;
150
+ return ((dstRef === null || dstRef === void 0 ? void 0 : dstRef.ref) === argResolvedType.decl || dstType === 'Any') && dstIsArray === argResolvedType.array;
147
151
  }
148
152
  }
149
153
  exports.assignableToAttributeParam = assignableToAttributeParam;
150
- function validateAttributeApplication(attr, accept) {
151
- const decl = attr.decl.ref;
152
- if (!decl) {
153
- return;
154
- }
155
- const targetDecl = attr.$container;
156
- if (decl.name === '@@@targetField' && !(0, ast_1.isAttribute)(targetDecl)) {
157
- accept('error', `attribute "${decl.name}" can only be used on attribute declarations`, { node: attr });
158
- return;
159
- }
160
- if ((0, ast_1.isDataModelField)(targetDecl) && !isValidAttributeTarget(decl, targetDecl)) {
161
- accept('error', `attribute "${decl.name}" cannot be used on this type of field`, { node: attr });
162
- }
163
- const filledParams = new Set();
164
- for (const arg of attr.args) {
165
- let paramDecl;
166
- if (!arg.name) {
167
- paramDecl = decl.params.find((p) => p.default && !filledParams.has(p));
168
- if (!paramDecl) {
169
- accept('error', `Unexpected unnamed argument`, {
170
- node: arg,
171
- });
172
- return false;
173
- }
174
- }
175
- else {
176
- paramDecl = decl.params.find((p) => p.name === arg.name);
177
- if (!paramDecl) {
178
- accept('error', `Attribute "${decl.name}" doesn't have a parameter named "${arg.name}"`, {
179
- node: arg,
180
- });
181
- return false;
182
- }
183
- }
184
- if (!assignableToAttributeParam(arg, paramDecl, attr)) {
185
- accept('error', `Value is not assignable to parameter`, {
186
- node: arg,
187
- });
188
- return false;
189
- }
190
- if (filledParams.has(paramDecl)) {
191
- accept('error', `Parameter "${paramDecl.name}" is already provided`, { node: arg });
192
- return false;
193
- }
194
- filledParams.add(paramDecl);
195
- arg.$resolvedParam = paramDecl;
196
- }
197
- const missingParams = decl.params.filter((p) => !p.type.optional && !filledParams.has(p));
198
- if (missingParams.length > 0) {
199
- accept('error', `Required ${(0, pluralize_1.default)('parameter', missingParams.length)} not provided: ${missingParams
200
- .map((p) => p.name)
201
- .join(', ')}`, { node: attr });
202
- return false;
203
- }
204
- return true;
205
- }
206
- exports.validateAttributeApplication = validateAttributeApplication;
207
- function isValidAttributeTarget(attrDecl, targetDecl) {
208
- var _a;
209
- const targetField = attrDecl.attributes.find((attr) => { var _a; return ((_a = attr.decl.ref) === null || _a === void 0 ? void 0 : _a.name) === '@@@targetField'; });
210
- if (!targetField) {
211
- // no field type constraint
212
- return true;
213
- }
214
- const fieldTypes = targetField.args[0].value.items.map((item) => { var _a; return (_a = item.target.ref) === null || _a === void 0 ? void 0 : _a.name; });
215
- let allowed = false;
216
- for (const allowedType of fieldTypes) {
217
- switch (allowedType) {
218
- case 'StringField':
219
- allowed = allowed || targetDecl.type.type === 'String';
220
- break;
221
- case 'IntField':
222
- allowed = allowed || targetDecl.type.type === 'Int';
223
- break;
224
- case 'BigIntField':
225
- allowed = allowed || targetDecl.type.type === 'BigInt';
226
- break;
227
- case 'FloatField':
228
- allowed = allowed || targetDecl.type.type === 'Float';
229
- break;
230
- case 'DecimalField':
231
- allowed = allowed || targetDecl.type.type === 'Decimal';
232
- break;
233
- case 'BooleanField':
234
- allowed = allowed || targetDecl.type.type === 'Boolean';
235
- break;
236
- case 'DateTimeField':
237
- allowed = allowed || targetDecl.type.type === 'DateTime';
238
- break;
239
- case 'JsonField':
240
- allowed = allowed || targetDecl.type.type === 'Json';
241
- break;
242
- case 'BytesField':
243
- allowed = allowed || targetDecl.type.type === 'Bytes';
244
- break;
245
- case 'ModelField':
246
- allowed = allowed || (0, ast_1.isDataModel)((_a = targetDecl.type.reference) === null || _a === void 0 ? void 0 : _a.ref);
247
- break;
248
- default:
249
- break;
250
- }
251
- if (allowed) {
252
- break;
253
- }
254
- }
255
- return allowed;
256
- }
257
154
  //# sourceMappingURL=utils.js.map