@sap/cds-compiler 2.12.0 → 2.13.6

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 (118) hide show
  1. package/CHANGELOG.md +110 -15
  2. package/bin/cdsc.js +13 -13
  3. package/bin/cdsse.js +2 -2
  4. package/doc/CHANGELOG_BETA.md +13 -6
  5. package/doc/CHANGELOG_DEPRECATED.md +22 -6
  6. package/doc/NameResolution.md +21 -16
  7. package/lib/api/main.js +28 -63
  8. package/lib/api/options.js +3 -3
  9. package/lib/api/validate.js +0 -5
  10. package/lib/backends.js +15 -23
  11. package/lib/base/dictionaries.js +0 -8
  12. package/lib/base/error.js +26 -0
  13. package/lib/base/keywords.js +7 -17
  14. package/lib/base/location.js +9 -4
  15. package/lib/base/message-registry.js +25 -4
  16. package/lib/base/messages.js +16 -26
  17. package/lib/base/model.js +2 -63
  18. package/lib/base/optionProcessorHelper.js +158 -123
  19. package/lib/checks/annotationsOData.js +1 -1
  20. package/lib/checks/cdsPersistence.js +2 -1
  21. package/lib/checks/enricher.js +17 -1
  22. package/lib/checks/invalidTarget.js +3 -1
  23. package/lib/checks/managedWithoutKeys.js +3 -1
  24. package/lib/checks/selectItems.js +4 -4
  25. package/lib/checks/sql-snippets.js +27 -26
  26. package/lib/checks/types.js +1 -1
  27. package/lib/checks/validator.js +4 -7
  28. package/lib/compiler/assert-consistency.js +5 -3
  29. package/lib/compiler/builtins.js +8 -6
  30. package/lib/compiler/checks.js +14 -3
  31. package/lib/compiler/cycle-detector.js +1 -1
  32. package/lib/compiler/define.js +1103 -0
  33. package/lib/compiler/extend.js +983 -0
  34. package/lib/compiler/finalize-parse-cdl.js +231 -0
  35. package/lib/compiler/index.js +32 -13
  36. package/lib/compiler/kick-start.js +190 -0
  37. package/lib/compiler/moduleLayers.js +4 -4
  38. package/lib/compiler/populate.js +1226 -0
  39. package/lib/compiler/propagator.js +111 -46
  40. package/lib/compiler/resolve.js +1433 -0
  41. package/lib/compiler/shared.js +64 -37
  42. package/lib/compiler/tweak-assocs.js +529 -0
  43. package/lib/compiler/utils.js +197 -33
  44. package/lib/edm/.eslintrc.json +5 -0
  45. package/lib/edm/annotations/genericTranslation.js +5 -9
  46. package/lib/edm/annotations/preprocessAnnotations.js +2 -2
  47. package/lib/edm/csn2edm.js +9 -8
  48. package/lib/edm/edm.js +11 -12
  49. package/lib/edm/edmPreprocessor.js +137 -73
  50. package/lib/edm/edmUtils.js +116 -22
  51. package/lib/gen/Dictionary.json +10 -3
  52. package/lib/gen/language.checksum +1 -1
  53. package/lib/gen/language.interp +9 -1
  54. package/lib/gen/language.tokens +86 -83
  55. package/lib/gen/languageLexer.interp +10 -1
  56. package/lib/gen/languageLexer.js +860 -833
  57. package/lib/gen/languageLexer.tokens +78 -75
  58. package/lib/gen/languageParser.js +5282 -4265
  59. package/lib/json/from-csn.js +12 -1
  60. package/lib/json/to-csn.js +126 -66
  61. package/lib/language/docCommentParser.js +2 -2
  62. package/lib/language/genericAntlrParser.js +76 -3
  63. package/lib/language/language.g4 +297 -130
  64. package/lib/language/multiLineStringParser.js +5 -5
  65. package/lib/main.d.ts +468 -59
  66. package/lib/main.js +35 -9
  67. package/lib/model/api.js +3 -1
  68. package/lib/model/csnRefs.js +225 -156
  69. package/lib/model/csnUtils.js +192 -223
  70. package/lib/model/enrichCsn.js +70 -29
  71. package/lib/model/revealInternalProperties.js +27 -6
  72. package/lib/model/sortViews.js +2 -1
  73. package/lib/modelCompare/compare.js +17 -12
  74. package/lib/optionProcessor.js +5 -4
  75. package/lib/render/manageConstraints.js +35 -32
  76. package/lib/render/toCdl.js +73 -288
  77. package/lib/render/toHdbcds.js +25 -23
  78. package/lib/render/toSql.js +98 -41
  79. package/lib/render/utils/common.js +5 -10
  80. package/lib/render/utils/sql.js +4 -3
  81. package/lib/render/utils/stringEscapes.js +111 -0
  82. package/lib/sql-identifier.js +1 -1
  83. package/lib/transform/.eslintrc.json +5 -0
  84. package/lib/transform/db/.eslintrc.json +2 -0
  85. package/lib/transform/db/applyTransformations.js +35 -12
  86. package/lib/transform/db/assertUnique.js +1 -1
  87. package/lib/transform/db/associations.js +103 -305
  88. package/lib/transform/db/cdsPersistence.js +2 -2
  89. package/lib/transform/db/constraints.js +55 -52
  90. package/lib/transform/db/expansion.js +46 -24
  91. package/lib/transform/db/flattening.js +553 -102
  92. package/lib/transform/db/groupByOrderBy.js +3 -1
  93. package/lib/transform/db/transformExists.js +59 -6
  94. package/lib/transform/db/views.js +5 -4
  95. package/lib/transform/draft/.eslintrc.json +38 -0
  96. package/lib/transform/{db/draft.js → draft/db.js} +6 -5
  97. package/lib/transform/draft/odata.js +227 -0
  98. package/lib/transform/forHanaNew.js +67 -183
  99. package/lib/transform/forOdataNew.js +17 -171
  100. package/lib/transform/localized.js +34 -19
  101. package/lib/transform/odata/generateForeignKeyElements.js +1 -1
  102. package/lib/transform/odata/referenceFlattener.js +95 -89
  103. package/lib/transform/odata/structureFlattener.js +1 -1
  104. package/lib/transform/odata/toFinalBaseType.js +86 -12
  105. package/lib/transform/odata/typesExposure.js +5 -5
  106. package/lib/transform/odata/utils.js +2 -2
  107. package/lib/transform/transformUtilsNew.js +36 -22
  108. package/lib/transform/translateAssocsToJoins.js +2 -19
  109. package/lib/transform/universalCsn/.eslintrc.json +36 -0
  110. package/lib/transform/universalCsn/coreComputed.js +170 -0
  111. package/lib/transform/universalCsn/universalCsnEnricher.js +715 -0
  112. package/lib/transform/universalCsn/utils.js +63 -0
  113. package/lib/utils/objectUtils.js +30 -0
  114. package/package.json +1 -1
  115. package/share/messages/README.md +26 -0
  116. package/lib/compiler/definer.js +0 -2361
  117. package/lib/compiler/resolver.js +0 -3079
  118. package/lib/transform/universalCsnEnricher.js +0 -237
