@sap/cds-compiler 3.9.2 → 4.0.0

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 (96) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/README.md +0 -1
  3. package/bin/cdsc.js +11 -23
  4. package/bin/cdsse.js +3 -3
  5. package/doc/API.md +5 -0
  6. package/doc/CHANGELOG_ARCHIVE.md +1 -1
  7. package/doc/CHANGELOG_BETA.md +17 -1
  8. package/doc/CHANGELOG_DEPRECATED.md +28 -0
  9. package/lib/api/.eslintrc.json +1 -1
  10. package/lib/api/main.js +26 -8
  11. package/lib/api/options.js +2 -0
  12. package/lib/base/error.js +2 -0
  13. package/lib/base/message-registry.js +144 -65
  14. package/lib/base/messages.js +213 -107
  15. package/lib/base/model.js +11 -11
  16. package/lib/checks/.eslintrc.json +1 -1
  17. package/lib/checks/annotationsOData.js +2 -2
  18. package/lib/checks/elements.js +1 -1
  19. package/lib/checks/enricher.js +26 -3
  20. package/lib/checks/onConditions.js +67 -12
  21. package/lib/checks/queryNoDbArtifacts.js +106 -105
  22. package/lib/checks/sql-snippets.js +2 -0
  23. package/lib/checks/types.js +12 -6
  24. package/lib/checks/validator.js +2 -2
  25. package/lib/compiler/assert-consistency.js +10 -8
  26. package/lib/compiler/builtins.js +8 -2
  27. package/lib/compiler/checks.js +52 -35
  28. package/lib/compiler/define.js +31 -26
  29. package/lib/compiler/extend.js +120 -65
  30. package/lib/compiler/finalize-parse-cdl.js +12 -43
  31. package/lib/compiler/generate.js +16 -5
  32. package/lib/compiler/index.js +8 -5
  33. package/lib/compiler/kick-start.js +4 -3
  34. package/lib/compiler/populate.js +96 -95
  35. package/lib/compiler/propagator.js +7 -8
  36. package/lib/compiler/resolve.js +377 -103
  37. package/lib/compiler/shared.js +794 -517
  38. package/lib/compiler/tweak-assocs.js +8 -6
  39. package/lib/compiler/utils.js +44 -0
  40. package/lib/edm/annotations/genericTranslation.js +24 -6
  41. package/lib/edm/csn2edm.js +47 -45
  42. package/lib/edm/edm.js +34 -31
  43. package/lib/edm/edmAnnoPreprocessor.js +0 -23
  44. package/lib/edm/edmInboundChecks.js +7 -2
  45. package/lib/edm/edmPreprocessor.js +18 -17
  46. package/lib/edm/edmUtils.js +8 -4
  47. package/lib/gen/Dictionary.json +18 -0
  48. package/lib/gen/language.checksum +1 -1
  49. package/lib/gen/language.interp +4 -2
  50. package/lib/gen/languageParser.js +5006 -4582
  51. package/lib/json/from-csn.js +159 -114
  52. package/lib/json/to-csn.js +60 -89
  53. package/lib/language/antlrParser.js +17 -13
  54. package/lib/language/docCommentParser.js +11 -1
  55. package/lib/language/genericAntlrParser.js +13 -10
  56. package/lib/language/language.g4 +168 -97
  57. package/lib/main.d.ts +128 -36
  58. package/lib/main.js +1 -1
  59. package/lib/model/csnRefs.js +24 -5
  60. package/lib/model/csnUtils.js +9 -8
  61. package/lib/model/revealInternalProperties.js +7 -12
  62. package/lib/modelCompare/compare.js +1 -1
  63. package/lib/modelCompare/utils/filter.js +40 -2
  64. package/lib/optionProcessor.js +0 -3
  65. package/lib/render/toCdl.js +247 -214
  66. package/lib/render/toHdbcds.js +197 -181
  67. package/lib/render/toSql.js +325 -289
  68. package/lib/render/utils/common.js +42 -4
  69. package/lib/render/utils/delta.js +1 -1
  70. package/lib/render/utils/sql.js +3 -3
  71. package/lib/transform/braceExpression.js +2 -2
  72. package/lib/transform/db/.eslintrc.json +1 -1
  73. package/lib/transform/db/applyTransformations.js +3 -3
  74. package/lib/transform/db/associations.js +24 -12
  75. package/lib/transform/db/expansion.js +17 -18
  76. package/lib/transform/db/flattening.js +17 -21
  77. package/lib/transform/db/rewriteCalculatedElements.js +171 -64
  78. package/lib/transform/db/views.js +3 -4
  79. package/lib/transform/draft/db.js +21 -12
  80. package/lib/transform/draft/odata.js +4 -0
  81. package/lib/transform/forOdataNew.js +11 -10
  82. package/lib/transform/forRelationalDB.js +12 -7
  83. package/lib/transform/localized.js +5 -3
  84. package/lib/transform/odata/toFinalBaseType.js +5 -5
  85. package/lib/transform/odata/typesExposure.js +3 -3
  86. package/lib/transform/parseExpr.js +3 -0
  87. package/lib/transform/transformUtilsNew.js +43 -23
  88. package/lib/transform/translateAssocsToJoins.js +7 -6
  89. package/lib/transform/universalCsn/.eslintrc.json +1 -1
  90. package/lib/transform/universalCsn/coreComputed.js +7 -5
  91. package/lib/transform/universalCsn/universalCsnEnricher.js +12 -12
  92. package/lib/utils/file.js +3 -3
  93. package/lib/utils/moduleResolve.js +1 -1
  94. package/package.json +2 -2
  95. package/share/messages/{duplicate-autoexposed.md → def-duplicate-autoexposed.md} +5 -1
  96. package/share/messages/message-explanations.json +1 -1
