@sap/cds-compiler 2.13.8 → 3.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.
- package/CHANGELOG.md +155 -1594
- package/bin/cdsc.js +144 -66
- package/doc/CHANGELOG_ARCHIVE.md +1592 -0
- package/doc/CHANGELOG_BETA.md +3 -4
- package/doc/CHANGELOG_DEPRECATED.md +35 -1
- package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
- package/doc/Versioning.md +20 -1
- package/lib/api/.eslintrc.json +2 -2
- package/lib/api/main.js +237 -122
- package/lib/api/options.js +17 -88
- package/lib/api/validate.js +12 -16
- package/lib/base/keywords.js +216 -109
- package/lib/base/message-registry.js +152 -37
- package/lib/base/messages.js +145 -83
- package/lib/base/model.js +44 -2
- package/lib/base/optionProcessorHelper.js +19 -0
- package/lib/checks/actionsFunctions.js +7 -5
- package/lib/checks/annotationsOData.js +11 -32
- package/lib/checks/arrayOfs.js +1 -34
- package/lib/checks/cdsPersistence.js +1 -0
- package/lib/checks/elements.js +6 -6
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/nonexpandableStructured.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -1
- package/lib/checks/selectItems.js +5 -1
- package/lib/checks/types.js +4 -2
- package/lib/checks/utils.js +2 -2
- package/lib/checks/validator.js +4 -5
- package/lib/compiler/assert-consistency.js +16 -10
- package/lib/compiler/base.js +1 -0
- package/lib/compiler/builtins.js +98 -9
- package/lib/compiler/checks.js +22 -70
- package/lib/compiler/define.js +61 -13
- package/lib/compiler/extend.js +79 -14
- package/lib/compiler/finalize-parse-cdl.js +46 -29
- package/lib/compiler/index.js +100 -37
- package/lib/compiler/moduleLayers.js +7 -0
- package/lib/compiler/populate.js +19 -18
- package/lib/compiler/propagator.js +7 -4
- package/lib/compiler/resolve.js +297 -234
- package/lib/compiler/shared.js +107 -102
- package/lib/compiler/tweak-assocs.js +16 -11
- package/lib/compiler/utils.js +5 -0
- package/lib/edm/annotations/genericTranslation.js +93 -21
- package/lib/edm/csn2edm.js +230 -115
- package/lib/edm/edm.js +305 -226
- package/lib/edm/edmPreprocessor.js +509 -438
- package/lib/edm/edmUtils.js +31 -45
- package/lib/gen/Dictionary.json +98 -22
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +10 -30
- package/lib/gen/language.tokens +105 -114
- package/lib/gen/languageLexer.interp +1 -34
- package/lib/gen/languageLexer.js +889 -1007
- package/lib/gen/languageLexer.tokens +95 -106
- package/lib/gen/languageParser.js +20786 -22199
- package/lib/json/csnVersion.js +10 -11
- package/lib/json/from-csn.js +59 -51
- package/lib/json/to-csn.js +10 -10
- package/lib/language/antlrParser.js +2 -2
- package/lib/language/docCommentParser.js +62 -39
- package/lib/language/errorStrategy.js +52 -40
- package/lib/language/genericAntlrParser.js +348 -229
- package/lib/language/language.g4 +629 -653
- package/lib/language/multiLineStringParser.js +14 -42
- package/lib/language/textUtils.js +44 -0
- package/lib/main.d.ts +46 -43
- package/lib/main.js +108 -79
- package/lib/model/csnRefs.js +34 -7
- package/lib/model/csnUtils.js +337 -332
- package/lib/model/enrichCsn.js +1 -0
- package/lib/model/revealInternalProperties.js +30 -10
- package/lib/model/sortViews.js +32 -31
- package/lib/modelCompare/compare.js +6 -6
- package/lib/optionProcessor.js +73 -46
- package/lib/render/.eslintrc.json +1 -1
- package/lib/render/DuplicateChecker.js +4 -7
- package/lib/render/manageConstraints.js +70 -2
- package/lib/render/toCdl.js +1042 -882
- package/lib/render/toHdbcds.js +195 -245
- package/lib/render/toRename.js +44 -22
- package/lib/render/toSql.js +225 -241
- package/lib/render/utils/common.js +145 -15
- package/lib/render/utils/sql.js +20 -19
- package/lib/sql-identifier.js +6 -0
- package/lib/transform/db/.eslintrc.json +4 -3
- package/lib/transform/db/associations.js +2 -2
- package/lib/transform/db/cdsPersistence.js +5 -15
- package/lib/transform/db/constraints.js +4 -2
- package/lib/transform/db/expansion.js +22 -16
- package/lib/transform/db/flattening.js +109 -80
- package/lib/transform/db/transformExists.js +7 -7
- package/lib/transform/db/views.js +9 -6
- package/lib/transform/draft/.eslintrc.json +2 -2
- package/lib/transform/draft/db.js +6 -6
- package/lib/transform/draft/odata.js +6 -7
- package/lib/transform/forHanaNew.js +62 -48
- package/lib/transform/forOdataNew.js +49 -50
- package/lib/transform/localized.js +31 -20
- package/lib/transform/odata/toFinalBaseType.js +16 -14
- package/lib/transform/odata/typesExposure.js +146 -198
- package/lib/transform/odata/utils.js +1 -38
- package/lib/transform/transformUtilsNew.js +67 -84
- package/lib/transform/translateAssocsToJoins.js +7 -3
- package/lib/transform/universalCsn/.eslintrc.json +2 -2
- package/lib/transform/universalCsn/coreComputed.js +16 -9
- package/lib/transform/universalCsn/universalCsnEnricher.js +60 -10
- package/lib/utils/file.js +3 -3
- package/lib/utils/moduleResolve.js +13 -6
- package/lib/utils/timetrace.js +20 -21
- package/package.json +35 -4
- package/share/messages/message-explanations.json +2 -1
- package/share/messages/syntax-expected-integer.md +37 -0
- package/doc/ApiMigration.md +0 -237
- package/doc/CommandLineMigration.md +0 -58
- package/doc/ErrorMessages.md +0 -175
- package/doc/FioriAnnotations.md +0 -94
- package/doc/ODataTransformation.md +0 -273
- package/lib/backends.js +0 -529
- package/lib/fix_antlr4-8_warning.js +0 -56
- package/lib/transform/odata/attachPath.js +0 -96
- package/lib/transform/odata/expandStructKeysInAssociations.js +0 -59
- package/lib/transform/odata/generateForeignKeyElements.js +0 -261
- package/lib/transform/odata/referenceFlattener.js +0 -296
- package/lib/transform/odata/sortByAssociationDependency.js +0 -105
- package/lib/transform/odata/structuralPath.js +0 -72
- package/lib/transform/odata/structureFlattener.js +0 -171
package/lib/json/csnVersion.js
CHANGED
|
@@ -15,18 +15,17 @@
|
|
|
15
15
|
// 0.1.99 : Like 0.1.0, but with new-style CSN
|
|
16
16
|
// 0.2 : same as 0.1.99, but with new top-level properties: $version, meta
|
|
17
17
|
|
|
18
|
-
// Use literal version constants intentionally and not number intervals to
|
|
18
|
+
// Use literal version constants intentionally and not number intervals to
|
|
19
19
|
// record all published version strings of the core compiler.
|
|
20
|
-
const newCSNVersions = [
|
|
20
|
+
const newCSNVersions = [ '0.1.99', '0.2', '0.2.0', '1.0', '2.0' ];
|
|
21
21
|
// checks if new-csn is requested via the options of already specified in the CSN
|
|
22
22
|
// default: old-style
|
|
23
23
|
function isNewCSN(csn, options) {
|
|
24
|
-
if( (options && options.newCsn ===
|
|
24
|
+
if ( (options && options.newCsn === false) ||
|
|
25
25
|
(csn.version && !newCSNVersions.includes(csn.version.csn)) ||
|
|
26
26
|
(csn.$version && !newCSNVersions.includes(csn.$version)))
|
|
27
|
-
{
|
|
28
27
|
return false;
|
|
29
|
-
|
|
28
|
+
|
|
30
29
|
return true;
|
|
31
30
|
}
|
|
32
31
|
|
|
@@ -34,18 +33,18 @@ function checkCSNVersion(csn, options) {
|
|
|
34
33
|
if (!isNewCSN(csn, options)) {
|
|
35
34
|
// the new transformer works only with new CSN
|
|
36
35
|
const { makeMessageFunction } = require('../base/messages');
|
|
37
|
-
const { error,
|
|
36
|
+
const { error, throwWithAnyError } = makeMessageFunction(csn, options);
|
|
38
37
|
|
|
39
38
|
let errStr = 'CSN Version not supported, version tag: "';
|
|
40
|
-
errStr +=
|
|
41
|
-
errStr += (options.newCsn !== undefined) ?
|
|
39
|
+
errStr += `${ csn.version && csn.version.csn ? csn.version.csn : (csn.$version ? csn.$version : 'not available') }"`;
|
|
40
|
+
errStr += (options.newCsn !== undefined) ? `, options.newCsn: ${ options.newCsn }` : '';
|
|
42
41
|
|
|
43
42
|
error(null, null, errStr);
|
|
44
|
-
|
|
43
|
+
throwWithAnyError();
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
module.exports = {
|
|
49
48
|
isNewCSN,
|
|
50
|
-
checkCSNVersion
|
|
51
|
-
}
|
|
49
|
+
checkCSNVersion,
|
|
50
|
+
};
|
package/lib/json/from-csn.js
CHANGED
|
@@ -135,7 +135,7 @@ const schemaClasses = {
|
|
|
135
135
|
condition: {
|
|
136
136
|
arrayOf: exprOrString,
|
|
137
137
|
type: condition,
|
|
138
|
-
msgId: 'syntax-
|
|
138
|
+
msgId: 'syntax-expected-term',
|
|
139
139
|
// TODO: also specify requires here, and adapt onlyWith()
|
|
140
140
|
optional: exprProperties,
|
|
141
141
|
},
|
|
@@ -145,14 +145,15 @@ const schemaClasses = {
|
|
|
145
145
|
},
|
|
146
146
|
natnumOrStar: {
|
|
147
147
|
type: natnumOrStar,
|
|
148
|
-
msgId: 'syntax-
|
|
148
|
+
msgId: 'syntax-expected-cardinality',
|
|
149
149
|
},
|
|
150
150
|
columns: {
|
|
151
151
|
arrayOf: selectItem,
|
|
152
|
-
msgId: 'syntax-
|
|
152
|
+
msgId: 'syntax-expected-column',
|
|
153
153
|
defaultKind: '$column',
|
|
154
154
|
validKinds: [], // pseudo kind '$column'
|
|
155
|
-
|
|
155
|
+
// A column with only as+cast.type is a new association
|
|
156
|
+
requires: [ 'ref', 'as', 'xpr', 'val', '#', 'func', 'list', 'SELECT', 'SET', 'expand' ],
|
|
156
157
|
schema: {
|
|
157
158
|
xpr: {
|
|
158
159
|
class: 'condition',
|
|
@@ -197,7 +198,7 @@ const schema = compileSchema( {
|
|
|
197
198
|
dictionaryOf: definition,
|
|
198
199
|
defaultKind: 'enum',
|
|
199
200
|
validKinds: [ 'enum' ],
|
|
200
|
-
inKind: [ 'element', 'type', 'param', 'annotation', 'annotate' ],
|
|
201
|
+
inKind: [ 'element', 'type', 'param', 'annotation', 'annotate', 'extend' ],
|
|
201
202
|
},
|
|
202
203
|
elements: {
|
|
203
204
|
dictionaryOf: definition,
|
|
@@ -289,7 +290,7 @@ const schema = compileSchema( {
|
|
|
289
290
|
// type properties (except: elements, enum, keys, on): ---------------------
|
|
290
291
|
type: {
|
|
291
292
|
type: artifactRef,
|
|
292
|
-
msgId: 'syntax-
|
|
293
|
+
msgId: 'syntax-expected-reference',
|
|
293
294
|
optional: [ 'ref', 'global' ],
|
|
294
295
|
inKind: [ 'element', 'type', 'param', 'mixin', 'event', 'annotation' ],
|
|
295
296
|
},
|
|
@@ -365,7 +366,7 @@ const schema = compileSchema( {
|
|
|
365
366
|
ref: {
|
|
366
367
|
arrayOf: refItem,
|
|
367
368
|
type: renameTo( 'path', arrayOf( refItem ) ),
|
|
368
|
-
msgId: 'syntax-
|
|
369
|
+
msgId: 'syntax-expected-reference',
|
|
369
370
|
minLength: 1,
|
|
370
371
|
requires: 'id',
|
|
371
372
|
optional: [ 'id', 'args', 'cardinality', 'where' ],
|
|
@@ -581,7 +582,7 @@ const schema = compileSchema( {
|
|
|
581
582
|
inKind: [ 'element', '$column' ],
|
|
582
583
|
},
|
|
583
584
|
masked: {
|
|
584
|
-
type:
|
|
585
|
+
type: masked,
|
|
585
586
|
inKind: [ 'element' ],
|
|
586
587
|
},
|
|
587
588
|
notNull: {
|
|
@@ -778,7 +779,7 @@ function arrayOf( fn, filter = undefined ) {
|
|
|
778
779
|
} );
|
|
779
780
|
const minLength = spec.minLength || 0;
|
|
780
781
|
if (minLength > val.length) {
|
|
781
|
-
message( 'syntax-
|
|
782
|
+
message( 'syntax-expected-length', location(true),
|
|
782
783
|
{ prop: spec.prop, n: minLength, '#': minLength === 1 ? 'one' : 'std' });
|
|
783
784
|
}
|
|
784
785
|
if (val.length)
|
|
@@ -848,7 +849,7 @@ function object( obj, spec ) {
|
|
|
848
849
|
if (requires === undefined || requires === true) {
|
|
849
850
|
// console.log(csnProps,JSON.stringify(spec))
|
|
850
851
|
if (!relevantProps) {
|
|
851
|
-
error( 'syntax-
|
|
852
|
+
error( 'syntax-required-subproperty', location(true),
|
|
852
853
|
{
|
|
853
854
|
prop: spec.msgProp,
|
|
854
855
|
'#': (
|
|
@@ -874,7 +875,7 @@ function object( obj, spec ) {
|
|
|
874
875
|
|
|
875
876
|
function vZeroDelete( o, spec ) { // for old-CSN property 'origin'
|
|
876
877
|
if (!csnVersionZero) {
|
|
877
|
-
warning( 'syntax-
|
|
878
|
+
warning( 'syntax-zero-delete', location(true), { prop: spec.msgProp },
|
|
878
879
|
'Delete/inline CSN v0.1.0 property $(PROP)' );
|
|
879
880
|
}
|
|
880
881
|
string( o, spec );
|
|
@@ -959,7 +960,7 @@ function definition( def, spec, xsn, csn, name ) {
|
|
|
959
960
|
function dictionaryOf( elementFct ) {
|
|
960
961
|
return function dictionary( dict, spec ) {
|
|
961
962
|
if (!dict || typeof dict !== 'object' || Array.isArray( dict )) {
|
|
962
|
-
error( 'syntax-
|
|
963
|
+
error( 'syntax-expected-object', location(true),
|
|
963
964
|
{ prop: spec.prop }); // spec.prop, not spec.msgProp!
|
|
964
965
|
return ignore( dict );
|
|
965
966
|
}
|
|
@@ -971,7 +972,7 @@ function dictionaryOf( elementFct ) {
|
|
|
971
972
|
++virtualLine;
|
|
972
973
|
for (const name of allNames) {
|
|
973
974
|
if (!name) {
|
|
974
|
-
warning( 'syntax-
|
|
975
|
+
warning( 'syntax-empty-name', location(true),
|
|
975
976
|
{ prop: spec.prop }, // TODO: Error
|
|
976
977
|
'Property names in dictionary $(PROP) must not be empty' );
|
|
977
978
|
}
|
|
@@ -1048,11 +1049,11 @@ function validKind( val, spec, xsn ) {
|
|
|
1048
1049
|
if (val === xsn.kind) // has been set in definition - the same = ok!
|
|
1049
1050
|
return undefined; // already set in definition
|
|
1050
1051
|
if (val === 'view' && xsn.kind === 'entity') {
|
|
1051
|
-
warning( 'syntax-
|
|
1052
|
+
warning( 'syntax-zero-value', location(true), { prop: spec.msgProp },
|
|
1052
1053
|
'Replace CSN v0.1.0 value in $(PROP) by something specified' );
|
|
1053
1054
|
}
|
|
1054
1055
|
else if ((val === 'entity' || val === 'type') && xsn.kind === 'aspect') {
|
|
1055
|
-
info( 'syntax-
|
|
1056
|
+
info( 'syntax-aspect', location(true), { kind: 'aspect', '#': val },
|
|
1056
1057
|
{
|
|
1057
1058
|
std: 'Use the dedicated kind $(KIND) for aspect definitions',
|
|
1058
1059
|
// eslint-disable-next-line max-len
|
|
@@ -1060,7 +1061,7 @@ function validKind( val, spec, xsn ) {
|
|
|
1060
1061
|
} );
|
|
1061
1062
|
}
|
|
1062
1063
|
else {
|
|
1063
|
-
error( 'syntax-
|
|
1064
|
+
error( 'syntax-expected-valid', location(true), { prop: spec.msgProp },
|
|
1064
1065
|
'Expected valid string for property $(PROP)' );
|
|
1065
1066
|
}
|
|
1066
1067
|
return ignore( val );
|
|
@@ -1102,7 +1103,7 @@ function vZeroRef( name, spec, xsn ) {
|
|
|
1102
1103
|
return;
|
|
1103
1104
|
const path = name.split('.');
|
|
1104
1105
|
if (!path.every( id => id)) {
|
|
1105
|
-
warning( 'syntax-
|
|
1106
|
+
warning( 'syntax-expected-name', location(true), { prop: spec.msgProp },
|
|
1106
1107
|
'Expected correct name for property $(PROP)' );
|
|
1107
1108
|
}
|
|
1108
1109
|
xsn.path = path.map( id => ({ id, location: location() }) );
|
|
@@ -1113,7 +1114,7 @@ function vZeroRef( name, spec, xsn ) {
|
|
|
1113
1114
|
function boolOrNull( val, spec ) {
|
|
1114
1115
|
if ([ true, false, null ].includes( val ))
|
|
1115
1116
|
return { val, location: location() };
|
|
1116
|
-
warning( 'syntax-
|
|
1117
|
+
warning( 'syntax-expected-boolean', location(true), { prop: spec.msgProp },
|
|
1117
1118
|
'Expected boolean or null for property $(PROP)' );
|
|
1118
1119
|
ignore( val );
|
|
1119
1120
|
return { val: !!val, location: location() };
|
|
@@ -1123,7 +1124,7 @@ function string( val, spec ) {
|
|
|
1123
1124
|
if (typeof val === 'string' && val)
|
|
1124
1125
|
// XSN TODO: do not require literal
|
|
1125
1126
|
return val;
|
|
1126
|
-
error( 'syntax-
|
|
1127
|
+
error( 'syntax-expected-string', location(true), { prop: spec.msgProp },
|
|
1127
1128
|
'Expected non-empty string for property $(PROP)' );
|
|
1128
1129
|
return ignore( val );
|
|
1129
1130
|
}
|
|
@@ -1132,7 +1133,7 @@ function stringVal( val, spec ) {
|
|
|
1132
1133
|
if (typeof val === 'string' && val)
|
|
1133
1134
|
// XSN TODO: do not require literal
|
|
1134
1135
|
return { val, literal: 'string', location: location() };
|
|
1135
|
-
error( 'syntax-
|
|
1136
|
+
error( 'syntax-expected-string', location(true), { prop: spec.msgProp },
|
|
1136
1137
|
'Expected non-empty string for property $(PROP)' );
|
|
1137
1138
|
return ignore( val );
|
|
1138
1139
|
}
|
|
@@ -1154,7 +1155,7 @@ function natnum( val, spec ) {
|
|
|
1154
1155
|
if (typeof val === 'number' && val >= 0)
|
|
1155
1156
|
// XSN TODO: do not require literal
|
|
1156
1157
|
return { val, literal: 'number', location: location() };
|
|
1157
|
-
error( spec.msgId || 'syntax-
|
|
1158
|
+
error( spec.msgId || 'syntax-expected-natnum', location(true),
|
|
1158
1159
|
{ prop: spec.msgProp } );
|
|
1159
1160
|
return ignore( val );
|
|
1160
1161
|
}
|
|
@@ -1189,10 +1190,8 @@ function annoValue( val, spec ) {
|
|
|
1189
1190
|
/** @type {string|boolean} */
|
|
1190
1191
|
let seenEllipsis = false;
|
|
1191
1192
|
if (arrayLevelCount > 0) { // TODO: also inside structure (possible in CSN!)
|
|
1192
|
-
if (val.some( isEllipsis ))
|
|
1193
|
-
error( 'syntax-
|
|
1194
|
-
'Unexpected $(CODE) in nested array' );
|
|
1195
|
-
}
|
|
1193
|
+
if (val.some( isEllipsis ))
|
|
1194
|
+
error( 'syntax-unexpected-ellipsis', location(true), { '#': 'nested-array', code: '...' } );
|
|
1196
1195
|
}
|
|
1197
1196
|
else {
|
|
1198
1197
|
for (const item of val) {
|
|
@@ -1201,7 +1200,7 @@ function annoValue( val, spec ) {
|
|
|
1201
1200
|
}
|
|
1202
1201
|
else if (isEllipsis( item )) { // with or without UP TO
|
|
1203
1202
|
// error position at the beginning of the array, but that is fine
|
|
1204
|
-
error( 'syntax-
|
|
1203
|
+
error( 'syntax-duplicate-ellipsis', location(true), { code: '...' },
|
|
1205
1204
|
'Expected no more than one $(CODE)' );
|
|
1206
1205
|
break;
|
|
1207
1206
|
}
|
|
@@ -1215,7 +1214,7 @@ function annoValue( val, spec ) {
|
|
|
1215
1214
|
};
|
|
1216
1215
|
arrayLevelCount--;
|
|
1217
1216
|
if (seenEllipsis === 'upTo') {
|
|
1218
|
-
error( 'syntax-
|
|
1217
|
+
error( 'syntax-expecting-ellipsis', location(true), // at closing bracket
|
|
1219
1218
|
{ code: '... up to', newcode: '...' },
|
|
1220
1219
|
// TODO: should we be more CSN specific in the message?
|
|
1221
1220
|
'Expecting an array item $(NEWCODE) after an item with $(CODE)' );
|
|
@@ -1262,11 +1261,14 @@ function annoValue( val, spec ) {
|
|
|
1262
1261
|
}
|
|
1263
1262
|
|
|
1264
1263
|
function annotation( val, spec, xsn, csn, name ) {
|
|
1265
|
-
const
|
|
1266
|
-
|
|
1264
|
+
const absolute = (xsn ? name.substring(1) : name);
|
|
1265
|
+
// TODO: really care about variant (qualifier parts)?
|
|
1266
|
+
const variantIndex = absolute.indexOf('#') + 1 || absolute.length;
|
|
1267
|
+
const n = refSplit( absolute.substring( 0, variantIndex ), spec.msgProp );
|
|
1267
1268
|
if (!n)
|
|
1268
1269
|
return undefined;
|
|
1269
|
-
|
|
1270
|
+
n.absolute = absolute;
|
|
1271
|
+
if (variantIndex < absolute.length)
|
|
1270
1272
|
n.variant = { id: name.substring( variantIndex ), location: location() };
|
|
1271
1273
|
const r = annoValue( val, spec );
|
|
1272
1274
|
r.name = n;
|
|
@@ -1281,7 +1283,7 @@ function value( val, spec, xsn ) { // for CSN property 'val'
|
|
|
1281
1283
|
xsn.literal = (val === null) ? 'null' : typeof val;
|
|
1282
1284
|
return val;
|
|
1283
1285
|
}
|
|
1284
|
-
error( 'syntax-
|
|
1286
|
+
error( 'syntax-expected-scalar', location(true), { prop: spec.msgProp },
|
|
1285
1287
|
'Only scalar values are supported for property $(PROP)' );
|
|
1286
1288
|
return ignore( val );
|
|
1287
1289
|
}
|
|
@@ -1293,7 +1295,7 @@ function literal( val, spec, xsn, csn ) {
|
|
|
1293
1295
|
return val;
|
|
1294
1296
|
if (typeof val === 'string' && validLiteralsExtra[val] === type)
|
|
1295
1297
|
return val;
|
|
1296
|
-
error( 'syntax-
|
|
1298
|
+
error( 'syntax-expected-valid', location(true), { prop: spec.msgProp },
|
|
1297
1299
|
'Expected valid string for property $(PROP)' );
|
|
1298
1300
|
return ignore( val );
|
|
1299
1301
|
}
|
|
@@ -1308,7 +1310,7 @@ function func( val, spec, xsn ) {
|
|
|
1308
1310
|
function xpr( exprs, spec, xsn, csn ) {
|
|
1309
1311
|
if (csn.func) {
|
|
1310
1312
|
if (!exprs.length) {
|
|
1311
|
-
message( 'syntax-
|
|
1313
|
+
message( 'syntax-expected-length', location(true),
|
|
1312
1314
|
{ prop: 'xpr', otherprop: 'func', '#': 'suffix' });
|
|
1313
1315
|
}
|
|
1314
1316
|
xsn.suffix = exprArgs( exprs, spec );
|
|
@@ -1341,7 +1343,7 @@ function args( exprs, spec ) {
|
|
|
1341
1343
|
return arrayOf( exprOrString )( exprs, spec );
|
|
1342
1344
|
}
|
|
1343
1345
|
else if (!exprs || typeof exprs !== 'object') {
|
|
1344
|
-
error( 'syntax-
|
|
1346
|
+
error( 'syntax-expected-args', location(true),
|
|
1345
1347
|
{ prop: spec.prop }, // spec.prop, not spec.msgProp!
|
|
1346
1348
|
'Expected array or object for property $(PROP)' );
|
|
1347
1349
|
return ignore( exprs );
|
|
@@ -1404,12 +1406,12 @@ function condition( cond, spec ) {
|
|
|
1404
1406
|
function vZeroValue( obj, spec, xsn ) {
|
|
1405
1407
|
if (xsn.value) {
|
|
1406
1408
|
// TODO: also "sign" xsn.value created by inValue to complain about both 'value' and 'ref' etc
|
|
1407
|
-
warning( 'syntax-
|
|
1409
|
+
warning( 'syntax-unexpected-property', location(true), { prop: spec.msgProp },
|
|
1408
1410
|
'Unexpected CSN property $(PROP)' );
|
|
1409
1411
|
return undefined;
|
|
1410
1412
|
}
|
|
1411
1413
|
if (!csnVersionZero) {
|
|
1412
|
-
warning( 'syntax-
|
|
1414
|
+
warning( 'syntax-zero-delete', location(true), { prop: spec.msgProp },
|
|
1413
1415
|
'Delete/inline CSN v0.1.0 property $(PROP)' );
|
|
1414
1416
|
}
|
|
1415
1417
|
return expr( obj, spec );
|
|
@@ -1456,6 +1458,12 @@ function excluding( array, spec, xsn ) {
|
|
|
1456
1458
|
xsn.excludingDict = r;
|
|
1457
1459
|
}
|
|
1458
1460
|
|
|
1461
|
+
function masked( val, spec ) {
|
|
1462
|
+
message('syntax-invalid-masked', location(), { keyword: 'masked' },
|
|
1463
|
+
'Keyword $(KEYWORD) not supported');
|
|
1464
|
+
return boolOrNull( val, spec );
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1459
1467
|
function duplicateExcluding( name, loc ) {
|
|
1460
1468
|
error( 'duplicate-excluding', loc, { name, keyword: 'excluding' },
|
|
1461
1469
|
'Duplicate $(NAME) in the $(KEYWORD) clause' );
|
|
@@ -1476,7 +1484,7 @@ function join( val, spec, xsn ) {
|
|
|
1476
1484
|
|
|
1477
1485
|
function queryArgs( val, spec, xsn, csn ) {
|
|
1478
1486
|
if (Array.isArray( val ) && val.length > 1 && !csn.op) {
|
|
1479
|
-
warning( 'syntax-
|
|
1487
|
+
warning( 'syntax-expected-property', location(true),
|
|
1480
1488
|
{ prop: 'args', otherprop: 'op' },
|
|
1481
1489
|
'CSN property $(PROP) expects property $(OTHERPROP) to be specified' );
|
|
1482
1490
|
xsn.op = { val: 'union', location: location() };
|
|
@@ -1495,7 +1503,7 @@ function i18nLang( val, spec, xsn, csn, langKey ) {
|
|
|
1495
1503
|
function translations( keyVal, spec, xsn, csn, textKey ) {
|
|
1496
1504
|
if (typeof keyVal === 'string') // allow empty string
|
|
1497
1505
|
return { val: keyVal, literal: 'string', location: location() };
|
|
1498
|
-
error( 'syntax-
|
|
1506
|
+
error( 'syntax-expected-translation', location(true),
|
|
1499
1507
|
{ prop: textKey, otherprop: spec.prop },
|
|
1500
1508
|
'Expected string for text key $(PROP) of language $(OTHERPROP)' );
|
|
1501
1509
|
return ignore( keyVal );
|
|
@@ -1509,7 +1517,7 @@ function getSpec( parentSpec, csn, prop, xor, expected, kind ) {
|
|
|
1509
1517
|
if (!s || s.noPrefix && prop !== p0 ) {
|
|
1510
1518
|
if (ourpropsRegex.test( prop )) {
|
|
1511
1519
|
// TODO v2: Warning only with --sloppy
|
|
1512
|
-
warning( 'syntax-
|
|
1520
|
+
warning( 'syntax-unknown-property', location(true), { prop },
|
|
1513
1521
|
'Unknown CSN property $(PROP)' );
|
|
1514
1522
|
}
|
|
1515
1523
|
else { // TODO v2: always (i.e. also with message) add to $extra
|
|
@@ -1520,7 +1528,7 @@ function getSpec( parentSpec, csn, prop, xor, expected, kind ) {
|
|
|
1520
1528
|
if (s.ignore)
|
|
1521
1529
|
return { type: ignore };
|
|
1522
1530
|
if (s.vZeroIgnore && s.vZeroIgnore === csn[prop]) { // for "op": "call"
|
|
1523
|
-
warning( 'syntax-
|
|
1531
|
+
warning( 'syntax-zero-delete', location(true), { prop },
|
|
1524
1532
|
'Delete/inline CSN v0.1.0 property $(PROP)' );
|
|
1525
1533
|
return { type: ignore };
|
|
1526
1534
|
}
|
|
@@ -1539,7 +1547,7 @@ function getSpec( parentSpec, csn, prop, xor, expected, kind ) {
|
|
|
1539
1547
|
const variant = kind && s.inKind
|
|
1540
1548
|
? ([ 'extend', 'annotate' ].includes(kind) ? kind : 'def')
|
|
1541
1549
|
: (parentSpec.msgProp ? 'std' : 'top');
|
|
1542
|
-
message( 'syntax-
|
|
1550
|
+
message( 'syntax-unexpected-property', location(true),
|
|
1543
1551
|
{
|
|
1544
1552
|
prop, otherprop: parentSpec.msgProp, kind, '#': variant,
|
|
1545
1553
|
},
|
|
@@ -1597,13 +1605,13 @@ function onlyWith( spec, need, csn, prop, xor, expected ) {
|
|
|
1597
1605
|
need = allowed.find( p => !xor[schema[p].xorGroup] ) || allowed[0];
|
|
1598
1606
|
}
|
|
1599
1607
|
if (prop) {
|
|
1600
|
-
error( 'syntax-
|
|
1608
|
+
error( 'syntax-dependent-property', location(true),
|
|
1601
1609
|
{ prop, otherprop: need },
|
|
1602
1610
|
'CSN property $(PROP) can only be used in combination with $(OTHERPROP)');
|
|
1603
1611
|
xor['no:req'] = prop;
|
|
1604
1612
|
}
|
|
1605
1613
|
else if (!xor['no:req']) {
|
|
1606
|
-
error( 'syntax-
|
|
1614
|
+
error( 'syntax-required-property', location(true),
|
|
1607
1615
|
{ prop: need, otherprop: spec.msgProp, '#': spec.prop },
|
|
1608
1616
|
{ // TODO $(PARENT), TODO: do not use prop===0 hack
|
|
1609
1617
|
std: 'Object in $(OTHERPROP) must have the property $(PROP)',
|
|
@@ -1625,7 +1633,7 @@ function checkAndSetXorGroup( group, prop, xor ) {
|
|
|
1625
1633
|
if (prop === 'func' && xor[group] === 'xpr' ||
|
|
1626
1634
|
prop === 'xpr' && xor[group] === 'func')
|
|
1627
1635
|
return true; // hack for window function: both func and xpr is allowed
|
|
1628
|
-
error( 'syntax-
|
|
1636
|
+
error( 'syntax-excluded-property', location(true),
|
|
1629
1637
|
{ prop, otherprop: xor[group] },
|
|
1630
1638
|
'CSN property $(PROP) can only be used alternatively to $(OTHERPROP)');
|
|
1631
1639
|
return false;
|
|
@@ -1640,7 +1648,7 @@ function implicitName( ref ) {
|
|
|
1640
1648
|
function replaceZeroProp( otherprop, prop ) {
|
|
1641
1649
|
if (csnVersionZero)
|
|
1642
1650
|
return;
|
|
1643
|
-
warning( 'syntax-
|
|
1651
|
+
warning( 'syntax-zero-prop', location(true), { prop, otherprop },
|
|
1644
1652
|
'Replace CSN v0.1.0 property $(OTHERPROP) by $(PROP)' );
|
|
1645
1653
|
}
|
|
1646
1654
|
|
|
@@ -1649,7 +1657,7 @@ function replaceZeroProp( otherprop, prop ) {
|
|
|
1649
1657
|
function isArray( array, spec ) {
|
|
1650
1658
|
if (Array.isArray( array ))
|
|
1651
1659
|
return array;
|
|
1652
|
-
error( 'syntax-
|
|
1660
|
+
error( 'syntax-expected-array', location(true), { prop: spec.prop },
|
|
1653
1661
|
'Expected array for property $(PROP)' );
|
|
1654
1662
|
return ignore( array );
|
|
1655
1663
|
}
|
|
@@ -1657,7 +1665,7 @@ function isArray( array, spec ) {
|
|
|
1657
1665
|
function isObject( obj, spec ) {
|
|
1658
1666
|
if (obj && typeof obj === 'object' && !Array.isArray( obj ))
|
|
1659
1667
|
return obj;
|
|
1660
|
-
error( spec.msgId || 'syntax-
|
|
1668
|
+
error( spec.msgId || 'syntax-expected-object', location(true),
|
|
1661
1669
|
{ prop: spec.msgProp });
|
|
1662
1670
|
return ignore( obj );
|
|
1663
1671
|
}
|
|
@@ -1665,7 +1673,7 @@ function isObject( obj, spec ) {
|
|
|
1665
1673
|
function refSplit( name, prop ) {
|
|
1666
1674
|
const path = name.split('.');
|
|
1667
1675
|
if (!path.every( id => id)) {
|
|
1668
|
-
warning( 'syntax-
|
|
1676
|
+
warning( 'syntax-expected-name', location(true), { prop },
|
|
1669
1677
|
'Expected correct name for property $(PROP)' );
|
|
1670
1678
|
}
|
|
1671
1679
|
return { path: path.map( id => ({ id, location: location() }) ), location: location() };
|
|
@@ -1673,7 +1681,7 @@ function refSplit( name, prop ) {
|
|
|
1673
1681
|
|
|
1674
1682
|
function replaceZeroValue( spec ) {
|
|
1675
1683
|
if (!csnVersionZero && spec.vZeroFor == null) { // but 0 does not match!
|
|
1676
|
-
warning( 'syntax-
|
|
1684
|
+
warning( 'syntax-zero-value', location(true), { prop: spec.msgProp },
|
|
1677
1685
|
'Replace CSN v0.1.0 value in $(PROP) by something specified' );
|
|
1678
1686
|
}
|
|
1679
1687
|
}
|
|
@@ -1703,7 +1711,7 @@ function pushLocation( obj ) {
|
|
|
1703
1711
|
else if (!loc || typeof loc !== 'string') {
|
|
1704
1712
|
if (loc)
|
|
1705
1713
|
dollarLocations.push( null ); // must match with popLocation()
|
|
1706
|
-
error( 'syntax-
|
|
1714
|
+
error( 'syntax-expected-object', location(true), { prop: '$location' } );
|
|
1707
1715
|
}
|
|
1708
1716
|
// hidden feature: string $location
|
|
1709
1717
|
const m = /:(\d+)(?::(\d+))?$/.exec( loc ); // extra '^'s at end deliberately left out
|
|
@@ -1816,7 +1824,7 @@ function parse( source, filename = 'csn.json', options = {}, messageFunctions )
|
|
|
1816
1824
|
line,
|
|
1817
1825
|
col: column,
|
|
1818
1826
|
};
|
|
1819
|
-
messageFunctions.error( 'syntax-
|
|
1827
|
+
messageFunctions.error( 'syntax-illegal-json', loc, { msg }, 'Illegal JSON: $(MSG)' );
|
|
1820
1828
|
return xsn;
|
|
1821
1829
|
}
|
|
1822
1830
|
}
|
package/lib/json/to-csn.js
CHANGED
|
@@ -222,7 +222,7 @@ const operators = {
|
|
|
222
222
|
unboundedFollowing: [ 'unbounded', 'following' ],
|
|
223
223
|
following: postfix( [ 'following' ] ),
|
|
224
224
|
frameBetween: exprs => [ 'between', ...exprs[0], 'and', ...exprs[1] ],
|
|
225
|
-
|
|
225
|
+
ixpr: exprs => [].concat( ...exprs ), // xpr extra, due to extra parentheses
|
|
226
226
|
};
|
|
227
227
|
|
|
228
228
|
const csnDictionaries = [
|
|
@@ -404,8 +404,6 @@ function usings( srcDict ) {
|
|
|
404
404
|
* @param {object} csn
|
|
405
405
|
* @param {object} model
|
|
406
406
|
*/
|
|
407
|
-
|
|
408
|
-
|
|
409
407
|
function extensions( node, csn, model ) {
|
|
410
408
|
if (model.kind && model.kind !== 'source')
|
|
411
409
|
return undefined;
|
|
@@ -727,7 +725,8 @@ function annotationsAndDocComment( node, annotated ) {
|
|
|
727
725
|
const val = node[prop];
|
|
728
726
|
// val.$priority isn't set for computed annotations like @Core.Computed
|
|
729
727
|
// and @odata.containment.ignore
|
|
730
|
-
|
|
728
|
+
// TODO: use $inferred instead special $priority value
|
|
729
|
+
if (val.$priority !== undefined && (!!val.$priority) === annotated) {
|
|
731
730
|
// transformer (= value) takes care to exclude $inferred annotation assignments
|
|
732
731
|
const sub = transformer( val );
|
|
733
732
|
// As value() just has one value, so we do not provide ( val, csn, node, prop )
|
|
@@ -1590,10 +1589,11 @@ function compactExpr( e ) { // TODO: options
|
|
|
1590
1589
|
*/
|
|
1591
1590
|
function initModuleVars( options = { csnFlavor: 'gensrc' } ) {
|
|
1592
1591
|
gensrcFlavor = options.parseCdl || options.csnFlavor === 'gensrc' ||
|
|
1593
|
-
|
|
1594
|
-
universalCsn = (options.csnFlavor === 'universal' ||
|
|
1595
|
-
|
|
1596
|
-
|
|
1592
|
+
( options.toCsn && options.toCsn.flavor === 'gensrc');
|
|
1593
|
+
universalCsn = ( options.csnFlavor === 'universal' ||
|
|
1594
|
+
( options.toCsn && options.toCsn.flavor === 'universal') ) &&
|
|
1595
|
+
isBetaEnabled( options, 'enableUniversalCsn' ) &&
|
|
1596
|
+
!options.parseCdl;
|
|
1597
1597
|
strictMode = options.testMode;
|
|
1598
1598
|
const proto = options.dictionaryPrototype;
|
|
1599
1599
|
// eslint-disable-next-line no-nested-ternary
|
|
@@ -1601,8 +1601,8 @@ function initModuleVars( options = { csnFlavor: 'gensrc' } ) {
|
|
|
1601
1601
|
? proto
|
|
1602
1602
|
: (proto) ? Object.prototype : null;
|
|
1603
1603
|
withLocations = options.withLocations;
|
|
1604
|
-
parensAsStrings = isDeprecatedEnabled( options, '
|
|
1605
|
-
projectionAsQuery = isDeprecatedEnabled( options, '
|
|
1604
|
+
parensAsStrings = isDeprecatedEnabled( options, '_parensAsStrings' );
|
|
1605
|
+
projectionAsQuery = isDeprecatedEnabled( options, '_projectionAsQuery' );
|
|
1606
1606
|
}
|
|
1607
1607
|
|
|
1608
1608
|
module.exports = {
|
|
@@ -13,8 +13,8 @@ const antlr4 = require('antlr4');
|
|
|
13
13
|
const { CompileMessage } = require('../base/messages');
|
|
14
14
|
const errorStrategy = require('./errorStrategy');
|
|
15
15
|
|
|
16
|
-
const Parser = require('../gen/languageParser').
|
|
17
|
-
const Lexer = require('../gen/languageLexer').
|
|
16
|
+
const Parser = require('../gen/languageParser').default;
|
|
17
|
+
const Lexer = require('../gen/languageLexer').default;
|
|
18
18
|
|
|
19
19
|
// Error listener used for ANTLR4-generated parser
|
|
20
20
|
class ErrorListener extends antlr4.error.ErrorListener {
|