@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.
- package/CHANGELOG.md +110 -15
- package/bin/cdsc.js +13 -13
- package/bin/cdsse.js +2 -2
- package/doc/CHANGELOG_BETA.md +13 -6
- package/doc/CHANGELOG_DEPRECATED.md +22 -6
- package/doc/NameResolution.md +21 -16
- package/lib/api/main.js +28 -63
- package/lib/api/options.js +3 -3
- package/lib/api/validate.js +0 -5
- package/lib/backends.js +15 -23
- package/lib/base/dictionaries.js +0 -8
- package/lib/base/error.js +26 -0
- package/lib/base/keywords.js +7 -17
- package/lib/base/location.js +9 -4
- package/lib/base/message-registry.js +25 -4
- package/lib/base/messages.js +16 -26
- package/lib/base/model.js +2 -63
- package/lib/base/optionProcessorHelper.js +158 -123
- package/lib/checks/annotationsOData.js +1 -1
- package/lib/checks/cdsPersistence.js +2 -1
- package/lib/checks/enricher.js +17 -1
- package/lib/checks/invalidTarget.js +3 -1
- package/lib/checks/managedWithoutKeys.js +3 -1
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +27 -26
- package/lib/checks/types.js +1 -1
- package/lib/checks/validator.js +4 -7
- package/lib/compiler/assert-consistency.js +5 -3
- package/lib/compiler/builtins.js +8 -6
- package/lib/compiler/checks.js +14 -3
- package/lib/compiler/cycle-detector.js +1 -1
- package/lib/compiler/define.js +1103 -0
- package/lib/compiler/extend.js +983 -0
- package/lib/compiler/finalize-parse-cdl.js +231 -0
- package/lib/compiler/index.js +32 -13
- package/lib/compiler/kick-start.js +190 -0
- package/lib/compiler/moduleLayers.js +4 -4
- package/lib/compiler/populate.js +1226 -0
- package/lib/compiler/propagator.js +111 -46
- package/lib/compiler/resolve.js +1433 -0
- package/lib/compiler/shared.js +64 -37
- package/lib/compiler/tweak-assocs.js +529 -0
- package/lib/compiler/utils.js +197 -33
- package/lib/edm/.eslintrc.json +5 -0
- package/lib/edm/annotations/genericTranslation.js +5 -9
- package/lib/edm/annotations/preprocessAnnotations.js +2 -2
- package/lib/edm/csn2edm.js +9 -8
- package/lib/edm/edm.js +11 -12
- package/lib/edm/edmPreprocessor.js +137 -73
- package/lib/edm/edmUtils.js +116 -22
- package/lib/gen/Dictionary.json +10 -3
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +9 -1
- package/lib/gen/language.tokens +86 -83
- package/lib/gen/languageLexer.interp +10 -1
- package/lib/gen/languageLexer.js +860 -833
- package/lib/gen/languageLexer.tokens +78 -75
- package/lib/gen/languageParser.js +5282 -4265
- package/lib/json/from-csn.js +12 -1
- package/lib/json/to-csn.js +126 -66
- package/lib/language/docCommentParser.js +2 -2
- package/lib/language/genericAntlrParser.js +76 -3
- package/lib/language/language.g4 +297 -130
- package/lib/language/multiLineStringParser.js +5 -5
- package/lib/main.d.ts +468 -59
- package/lib/main.js +35 -9
- package/lib/model/api.js +3 -1
- package/lib/model/csnRefs.js +225 -156
- package/lib/model/csnUtils.js +192 -223
- package/lib/model/enrichCsn.js +70 -29
- package/lib/model/revealInternalProperties.js +27 -6
- package/lib/model/sortViews.js +2 -1
- package/lib/modelCompare/compare.js +17 -12
- package/lib/optionProcessor.js +5 -4
- package/lib/render/manageConstraints.js +35 -32
- package/lib/render/toCdl.js +73 -288
- package/lib/render/toHdbcds.js +25 -23
- package/lib/render/toSql.js +98 -41
- package/lib/render/utils/common.js +5 -10
- package/lib/render/utils/sql.js +4 -3
- package/lib/render/utils/stringEscapes.js +111 -0
- package/lib/sql-identifier.js +1 -1
- package/lib/transform/.eslintrc.json +5 -0
- package/lib/transform/db/.eslintrc.json +2 -0
- package/lib/transform/db/applyTransformations.js +35 -12
- package/lib/transform/db/assertUnique.js +1 -1
- package/lib/transform/db/associations.js +103 -305
- package/lib/transform/db/cdsPersistence.js +2 -2
- package/lib/transform/db/constraints.js +55 -52
- package/lib/transform/db/expansion.js +46 -24
- package/lib/transform/db/flattening.js +553 -102
- package/lib/transform/db/groupByOrderBy.js +3 -1
- package/lib/transform/db/transformExists.js +59 -6
- package/lib/transform/db/views.js +5 -4
- package/lib/transform/draft/.eslintrc.json +38 -0
- package/lib/transform/{db/draft.js → draft/db.js} +6 -5
- package/lib/transform/draft/odata.js +227 -0
- package/lib/transform/forHanaNew.js +67 -183
- package/lib/transform/forOdataNew.js +17 -171
- package/lib/transform/localized.js +34 -19
- package/lib/transform/odata/generateForeignKeyElements.js +1 -1
- package/lib/transform/odata/referenceFlattener.js +95 -89
- package/lib/transform/odata/structureFlattener.js +1 -1
- package/lib/transform/odata/toFinalBaseType.js +86 -12
- package/lib/transform/odata/typesExposure.js +5 -5
- package/lib/transform/odata/utils.js +2 -2
- package/lib/transform/transformUtilsNew.js +36 -22
- package/lib/transform/translateAssocsToJoins.js +2 -19
- package/lib/transform/universalCsn/.eslintrc.json +36 -0
- package/lib/transform/universalCsn/coreComputed.js +170 -0
- package/lib/transform/universalCsn/universalCsnEnricher.js +715 -0
- package/lib/transform/universalCsn/utils.js +63 -0
- package/lib/utils/objectUtils.js +30 -0
- package/package.json +1 -1
- package/share/messages/README.md +26 -0
- package/lib/compiler/definer.js +0 -2361
- package/lib/compiler/resolver.js +0 -3079
- 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(
|
|
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(
|
|
299
|
+
function transformUserOption(userOptions) {
|
|
300
300
|
// move the user option value under user.id if specified as a string
|
|
301
|
-
if (
|
|
302
|
-
|
|
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 (
|
|
306
|
-
|
|
307
|
-
? Object.assign(
|
|
308
|
-
: { locale:
|
|
309
|
-
delete
|
|
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(
|
|
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
|
-
|
|
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 -----------
|
package/lib/base/dictionaries.js
CHANGED
|
@@ -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
|
+
};
|
package/lib/base/keywords.js
CHANGED
|
@@ -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',
|
package/lib/base/location.js
CHANGED
|
@@ -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-
|
|
48
|
-
'anno-invalid-sql-view
|
|
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'
|
package/lib/base/messages.js
CHANGED
|
@@ -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}
|
|
270
|
+
* @param {CSN.Path} csnPath
|
|
286
271
|
*/
|
|
287
|
-
function searchForLocation( model,
|
|
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
|
|
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
|
-
|
|
1139
|
-
|
|
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
|
|
1194
|
-
let currentThing = model.definitions[
|
|
1195
|
-
let result = `${ (currentThing && currentThing.kind) ? currentThing.kind : 'artifact' }:${ _quoted(
|
|
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
|
-
|
|
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,
|