@@ -11,72 +11,97 @@
11
11
  * Overview of properties in schema specifications (values in 'schema' dictionary):
12
12
  *
13
13
  * @typedef {object} SchemaSpec
14
- * @property {TransformerFunction} [type] Transformation and test function (i.e. type). The first
15
- * four arguments are the same for all functions. Further
16
- * ones may be accepted as well.
17
- * @property {string} [class] A schemaClass. Possible values are keys of the variable
18
- * "schemaClasses". Essentially all properties of the class
19
- * are copied.
20
- * @property {Function} [arrayOf] Alternative to "type". The property should be an array.
21
- * Value is passed to arrayOf().
22
- * Value is ignored if "type" is set. Then it is only used
23
- * for better error messages.
24
- * @property {Function} [dictionaryOf] Alternative to "type". The property should be an object
25
- * in dictionary form (i.e. Object.<string, type>).
26
- * Value is passed to dictionaryOf().
27
- * Value is ignored if "type" is set. Then it is only used
28
- * for better error messages.
29
- * @property {Object.<string, SchemaSpec>} [schema] If some sub-properties have a different
30
- * semantic in this property than the default then
31
- * switch the currently used spec to this value.
32
- * @property {string} [prop] Name of the property. compileSchema() sets it to the
33
- * dictionary key by default.
34
- * @property {string} [msgProp] Display name of the property. compileSchema() sets it to
35
- * the dictionary key (+ optional '[]') by default.
36
- * @property {string} [msgVariant] Use this message variant instead of the default one.
37
- * Allows more precise and detailed error messages.
38
- * @property {string|string[]|false} [requires] If the value is a string, then the given sub-
39
- * property is required. If 'undefined', then at
40
- * least one property is required. If false the no
41
- * sub-properties are required.
42
- * @property {boolean} [noPrefix] Only used for '#' at the moment. Signals that the entry
43
- * should not be used for keys like '#key'. getSchema(...)
44
- * normally checks if schema[prop] exists and if not,
45
- * checks for schema[prop.charAt(0)]. This is intended for
46
- * annotations and similar (which start with special
47
- * characters).
48
- * @property {boolean} [ignore] Don't issue warnings.
49
- * @property {string[]} [optional] Optional sub-properties that may be used. Warnings are
50
- * issued if unknown properties are set.
51
- * @property {string} [defaultKind] Default kind for sub-elements, e.g. objects in
52
- * "elements".
53
- * @property {string[]|Function} [inKind] Specifies in what definition type this property may
54
- * be used, e.g. "virtual" may only be used for elements.
55
- * If it is a function then it takes two arguments "kind"
56
- * and "parentSpec" should return a boolean
57
- * @property {string[]} [validKinds] What "kind" values are possible in a definition. The
58
- * root "definitions" properties allows more kinds than
59
- * e.g. definitions inside "elements".
60
- * @property {string|string[]} [onlyWith] Defines that the property *must* be used with these
61
- * properties.
62
- * @property {number} [minLength] Minimum number of elements that an array must have.
63
- * @property {boolean} [inValue] Puts the value into an XSN property "value",
64
- * e.g. { value: ... }
65
- * @property {string[]} [xorGroups] Corresponding xor groups. It references a value of
66
- * xorGroups. If set then only one property of the
67
- * xorGroup may be set, e.g. if target is set, elements
68
- * may not.
69
- * @property {string} [xsnOp] Defines the operator to be used for XSN. Used for SET
70
- * and SELECT. See queryTerm().
71
- * @property {string} [vZeroFor] Marks the property as a CSN 0.1.0 property. It is
72
- * replaced by this CSN 1.0 property (value of vZeroFor).
73
- * @property {string} [vZeroIgnore] Marks the property as a CSN 0.1.0 property. The
74
- * property is ignored and a warning may be issues about
75
- * it.
76
- * @property {string} [xorException] A property name that is allowed besides another property
77
- * of an xorGroup (as an exception to the rule).
78
- * @property {boolean} [ignoreExtra] Whether extra properties are ignored and not put
79
- * into $extra.
14
+ *
15
+ * @property {TransformerFunction} [type]
16
+ * Transformation and test function (i.e. type). The first four arguments are the same for
17
+ * all functions. Further ones may be accepted as well.
18
+ *
19
+ * @property {string} [class]
20
+ * A schemaClass. Possible values are keys of the variable "schemaClasses".
21
+ * Essentially all properties of the class are copied.
22
+ *
23
+ * @property {Function} [arrayOf]
24
+ * Alternative to "type". The property should be an array. Value is passed to arrayOf().
25
+ * Value is ignored if "type" is set. Then it is only used for better error messages.
26
+ *
27
+ * @property {Function} [dictionaryOf]
28
+ * Alternative to "type". The property should be an object in dictionary form (i.e.
29
+ * Object.<string, type>). Value is passed to dictionaryOf(). Value is ignored if "type"
30
+ * is set. Then it is only used for better error messages.
31
+ *
32
+ * @property {Object.<string, SchemaSpec>} [schema]
33
+ * If some sub-properties have a different semantic in this property than the default then
34
+ * switch the currently used spec to this value.
35
+ *
36
+ * @property {string} [prop]
37
+ * Name of the property. compileSchema() sets it to the dictionary key by default.
38
+ *
39
+ * @property {string} [msgProp]
40
+ * Display name of the property. compileSchema() sets it to the dictionary key
41
+ * (+ optional '[]') by default.
42
+ *
43
+ * @property {string} [msgVariant]
44
+ * Use this message variant instead of the default one.
45
+ * Allows more precise and detailed error messages.
46
+ *
47
+ * @property {string|string[]|false} [requires]
48
+ * If the value is a string, then the given sub-property is required. If 'undefined', then at
49
+ * least one property is required. If false the no sub-properties are required.
50
+ *
51
+ * @property {boolean} [noPrefix]
52
+ * Only used for '#' at the moment. Signals that the entry should not be used for keys
53
+ * like '#key'. `getSchema(...)` normally checks if `schema[prop]` exists and if not, checks
54
+ * for `schema[prop.charAt(0)]`.
55
+ * This is intended for annotations and similar (which start with special characters).
56
+ *
57
+ * @property {boolean} [ignore]
58
+ * Don't issue warnings.
59
+ *
60
+ * @property {string[]} [optional]
61
+ * Optional sub-properties that may be used. Warnings are issued if unknown properties are set.
62
+ *
63
+ * @property {string} [defaultKind]
64
+ * Default kind for sub-elements, e.g. objects in "elements".
65
+ *
66
+ * @property {string[]|Function} [inKind]
67
+ * Specifies in what definition type this property may be used, e.g. "virtual" may only be
68
+ * used for elements. If it is a function then it takes two arguments "kind" and "parentSpec"
69
+ * should return a boolean.
70
+ *
71
+ * @property {string[]} [validKinds]
72
+ * What "kind" values are possible in a definition. The root "definitions" properties allows
73
+ * more kinds than e.g. definitions inside "elements".
74
+ *
75
+ * @property {string|string[]} [onlyWith]
76
+ * Defines that the property *must* be used with these properties.
77
+ *
78
+ * @property {number} [minLength]
79
+ * Minimum number of elements that an array must have.
80
+ *
81
+ * @property {boolean} [inValue]
82
+ * Puts the value into an XSN property "value", e.g. { value: ... }
83
+ *
84
+ * @property {string[]} [xorGroups]
85
+ * Corresponding xor groups. It references a value of xorGroups. If set then only one property
86
+ * of the xorGroup may be set, e.g. if target is set, elements may not.
87
+ *
88
+ * @property {string} [xsnOp]
89
+ * Defines the operator to be used for XSN. Used for SET and SELECT. See queryTerm().
90
+ *
91
+ * @property {string} [vZeroFor]
92
+ * Marks the property as a CSN 0.1.0 property. It is replaced by this CSN 1.0
93
+ * property (value of vZeroFor).
94
+ *
95
+ * @property {string} [vZeroIgnore]
96
+ * Marks the property as a CSN 0.1.0 property. The property is ignored and a warning may be
97
+ * issues about it.
98
+ *
99
+ * @property {string} [xorException]
100
+ * A property name that is allowed besides another property of an xorGroup (as an exception
101
+ * to the rule).
102
+ *
103
+ * @property {boolean} [ignoreExtra]
104
+ * Whether extra properties are ignored and not put into $extra.
80
105
  */