package/lib/backends.js CHANGED
@@ -279,7 +279,7 @@ function transformSQLOptions(model, options) {
279
279
 
280
280
  if(options.toSql.dialect !== 'hana') {
281
281
  // CDXCORE-465, 'quoted' and 'hdbcds' are to be used in combination with dialect 'hana' only
282
- if(['quoted', 'hdbcds'].includes(options.toSql.names)) {
282
+ if (options.toSql.names === 'quoted' || options.toSql.names === 'hdbcds') {
283
283
  error(null, null, `Option "{ toSql.dialect: '${options.toSql.dialect}' }" can't be combined with "{ toSql.names: '${options.toSql.names}' }"`);
284
284
  }
285
285
  // No non-HANA SQL for HDI
@@ -296,17 +296,17 @@ function transformSQLOptions(model, options) {
296
296
  // If among the options user, user.id or user.locale are specified via the CLI or
297
297
  // via the API, then ensure that at the end there is a user option, which is an object and has(have)
298
298
  // "id" and/or "locale" prop(s)
299
- function transformUserOption(options) {
299
+ function transformUserOption(userOptions) {
300
300
  // move the user option value under user.id if specified as a string
301
- if (options.user && typeof options.user === 'string' || options.user instanceof String) {
302
- options.user = { id: options.user };
301
+ if (userOptions.user && typeof userOptions.user === 'string' || userOptions.user instanceof String) {
302
+ userOptions.user = { id: userOptions.user };
303
303
  }
304
304
  // move the locale option(if provided) under user.locale
305
- if (options.locale) {
306
- options.user = options.user
307
- ? Object.assign(options.user, { locale: options.locale })
308
- : { locale: options.locale };
309
- delete options.locale;
305
+ if (userOptions.locale) {
306
+ userOptions.user = userOptions.user
307
+ ? Object.assign(userOptions.user, { locale: userOptions.locale })
308
+ : { locale: userOptions.locale };
309
+ delete userOptions.locale;
310
310
  }
311
311
  }
312
312
  }
@@ -389,7 +389,7 @@ function toRenameWithCsn(csn, options) {
389
389
  let forHanaCsn = transformForHanaWithCsn(csn, mergeOptions(options, { forHana : options.toRename } ), 'to.rename');
390
390
  // forHanaCsn looses empty contexts and services, add them again so that toRename can calculate the namespaces
391
391
  forEachDefinition(csn, (artifact, artifactName) => {
392
- if(['context', 'service'].includes(artifact.kind) && forHanaCsn.definitions[artifactName] === undefined) {
392
+ if((artifact.kind === 'context' || artifact.kind === 'service') && forHanaCsn.definitions[artifactName] === undefined) {
393
393
  forHanaCsn.definitions[artifactName] = artifact;
394
394
  }
395
395
  });
@@ -416,6 +416,10 @@ function alterConstraintsWithCsn(csn, options) {
416
416
  names: names || 'plain'
417
417
  }
418
418
 
419
+ // Also set new-style options
420
+ options.sqlDialect = 'hana';
421
+ options.sqlMapping = names || 'plain';
422
+
419
423
  // Of course we want the database constraints
420
424
  options.assertIntegrityType = 'DB';
421
425
 
@@ -432,19 +436,7 @@ function alterConstraintsWithCsn(csn, options) {
432
436
  else
433
437
  intermediateResult = manageConstraints(forSqlCsn, mergedOptions);
434
438
 
435
- if(options.testMode !== true)
436
- return intermediateResult;
437
-
438
- // if in testmode, return a string containing all the artifacts
439
- let resultString = '';
440
- const extension = src && src === 'hdi' ? 'hdbconstraint' : 'sql';
441
- for(const id in intermediateResult){
442
- const initialComment = `--$ --- ${id}.${extension} ---\n\n`;
443
- resultString += initialComment;
444
- resultString += intermediateResult[id];
445
- resultString += '\n\n'
446
- }
447
- return resultString;
439
+ return intermediateResult;
448
440
  }
449
441
 
450
442
  // ----------- toCsn -----------
@@ -89,17 +89,9 @@ function pushToDict( dict, name, entry ) {
89
89
  dict[name] = [entry];
90
90
  }
91
91
 
92
- function forEachInDict( dict, callback ) {
93
- let r = Object.create(null);
94
- for (let name of Object.keys(dict))
95
- r[name] = callback( dict[name], name, dict );
96
- return r;
97
- }
98
-
99
92
  module.exports = {
100
93
  dictAdd, dictForEach,
101
94
  dictAddArray,
102
95
  pushToDict,
103
- forEachInDict,
104
96
  }
105
97
 
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Use this class to indicate that an internal error was noticed.
5
+ * In testMode, these errors do _not_ trigger a recompilation.
6
+ */
7
+ class CompilerAssertion extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ }
11
+ }
12
+
13
+ /**
14
+ * Use this class to indicate that something with the input CSN is wrong,
15
+ * which will be caught by the core compiler through recompiling the sources.
16
+ */
17
+ class ModelError extends Error {
18
+ constructor(message) {
19
+ super(message);
20
+ }
21
+ }
22
+
23
+ module.exports = {
24
+ CompilerAssertion,
25
+ ModelError,
26
+ };
@@ -1,3 +1,7 @@
1
+ 'use strict';
2
+
3
+ const { functionsWithoutParens } = require("../compiler/builtins");
4
+
1
5
  module.exports = {
2
6
  // CDL reserved keywords, used for automatic quoting in 'toCdl' renderer
3
7
  // Keep in sync with reserved keywords in language.g4
@@ -30,21 +34,7 @@ module.exports = {
30
34
  ],
31
35
  // CDL functions, used for automatic quoting in 'toCdl' renderer,
32
36
  // only relevant for element references of path length 1.
33
- cdl_functions: [
34
- 'CURRENT_CONNECTION',
35
- 'CURRENT_DATE',
36
- 'CURRENT_SCHEMA',
37
- 'CURRENT_TIME',
38
- 'CURRENT_TIMESTAMP',
39
- 'CURRENT_TRANSACTION_ISOLATION_LEVEL',
40
- 'CURRENT_USER',
41
- 'CURRENT_UTCDATE',
42
- 'CURRENT_UTCTIME',
43
- 'CURRENT_UTCTIMESTAMP',
44
- 'SESSION_USER',
45
- 'SYSTEM_USER',
46
- 'SYSUUID',
47
- ],
37
+ cdl_functions: functionsWithoutParens,
48
38
  // SQLite keywords, used to warn in 'toSql' renderer with dialect 'sqlite'
49
39
  // Taken from http://www.sqlite.org/draft/lang_keywords.html
50
40
  // Better use keywords in tool/mkkeywordhash.c of a sqlite distribution.
@@ -195,7 +185,7 @@ module.exports = {
195
185
  'OTHERS',
196
186
  'TIES',
197
187
  ],
198
- // HANA keywords, used for smart quoting in to-hdi.plain
188
+ // SAP HANA keywords, used for smart quoting in to-hdi.plain
199
189
  // Taken from https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/28bcd6af3eb6437892719f7c27a8a285.html
200
190
  // Better use keywords in ptime/query/parser/syntax/qp_keyword.cc minus those
201
191
  // in rule unreserved_keyword_column (=…_common - "CONSTRAINT") in
@@ -675,7 +665,7 @@ module.exports = {
675
665
  'XMLTABLE',
676
666
  'YEAR'
677
667
  ],
678
- // HANA CDS keywords, used for smart quoting in to-hdbcds.plain
668
+ // SAP HANA CDS keywords, used for smart quoting in to-hdbcds.plain
679
669
  hdbcds: [
680
670
  'ALL', 'ALTER', 'AS',
681
671
  'BEFORE', 'BEGIN', 'BOTH',
@@ -12,6 +12,9 @@ const { copyPropIfExist } = require('../utils/objectUtils');
12
12
  * @param {XSN.WithLocation} start
13
13
  * @param {XSN.WithLocation} end
14
14
  * @returns {CSN.Location}
15
+ *
16
+ * TODO: make this function a CDL parser-only function (i.e. there should be
17
+ * no need to use it outside), it is XSN-only anyway already now
15
18
  */
16
19
  function combinedLocation( start, end ) {
17
20
  if (!start || !start.location)
@@ -33,6 +36,8 @@ function combinedLocation( start, end ) {
33
36
  *
34
37
  * @param {string} filename
35
38
  * @returns {CSN.Location}
39
+ *
40
+ * TODO: make this function redundant (XSN sparse locations project)
36
41
  */
37
42
  function emptyLocation(filename) {
38
43
  return {
@@ -50,6 +55,8 @@ function emptyLocation(filename) {
50
55
  *
51
56
  * @param {string} filename
52
57
  * @returns {CSN.Location}
58
+ *
59
+ * TODO: make this function redundant (XSN sparse locations project)
53
60
  */
54
61
  function emptyWeakLocation(filename) {
55
62
  return {
@@ -63,6 +70,8 @@ function emptyWeakLocation(filename) {
63
70
  * Returns a dummy location for built-in definitions.
64
71
  *
65
72
  * @returns {CSN.Location}
73
+ *
74
+ * TODO: make this function redundant (XSN sparse locations project)
66
75
  */
67
76
  function builtinLocation() {
68
77
  return emptyLocation('<built-in>');
@@ -140,10 +149,6 @@ function dictLocation( dict, extraLocation ) {
140
149
  endCol: max.endCol,
141
150
  };
142
151
  }
143
- dictLocation.end = (dict) => {
144
- const loc = dictLocation( dict );
145
- return loc && { file: loc.file, line: loc.endLine, col: loc.endCol };
146
- };
147
152
 
148
153
  function _objLocations( obj ) {
149
154
  return Array.isArray(obj) ? obj.map( o => o.location ) : [ obj.location ];
@@ -42,15 +42,17 @@ const centralMessages = {
42
42
  'anno-definition': { severity: 'Warning' },
43
43
  'anno-duplicate': { severity: 'Error', configurableFor: true }, // does not hurt us
44
44
  'anno-duplicate-unrelated-layer': { severity: 'Error', configurableFor: true }, // does not hurt us
45
- 'anno-invalid-sql-element': { severity: 'Error'}, // @sql.prepend/append
46
- 'anno-invalid-sql-struct': { severity: 'Error'}, // @sql.prepend/append
47
- 'anno-invalid-sql-view': { severity: 'Error' }, // @sql.prepend/append
48
- 'anno-invalid-sql-view-element': { severity: 'Error'}, // @sql.prepend/append
45
+ 'anno-invalid-sql-element': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
46
+ 'anno-invalid-sql-struct': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
47
+ 'anno-invalid-sql-kind': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
48
+ 'anno-invalid-sql-view': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
49
+ 'anno-invalid-sql-view-element': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
49
50
  'anno-undefined-action': { severity: 'Info' },
50
51
  'anno-undefined-art': { severity: 'Info' }, // for annotate statement (for CDL path root)
51
52
  'anno-undefined-def': { severity: 'Info' }, // for annotate statement (for CSN or CDL path cont)
52
53
  'anno-undefined-element': { severity: 'Info' },
53
54
  'anno-undefined-param': { severity: 'Info' },
55
+ 'anno-unexpected-ellipsis-layers': { severity: 'Error', configurableFor: true }, // TODO(v3): Merge with anno-unexpected-ellipsis and make non-configurable
54
56
 
55
57
  'args-expected-named': { severity: 'Error', configurableFor: 'deprecated' }, // future --sloppy
56
58
  'args-no-params': { severity: 'Error', configurableFor: 'deprecated' }, // future --sloppy
@@ -58,6 +60,8 @@ const centralMessages = {
58
60
 
59
61
  'assoc-in-array': { severity: 'Error', configurableFor: 'deprecated' }, // not supported yet
60
62
  'assoc-as-type': { severity: 'Error', configurableFor: 'deprecated' }, // TODO: allow more, but not all
63
+ 'def-unexpected-paramview-assoc': { severity: 'Error' },
64
+ 'def-unexpected-calcview-assoc': { severity: 'Error' },
61
65
 
62
66
  'check-proper-type': { severity: 'Error', configurableFor: [ 'compile' ] },
63
67
  'check-proper-type-of': { severity: 'Info', errorFor: [ 'for.odata', 'to.edmx', 'to.hdbcds', 'to.sql', 'to.rename' ] },
@@ -131,6 +135,8 @@ const centralMessages = {
131
135
  'syntax-fragile-alias': { severity: 'Error', configurableFor: true },
132
136
  'syntax-fragile-ident': { severity: 'Error', configurableFor: true },
133
137
 
138
+ 'syntax-invalid-extend': { severity: 'Error' },
139
+
134
140
  'syntax-invalid-text-block' : { severity: 'Error' },
135
141
  'syntax-unknown-escape': { severity: 'Error', configurableFor: true },
136
142
  'syntax-invalid-escape': { severity: 'Error' },
@@ -156,8 +162,10 @@ const centralMessages = {
156
162
 
157
163
  // For messageIds, where no text has been provided via code (central def)
158
164
  const centralMessageTexts = {
165
+ 'anno-duplicate': 'Duplicate assignment with $(ANNO)',
159
166
  'anno-mismatched-ellipsis': 'An array with $(CODE) can only be used if there is an assignment below with an array value',
160
167
  'anno-unexpected-ellipsis': 'No base annotation available to apply $(CODE)',
168
+ 'anno-unexpected-ellipsis-layers': 'No base annotation available to apply $(CODE)',
161
169
  'missing-type-parameter': 'Missing value for type parameter $(NAME) in reference to type $(ID)',
162
170
  'syntax-csn-expected-object': 'Expected object for property $(PROP)',
163
171
  'syntax-csn-expected-column': 'Expected object or string \'*\' for property $(PROP)',
@@ -179,6 +187,7 @@ const centralMessageTexts = {
179
187
  one: 'Expected array in $(PROP) to have at least one item',
180
188
  suffix: 'With sibling property $(OTHERPROP), expected array in $(PROP) to have at least one item',
181
189
  },
190
+ 'syntax-invalid-extend': 'Can\'t extend an element with $(KIND)',
182
191
  'syntax-invalid-text-block': 'Missing newline in text block',
183
192
  'syntax-unknown-escape': 'Unknown escape sequence $(CODE)',
184
193
  'syntax-invalid-escape': {
@@ -209,6 +218,7 @@ const centralMessageTexts = {
209
218
  'ref-unknown-var': {
210
219
  std: 'Replacement $(ID) not found'
211
220
  },
221
+ 'ref-unexpected-draft-enabled': 'Composition in draft-enabled entity can\'t lead to another entity with $(ANNO)',
212
222
  'ref-rejected-on': {
213
223
  std: 'Do not refer to a artefact like $(ID) in the explicit ON of a redirection', // Not used
214
224
  mixin: 'Do not refer to a mixin like $(ID) in the explicit ON of a redirection',
@@ -238,6 +248,17 @@ const centralMessageTexts = {
238
248
  param: 'Artifact $(ART) has no parameter $(MEMBER)'
239
249
  },
240
250
 
251
+ 'def-unexpected-paramview-assoc': {
252
+ std: 'SAP HANA does no support associations in/to parameterized entities',
253
+ view: 'SAP HANA does no support associations in parameterized entities',
254
+ target: 'SAP HANA does no support associations to parameterized entities',
255
+ },
256
+ 'def-unexpected-calcview-assoc': {
257
+ std: 'SAP HANA does not allow associations in/to entities annotated with $(ANNO)',
258
+ 'entity-persistence': 'SAP HANA does not allow associations in entities annotated with $(ANNO)',
259
+ 'target-persistence': 'SAP HANA does not allow associations pointing to entities annotated with $(ANNO)',
260
+ },
261
+
241
262
  'def-missing-element': {
242
263
  std: 'Expecting entity to have at least one non-virtual element',
243
264
  view: 'Expecting view to have at least one non-virtual element'
@@ -125,6 +125,7 @@ class CompileMessage {
125
125
  * @param {CSN.MessageSeverity} [severity='Error'] Severity: Debug, Info, Warning, Error
126
126
  * @param {string} [id] The ID of the message - visible as property messageId
127
127
  * @param {any} [home]
128
+ * @param {string} [moduleName] Name of the module that created this message
128
129
  *
129
130
  * @memberOf CompileMessage
130
131
  */
@@ -175,22 +176,6 @@ function dollarLocation( location ) {
175
176
  return loc;
176
177
  }
177
178
 
178
- /**
179
- * Handle compiler messages, i.e. throw a compiler exception if there are errors.
180
- *
181
- * @param {object} model CSN or XSN
182
- * @param {CSN.Options} [options]
183
- * @deprecated Use throwWithError() from makeMessageFunction instead.
184
- */
185
- function handleMessages( model, options = {} ) {
186
- const messages = options.messages;
187
- if (messages && messages.length) {
188
- if (hasErrors( messages ))
189
- throw new CompilationError( messages, options.attachValidNames && model );
190
- }
191
- return model;
192
- }
193
-
194
179
  const severitySpecs = {
195
180
  error: { name: 'Error', level: 0 },
196
181
  warning: { name: 'Warning', level: 1 },
@@ -282,16 +267,16 @@ function compareSeverities( a, b ) {
282
267
  /**
283
268
  * @todo This was copied from somewhere just to make CSN paths work.
284
269
  * @param {CSN.Model} model
285
- * @param {CSN.Path} path
270
+ * @param {CSN.Path} csnPath
286
271
  */
287
- function searchForLocation( model, path ) {
272
+ function searchForLocation( model, csnPath ) {
288
273
  if (!model)
289
274
  return null;
290
275
  // Don't display a location if we cannot find one!
291
276
  let lastLocation = null;
292
277
  /** @type {object} */
293
278
  let currentStep = model;
294
- for (const step of path) {
279
+ for (const step of csnPath) {
295
280
  if (!currentStep)
296
281
  return lastLocation;
297
282
  currentStep = currentStep[step];
@@ -1101,13 +1086,15 @@ function artName( art, omit ) {
1101
1086
  r.push( (art.kind === 'extend' ? 'block:' : 'query:') + name.select ); // TODO: rename to 'select:1' and consider whether there are more selects
1102
1087
  if (name.action && omit !== 'action')
1103
1088
  r.push( memberActionName(art) + ':' + quoted( name.action ) );
1104
- if (name.alias)
1089
+ if (name.alias && art.kind !== '$self')
1105
1090
  r.push( (art.kind === 'mixin' ? 'mixin:' : 'alias:') + quoted( name.alias ) )
1106
1091
  if (name.param != null && omit !== 'param')
1107
1092
  r.push( name.param ? 'param:' + quoted( name.param ) : 'returns' ); // TODO: join
1108
1093
  if (name.element && omit !== 'element')
1109
1094
  // r.push( `${ art.kind }: ${ quoted( name.element )}` ); or even better element:"assoc"/key:"i" same with enum
1110
1095
  r.push( (art.kind === 'enum' ? 'enum:' : 'element:') + quoted( name.element ) );
1096
+ if (art.kind === '$self')
1097
+ r.push( 'alias:' + quoted( name.alias ) ) // should be late due to $self in anonymous aspect
1111
1098
  return r.join('/');
1112
1099
  }
1113
1100
 
@@ -1120,6 +1107,7 @@ function memberActionName( art ) {
1120
1107
  return 'action';
1121
1108
  }
1122
1109
 
1110
+ // TODO: XSN-specific things should probably move out
1123
1111
  function homeName( art, absoluteOnly ) {
1124
1112
  if (!art)
1125
1113
  return art;
@@ -1135,8 +1123,10 @@ function homeName( art, absoluteOnly ) {
1135
1123
  return homeName( art.name._artifact, absoluteOnly ); // use corresponding definition
1136
1124
  else if (absoluteOnly)
1137
1125
  return art.name.absolute;
1138
- else
1139
- return (art._main ? art._main.kind : art.kind) + ':' + artName( art );
1126
+ let main = art._main || art;
1127
+ while (main._outer) // anonymous aspect
1128
+ main = main._outer._main;
1129
+ return main.kind + ':' + artName( art );
1140
1130
  }
1141
1131
 
1142
1132
  // The "home" for extensions is handled differently because `_artifact` is not
@@ -1190,9 +1180,9 @@ function constructSemanticLocationFromCsnPath(csnPath, model) {
1190
1180
 
1191
1181
  // remove definitions
1192
1182
  csnPath.shift();
1193
- const artName = csnPath.shift();
1194
- let currentThing = model.definitions[artName];
1195
- let result = `${ (currentThing && currentThing.kind) ? currentThing.kind : 'artifact' }:${ _quoted(artName) }`;
1183
+ const artifactName = csnPath.shift();
1184
+ let currentThing = model.definitions[artifactName];
1185
+ let result = `${ (currentThing && currentThing.kind) ? currentThing.kind : 'artifact' }:${ _quoted(artifactName) }`;
1196
1186
 
1197
1187
  if (!currentThing)
1198
1188
  return result;
@@ -1444,12 +1434,12 @@ module.exports = {
1444
1434
  createMessageFunctions,
1445
1435
  makeMessageFunction,
1446
1436
  artName,
1447
- handleMessages,
1448
1437
  sortMessages: (m => m.sort(compareMessage)),
1449
1438
  sortMessagesSeverityAware: (m => m.sort(compareMessageSeverityAware)),
1450
1439
  deduplicateMessages,
1451
1440
  CompileMessage,
1452
1441
  CompilationError,
1442
+ isMessageDowngradable: isDowngradable,
1453
1443
  explainMessage,
1454
1444
  hasMessageExplanation,
1455
1445
  messageIdsWithExplanation,
package/lib/base/model.js CHANGED
@@ -27,7 +27,6 @@ const availableBetaFlags = {
27
27
  ignoreAssocPublishingInUnion: true,
28
28
  nestedProjections: true,
29
29
  enableUniversalCsn: true,
30
- sqlSnippets: true,
31
30
  // disabled by --beta-mode
32
31
  nestedServices: false,
33
32
  };
@@ -64,7 +63,7 @@ function isBetaEnabled( options, feature ) {
64
63
  */
65
64
  function isDeprecatedEnabled( options, feature = null ) {
66
65
  const { deprecated } = options;
67
- if(!feature)
66
+ if (!feature)
68
67
  return !!deprecated;
69
68
  return deprecated && typeof deprecated === 'object' && deprecated[feature];
70
69
  }
@@ -94,63 +93,6 @@ function forEachMember( construct, callback, target ) {
94
93
 
95
94
  }
96
95
 
97
- // Apply function `callback(member, memberName, prop)` to each member in
98
- // `construct`, recursively (i.e. also for sub-elements of elements).
99
- function forEachMemberRecursively( construct, callback ) {
100
- forEachMember( construct, ( member, memberName, prop ) => {
101
- callback( member, memberName, prop );
102
- // Descend into nested members, too
103
- forEachMemberRecursively( member, callback );
104
- });
105
- // If 'construct' has more than one query, descend into the elements of the remaining ones, too
106
- if (construct.$queries && construct.$queries.length > 1) {
107
- construct.$queries.slice(1).forEach(query => forEachMemberRecursively(query, callback));
108
- }
109
- }
110
-
111
- /**
112
- * Apply function `callback` to all members of object `obj` (main artifact or
113
- * parent member). Members are considered those in dictionaries `elements`,
114
- * `enum`, `actions` and `params` of `obj`, `elements` and `enums` are also
115
- * searched inside property `items` (array of). `$queries`, `mixin` and
116
- * `columns` are also visited in contrast to `forEachMember()`.
117
- * See function `forEachGeneric()` for details.
118
- *
119
- * @param {XSN.Artifact} construct
120
- * @param {(member: object, memberName: string, prop: string) => any} callback
121
- * @param {object} [target]
122
- */
123
- function forEachMemberWithQuery( construct, callback, target ) {
124
- let obj = construct.returns || construct; // why the extra `returns` for actions?
125
- obj = obj.items || obj;
126
- forEachGeneric( target || obj, 'elements', callback );
127
- forEachGeneric( obj, 'enum', callback );
128
- forEachGeneric( obj, 'foreignKeys', callback );
129
- forEachGeneric( construct, 'actions', callback );
130
- forEachGeneric( construct, 'params', callback );
131
- // For Queries
132
- forEachGeneric( construct, '$queries', callback );
133
- forEachGeneric( construct, 'mixin', callback );
134
- forEachGeneric( construct, 'columns', callback );
135
- }
136
-
137
- /**
138
- * Apply function `callback(member, memberName, prop)` to each member in
139
- * `construct`, recursively (i.e. also for sub-elements of elements).
140
- * In contrast to `forEachMemberRecursively()` this function also traverses
141
- * queries and mixins.
142
- *
143
- * @param {XSN.Artifact} construct
144
- * @param {(member: object, memberName: string, prop: string) => any} callback
145
- */
146
- function forEachMemberRecursivelyWithQuery( construct, callback ) {
147
- forEachMemberWithQuery( construct, ( member, memberName, prop ) => {
148
- callback( member, memberName, prop );
149
- // Descend into nested members, too
150
- forEachMemberRecursivelyWithQuery( member, callback );
151
- });
152
- }
153
-
154
96
  // Apply function `callback` to all objects in dictionary `dict`, including all
155
97
  // duplicates (found under the same name). Function `callback` is called with
156
98
  // the following arguments: the object, the name, and -if it is a duplicate-
@@ -158,7 +100,7 @@ function forEachMemberRecursivelyWithQuery( construct, callback ) {
158
100
  function forEachGeneric( obj, prop, callback ) {
159
101
  let dict = obj[prop];
160
102
  for (let name in dict) {
161
- let obj = dict[name];
103
+ obj = dict[name];
162
104
  callback( obj, name, prop );
163
105
  if (Array.isArray(obj.$duplicates)) // redefinitions
164
106
  obj.$duplicates.forEach( o => callback( o, name, prop ) )
@@ -190,9 +132,6 @@ module.exports = {
190
132
  queryOps,
191
133
  forEachDefinition,
192
134
  forEachMember,
193
- forEachMemberRecursively,
194
- forEachMemberWithQuery,
195
- forEachMemberRecursivelyWithQuery,
196
135
  forEachGeneric,
197
136
  forEachInOrder,
198
137
  setProp,