81
106
 
82
107
  /**
@@ -92,7 +117,6 @@
92
117
  const { dictAdd } = require('../base/dictionaries');
93
118
  const { quotedLiteralPatterns } = require('../compiler/builtins');
94
119
  const { CompilerAssertion } = require('../base/error');
95
- const { isBetaEnabled } = require('../base/model');
96
120
 
97
121
  const $location = Symbol.for('cds.$location');
98
122
 
@@ -114,7 +138,7 @@ const typeProperties = [
114
138
  const exprProperties = [
115
139
  // do not include CSN v0.1.0 properties here:
116
140
  'ref', 'xpr', 'list', 'val', '#', 'func', 'SELECT', 'SET', // Core Compiler checks SELECT/SET
117
- 'param', 'global', 'literal', 'args', 'cast', // only with 'ref'/'ref'/'val'/'func'
141
+ 'param', 'literal', 'args', 'cast', // only with 'ref'/'ref'/'val'/'func'
118
142
  ];
119
143
 
120
144
  // Groups of properties which cannot be used together:
@@ -128,9 +152,16 @@ const xorGroups = {
128
152
  ':col': [ 'expand', 'inline' ],
129
153
  ':ext': [ 'annotate', 'extend' ], // TODO: better msg for test/negative/UnexpectedProperties.csn
130
154
  ':assoc': [ 'on', 'keys', 'foreignKeys', 'onCond' ], // 'foreignKeys'/'onCond' is CSN v0.1.0
155
+
156
+ // TODO: Maybe use a field "notWith", similar to "onlyWith" on `elements`/`items`?
157
+ ':length': [ 'elements', 'items', 'length' ],
158
+ ':srid': [ 'elements', 'items', 'srid' ],
159
+ ':precision': [ 'elements', 'items', 'precision' ],
160
+ ':scale': [ 'elements', 'items', 'scale' ],
161
+
131
162
  // TODO - improve consequential errors: assume no name given with `join` or `inline`?
132
163
  as: [ 'as', 'join', 'inline' ],
133
- scope: [ 'param', 'global' ],
164
+ scope: [ 'param' ],
134
165
  quantifier: [ 'some', 'any', 'distinct', 'all' ],
135
166
  // quantifiers 'some' and 'any are 'xpr' token strings in CSN v1.0
136
167
  };
@@ -249,7 +280,7 @@ const schema = compileSchema( {
249
280
  inKind: [ 'event' ],
250
281
  },
251
282
  actions: {
252
- dictionaryOf: definition,
283
+ dictionaryOf: actions,
253
284
  defaultKind: 'action',
254
285
  validKinds: [ 'action', 'function' ],
255
286
  inKind: [ 'entity', 'aspect', 'annotate', 'extend' ],
@@ -318,7 +349,7 @@ const schema = compileSchema( {
318
349
  type: {
319
350
  type: typeArtifactRef,
320
351
  msgVariant: 'or-object', // for 'syntax-expecting-string',
321
- optional: [ 'ref', 'global' ],
352
+ optional: [ 'ref' ],
322
353
  inKind: [ 'element', 'type', 'param', 'mixin', 'event', 'annotation', 'extend' ],
323
354
  schema: {
324
355
  ref: {
@@ -410,7 +441,11 @@ const schema = compileSchema( {
410
441
  msgVariant: 'or-object', // for 'syntax-expecting-string',
411
442
  minLength: 1,
412
443
  requires: 'id',
413
- optional: [ 'id', 'args', 'cardinality', 'where' ],
444
+ optional: [
445
+ 'id', 'args', 'cardinality', 'where',
446
+ // Support once we allow them in non-parse-only CDL.
447
+ // 'groupBy', 'having', 'orderBy', 'limit',
448
+ ],
414
449
  xorException: 'expand', // see xorGroup :expr
415
450
  inKind: [ '$column', 'key' ],
416
451
  },
@@ -422,11 +457,6 @@ const schema = compileSchema( {
422
457
  onlyWith: 'ref',
423
458
  inKind: [ '$column' ],
424
459
  },
425
- global: {
426
- type: asScope, // is bool, stored as string in XSN property 'scope'
427
- onlyWith: 'ref',
428
- inKind: [ '$column' ],
429
- },
430
460
  func: {
431
461
  type: func,
432
462
  xorException: 'xpr', // see xorGroup :expr
@@ -535,7 +565,7 @@ const schema = compileSchema( {
535
565
  },
536
566
  inKind: [ '$column' ],
537
567
  },
538
- op: { // used for UNION etc in CSN v1.0
568
+ op: { // used for UNION etc. in CSN v1.0
539
569
  vZeroFor: 'xpr',
540
570
  vZeroIgnore: 'call', // is also used in CSN v0.1.0 for "normal" expressions
541
571
  type: setOp,
@@ -545,8 +575,8 @@ const schema = compileSchema( {
545
575
  type: join, // string like 'cross' - TODO: test for valid ones?
546
576
  },
547
577
  from: {
548
- type: object,
549
- optional: [ 'ref', 'global', 'join', 'cardinality', 'args', 'on', 'SELECT', 'SET', 'as' ],
578
+ type: fromObject,
579
+ optional: [ 'ref', 'join', 'cardinality', 'args', 'on', 'SELECT', 'SET', 'as' ],
550
580
  schema: {
551
581
  cardinality: {
552
582
  type: object,
@@ -554,9 +584,9 @@ const schema = compileSchema( {
554
584
  onlyWith: 'join',
555
585
  },
556
586
  args: {
557
- arrayOf: object,
587
+ arrayOf: fromObject,
558
588
  minLength: 2,
559
- optional: [ 'ref', 'global', 'join', 'cardinality', 'args', 'on', 'SELECT', 'SET', 'as' ],
589
+ optional: [ 'ref', 'join', 'cardinality', 'args', 'on', 'SELECT', 'SET', 'as' ],
560
590
  onlyWith: 'join',
561
591
  schema: {}, // 'args' in 'args' in 'from' is same as 'args' in 'from'
562
592
  },
@@ -698,7 +728,7 @@ const schema = compileSchema( {
698
728
  class: 'expression', // calculated elements
699
729
  vZeroFor: 'val', // CSN v0.1.0 property for `val` in enum def
700
730
  // type: annoValue,
701
- inKind: [ 'element' ],
731
+ inKind: [ 'element', 'enum' ], // TODO: Remove "enum" again; currently for extensions
702
732
  optional: exprProperties.concat([ 'stored' ]),
703
733
  },
704
734
  stored: {
@@ -777,8 +807,6 @@ let virtualLine = 1;
777
807
  /** @type {CSN.Location[]} */
778
808
  let dollarLocations = [];
779
809
  let arrayLevelCount = 0;
780
- /** @type {CSN.Options} */
781
- let userOptions = null; // must be reset!
782
810
 
783
811
  /**
784
812
  * @param {Object.<string, SchemaSpec>} specs
@@ -935,7 +963,7 @@ function object( obj, spec ) {
935
963
 
936
964
  function vZeroDelete( o, spec ) { // for old-CSN property 'origin'
937
965
  if (!csnVersionZero) {
938
- warning( 'syntax-deprecated-property', location(true),
966
+ message( 'syntax-deprecated-property', location(true),
939
967
  { '#': 'zero', prop: spec.msgProp } );
940
968
  }
941
969
  ignore( o );
@@ -964,13 +992,15 @@ function definition( def, spec, xsn, csn, name ) {
964
992
 
965
993
  // If we have `extend … with { name = 3 }`, it could mean adding an element or an enum.
966
994
  // We use `elements: { name: { val: 3 } }` to represent this ambiguity.
967
- if (savedInExtensions === '' && prop === 'elements' && !def.value &&
968
- (def.val !== undefined || def['#'] !== undefined) &&
995
+ if (savedInExtensions === '' && prop === 'elements' &&
996
+ (def.val !== undefined || def['#'] !== undefined ||
997
+ def.value?.val !== undefined || def.value?.['#'] !== undefined) &&
969
998
  def.virtual === undefined && def.key === undefined && def.masked === undefined &&
970
999
  def.type === undefined && def.elements === undefined) {
971
1000
  r.$syntax = 'enum';
972
1001
  kind = 'enum'; // for function expected()
973
1002
  }
1003
+
974
1004
  if (csnProps.length) {
975
1005
  const valueName = (prop === 'keys' || prop === 'foreignKeys' ? 'targetElement' : 'value');
976
1006
  // the next is basically object() + the inValue handling
@@ -1024,6 +1054,20 @@ function definition( def, spec, xsn, csn, name ) {
1024
1054
  }
1025
1055
  }
1026
1056
 
1057
+ function actions( def, spec, xsn, csn, name ) {
1058
+ if (def.kind === 'extend' && (def.elements || def.enum)) {
1059
+ // TODO: Handle this case in extend.js; already done for `returns`
1060
+ // See message ext-expecting-returns
1061
+ error( 'syntax-unexpected-property', location(true), {
1062
+ '#': def.kind,
1063
+ prop: def.enum ? 'enum' : 'elements',
1064
+ parentprop: spec.msgProp,
1065
+ kind: def.kind,
1066
+ } );
1067
+ }
1068
+ return definition( def, spec, xsn, csn, name );
1069
+ }
1070
+
1027
1071
  // A dictionary is expected. Uses spec.dictionaryOf. If unset, default is "definition".
1028
1072
  function dictionaryOf( elementFct ) {
1029
1073
  return function dictionary( dict, spec ) {
@@ -1078,14 +1122,7 @@ function selectItem( def, spec, xsn, csn ) {
1078
1122
  }
1079
1123
 
1080
1124
  function returnsDefinition( def, spec, xsn, csn ) {
1081
- // TODO: be stricter in what is allowed inside returns
1082
- if (!inExtensions)
1083
- return definition( def, spec, xsn, csn, '' );
1084
- // for the moment, flatten elements in returns in an annotate
1085
- // TODO: bigger Core Compiler changes would have to be done otherwise
1086
- xsn.elements = definition( def, spec, xsn, csn, '' ).elements;
1087
- xsn.$syntax = 'returns';
1088
- return undefined;
1125
+ return definition( def, spec, xsn, csn, '' );
1089
1126
  }
1090
1127
 
1091
1128
  // For v1 CSNs with annotation definitions
@@ -1151,8 +1188,9 @@ function validKind( val, spec, xsn ) {
1151
1188
  if (val === xsn.kind) // has been set in definition - the same = ok!
1152
1189
  return undefined; // already set in definition
1153
1190
  if (val === 'view' && xsn.kind === 'entity') {
1154
- warning( 'syntax-deprecated-value', location(true),
1155
- { '#': 'replace', prop: spec.msgProp, value: 'entity' } );
1191
+ warning( 'syntax-deprecated-kind', location(true),
1192
+ { prop: spec.msgProp, value: 'entity' },
1193
+ 'Replace value in $(PROP) by $(VALUE)' );
1156
1194
  }
1157
1195
  else if (val !== 'entity' && val !== 'type' || xsn.kind !== 'aspect') {
1158
1196
  error( 'syntax-invalid-kind', location(true), { prop: spec.msgProp },
@@ -1169,13 +1207,22 @@ function typeArtifactRef( ref, spec ) {
1169
1207
  return artifactRef( ref, spec );
1170
1208
  }
1171
1209
 
1210
+ function fromObject( ref, spec ) {
1211
+ const r = object( ref, spec );
1212
+ if (r?.path?.length > 1)
1213
+ r.scope = 1; // `type`/`from` ref in CSN: elements start after definitions name
1214
+ return r;
1215
+ }
1216
+
1172
1217
  // Use with spec.msgVariant: 'or-object'
1173
1218
  function artifactRef( ref, spec ) {
1174
1219
  if (!ref || typeof ref !== 'string') {
1175
- if (ref && typeof ref === 'object' && !Array.isArray( ref ))
1176
- return object( ref, spec );
1220
+ if (!ref || typeof ref !== 'object' || Array.isArray( ref ))
1221
+ return string( ref, spec );
1177
1222
  // use error message 'syntax-expecting-string' (string more likely than object):
1178
- return string( ref, spec );
1223
+ return (!ref || typeof ref !== 'object' || Array.isArray( ref ))
1224
+ ? string( ref, spec )
1225
+ : fromObject( ref, spec );
1179
1226
  }
1180
1227
  if (spec.prop !== 'type')
1181
1228
  return stringRef( ref, spec );
@@ -1184,11 +1231,12 @@ function artifactRef( ref, spec ) {
1184
1231
  if (idx < 0)
1185
1232
  return stringRef( ref, spec );
1186
1233
  if (!csnVersionZero) {
1187
- warning( 'syntax-deprecated-value', location(true),
1234
+ message( 'syntax-deprecated-value', location(true),
1188
1235
  { '#': 'zero-replace', prop: spec.msgProp, value: '{ ref: […] }' } );
1189
1236
  }
1190
1237
  const r = refSplit( ref.substring( idx + 2 ), 'type' );
1191
1238
  r.path.unshift( { id: ref.substring( 0, idx ), location: location() } );
1239
+ r.scope = 1;
1192
1240
  return r;
1193
1241
  }
1194
1242
 
@@ -1375,8 +1423,6 @@ function annoValue( val, spec ) {
1375
1423
  // TODO: Have xprInAnnoProperties centrally for other backends to use as well (toCdl)
1376
1424
  const valKeys = Object.keys(val);
1377
1425
  if (valKeys.length > 1 &&
1378
- (isBetaEnabled(userOptions, 'annotationExpressions') ||
1379
- isBetaEnabled(userOptions, 'v4preview')) &&
1380
1426
  xprInAnnoProperties.some(prop => val[prop] !== undefined)) {
1381
1427
  const s = schema['@'].schema['-expr'];
1382
1428
  const r = { location: location() };
@@ -1400,7 +1446,7 @@ function annoValue( val, spec ) {
1400
1446
  return xsn;
1401
1447
  }
1402
1448
  }
1403
- else if (val['...'] && Object.keys( val ).length === 1) {
1449
+ else if (val['...'] !== undefined && Object.keys( val ).length === 1) {
1404
1450
  // TODO: only if not nested - see error above
1405
1451
  ++virtualLine;
1406
1452
  const ell = val['...'];
@@ -1598,6 +1644,7 @@ function exprArgs( cond, spec ) {
1598
1644
  // TODO: do that in definer.js, neither here nor in CDL parser
1599
1645
  if (Array.isArray( rxsn )) {
1600
1646
  for (let i = 0; i < rxsn.length - 1; i++) {
1647
+ // TODO: disallow param ref - write test
1601
1648
  if (rxsn[i]?.val === 'exists' && rxsn[i].literal === 'token' && rxsn[i + 1].path)
1602
1649
  rxsn[++i].$expected = 'exists';
1603
1650
  }
@@ -1680,8 +1727,8 @@ function join( val, spec, xsn ) {
1680
1727
 
1681
1728
  function queryArgs( val, spec, xsn, csn ) {
1682
1729
  if (Array.isArray( val ) && val.length > 1 && !csn.op) {
1683
- // Make it error 'syntax-missing-property#sibling' in v4:
1684
- warning( 'syntax-deprecated-auto-union', location(true),
1730
+ // Make it error 'syntax-missing-property#sibling' in v6:
1731
+ message( 'syntax-deprecated-auto-union', location(true),
1685
1732
  { siblingprop: 'args', prop: 'op' },
1686
1733
  'Object with property $(SIBLINGPROP) must also have a property $(PROP)' );
1687
1734
  xsn.op = { val: 'union', location: location() };
@@ -1726,7 +1773,7 @@ function getSpec( parentSpec, csn, prop, xor, expected, kind ) {
1726
1773
  if (s.ignore)
1727
1774
  return { type: ignore };
1728
1775
  if (s.vZeroIgnore && s.vZeroIgnore === csn[prop]) { // for "op": "call"
1729
- warning( 'syntax-deprecated-property', location(true), { '#': 'zero', prop } );
1776
+ message( 'syntax-deprecated-property', location(true), { '#': 'zero', prop } );
1730
1777
  return { type: ignore };
1731
1778
  }
1732
1779
  const zero = s.vZeroFor;
@@ -1851,7 +1898,7 @@ function implicitName( ref ) {
1851
1898
  function replaceZeroProp( prop, otherprop ) {
1852
1899
  if (csnVersionZero)
1853
1900
  return;
1854
- warning( 'syntax-deprecated-property', location(true),
1901
+ message( 'syntax-deprecated-property', location(true),
1855
1902
  { '#': 'zero-replace', prop, otherprop } );
1856
1903
  }
1857
1904
 
@@ -1881,10 +1928,10 @@ function refSplit( name, prop ) {
1881
1928
  return { path: path.map( id => ({ id, location: location() }) ), location: location() };
1882
1929
  }
1883
1930
 
1884
- function replaceZeroValue( spec, msgVariant, otherprop ) {
1931
+ function replaceZeroValue( spec, msgVariant, newValue ) {
1885
1932
  if (!csnVersionZero && !spec.vZeroFor) {
1886
- warning( 'syntax-deprecated-value', location(true),
1887
- { '#': msgVariant, prop: spec.msgProp, otherprop } );
1933
+ message( 'syntax-deprecated-value', location(true),
1934
+ { '#': msgVariant, prop: spec.msgProp, value: newValue } );
1888
1935
  }
1889
1936
  }
1890
1937
 
@@ -1939,7 +1986,6 @@ function popLocation( obj ) {
1939
1986
  function resetHeapModuleVars() {
1940
1987
  vocabInDefinitions = null;
1941
1988
  dollarLocations = [];
1942
- userOptions = null;
1943
1989
  message = () => undefined;
1944
1990
  error = () => undefined;
1945
1991
  warning = () => undefined;
@@ -1964,7 +2010,6 @@ function toXsn( csn, filename, options, messageFunctions ) {
1964
2010
  arrayLevelCount = 0;
1965
2011
  inExtensions = null;
1966
2012
  vocabInDefinitions = null;
1967
- userOptions = options;
1968
2013
 
1969
2014
  const xsn = { $frontend: 'json' };
1970
2015