@sap/cds-compiler 4.0.0 → 4.1.2
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 +115 -5
- package/bin/cdsc.js +12 -12
- package/doc/CHANGELOG_BETA.md +11 -0
- package/lib/api/main.js +60 -12
- package/lib/api/validate.js +1 -1
- package/lib/base/location.js +6 -7
- package/lib/base/message-registry.js +84 -38
- package/lib/base/messages.js +11 -10
- package/lib/base/model.js +6 -2
- package/lib/checks/defaultValues.js +6 -6
- package/lib/checks/foreignKeys.js +0 -5
- package/lib/checks/onConditions.js +17 -12
- package/lib/checks/queryNoDbArtifacts.js +132 -72
- package/lib/checks/sql-snippets.js +15 -4
- package/lib/checks/types.js +3 -3
- package/lib/checks/utils.js +1 -1
- package/lib/compiler/assert-consistency.js +44 -16
- package/lib/compiler/base.js +1 -0
- package/lib/compiler/builtins.js +7 -8
- package/lib/compiler/checks.js +274 -197
- package/lib/compiler/classes.js +62 -0
- package/lib/compiler/cycle-detector.js +3 -3
- package/lib/compiler/define.js +63 -50
- package/lib/compiler/extend.js +38 -20
- package/lib/compiler/finalize-parse-cdl.js +2 -1
- package/lib/compiler/generate.js +0 -8
- package/lib/compiler/index.js +9 -7
- package/lib/compiler/kick-start.js +2 -0
- package/lib/compiler/populate.js +139 -110
- package/lib/compiler/propagator.js +4 -3
- package/lib/compiler/resolve.js +157 -126
- package/lib/compiler/shared.js +706 -404
- package/lib/compiler/tweak-assocs.js +21 -10
- package/lib/compiler/utils.js +228 -36
- package/lib/edm/annotations/genericTranslation.js +30 -2
- package/lib/edm/edm.js +4 -1
- package/lib/edm/edmPreprocessor.js +12 -5
- package/lib/edm/edmUtils.js +2 -4
- package/lib/gen/Dictionary.json +34 -10
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +3987 -3963
- package/lib/json/from-csn.js +43 -47
- package/lib/json/to-csn.js +11 -11
- package/lib/language/antlrParser.js +2 -1
- package/lib/language/genericAntlrParser.js +52 -43
- package/lib/language/language.g4 +59 -59
- package/lib/language/multiLineStringParser.js +2 -0
- package/lib/main.d.ts +5 -0
- package/lib/model/csnRefs.js +37 -19
- package/lib/model/csnUtils.js +20 -16
- package/lib/model/revealInternalProperties.js +29 -21
- package/lib/model/sortViews.js +4 -2
- package/lib/modelCompare/compare.js +112 -39
- package/lib/modelCompare/utils/filter.js +54 -24
- package/lib/optionProcessor.js +6 -6
- package/lib/render/manageConstraints.js +20 -17
- package/lib/render/toCdl.js +34 -20
- package/lib/render/toHdbcds.js +2 -2
- package/lib/render/toRename.js +4 -9
- package/lib/render/toSql.js +77 -26
- package/lib/render/utils/common.js +3 -3
- package/lib/render/utils/unique.js +52 -0
- package/lib/transform/db/applyTransformations.js +61 -20
- package/lib/transform/db/assertUnique.js +7 -8
- package/lib/transform/db/associations.js +2 -2
- package/lib/transform/db/cdsPersistence.js +8 -8
- package/lib/transform/db/expansion.js +17 -21
- package/lib/transform/db/flattening.js +23 -23
- package/lib/transform/db/rewriteCalculatedElements.js +20 -14
- package/lib/transform/db/temporal.js +1 -1
- package/lib/transform/db/transformExists.js +8 -7
- package/lib/transform/db/views.js +73 -33
- package/lib/transform/draft/db.js +11 -9
- package/lib/transform/draft/odata.js +1 -1
- package/lib/transform/{forOdataNew.js → forOdata.js} +56 -42
- package/lib/transform/forRelationalDB.js +69 -75
- package/lib/transform/localized.js +6 -5
- package/lib/transform/odata/toFinalBaseType.js +3 -3
- package/lib/transform/{transformUtilsNew.js → transformUtils.js} +4 -101
- package/lib/transform/translateAssocsToJoins.js +14 -28
- package/package.json +1 -1
- package/share/messages/check-proper-type-of.md +1 -1
- package/share/messages/{check-proper-type.md → def-missing-type.md} +3 -5
- package/share/messages/message-explanations.json +1 -1
package/lib/json/from-csn.js
CHANGED
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
* @property {string[]} [xorGroups]
|
|
85
85
|
* Corresponding xor groups. It references a value of xorGroups. If set then only one property
|
|
86
86
|
* of the xorGroup may be set, e.g. if target is set, elements may not.
|
|
87
|
+
* If you are looking for a `notWith` (which should be symmetric), this is your property.
|
|
87
88
|
*
|
|
88
89
|
* @property {string} [xsnOp]
|
|
89
90
|
* Defines the operator to be used for XSN. Used for SET and SELECT. See queryTerm().
|
|
@@ -117,6 +118,7 @@
|
|
|
117
118
|
const { dictAdd } = require('../base/dictionaries');
|
|
118
119
|
const { quotedLiteralPatterns } = require('../compiler/builtins');
|
|
119
120
|
const { CompilerAssertion } = require('../base/error');
|
|
121
|
+
const { XsnSource, CsnLocation } = require('../compiler/classes');
|
|
120
122
|
|
|
121
123
|
const $location = Symbol.for('cds.$location');
|
|
122
124
|
|
|
@@ -144,20 +146,22 @@ const exprProperties = [
|
|
|
144
146
|
// Groups of properties which cannot be used together:
|
|
145
147
|
const xorGroups = {
|
|
146
148
|
// include CSN v0.1.0 properties here:
|
|
147
|
-
':type': [
|
|
149
|
+
':type': [
|
|
150
|
+
'target', 'targetAspect', 'elements', 'items', // xorException: target+targetAspect
|
|
151
|
+
'length', 'precision', 'scale', 'srid', // xorException: precision+scale
|
|
152
|
+
],
|
|
153
|
+
':enum': [ 'target', 'targetAspect', 'elements', 'enum', 'items' ],
|
|
148
154
|
':expr': [ // see also xorException property in schema
|
|
149
155
|
'ref', 'xpr', 'list', 'val', '#', 'func', 'SELECT', 'SET', 'expand',
|
|
150
156
|
'=', 'path', 'value', 'op', // '='/'path' is CSN v0.1.0 here
|
|
151
157
|
],
|
|
152
158
|
':col': [ 'expand', 'inline' ],
|
|
153
159
|
':ext': [ 'annotate', 'extend' ], // TODO: better msg for test/negative/UnexpectedProperties.csn
|
|
154
|
-
':assoc': [
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
':
|
|
159
|
-
':precision': [ 'elements', 'items', 'precision' ],
|
|
160
|
-
':scale': [ 'elements', 'items', 'scale' ],
|
|
160
|
+
':assoc': [
|
|
161
|
+
'on', 'keys',
|
|
162
|
+
'foreignKeys', 'onCond', // 'foreignKeys'/'onCond' is CSN v0.1.0
|
|
163
|
+
],
|
|
164
|
+
':on': [ 'on', 'default' ],
|
|
161
165
|
|
|
162
166
|
// TODO - improve consequential errors: assume no name given with `join` or `inline`?
|
|
163
167
|
as: [ 'as', 'join', 'inline' ],
|
|
@@ -272,13 +276,6 @@ const schema = compileSchema( {
|
|
|
272
276
|
'extend',
|
|
273
277
|
],
|
|
274
278
|
},
|
|
275
|
-
payload: { // keep it for a while, TODO: remove with v2 - at least warning
|
|
276
|
-
dictionaryOf: definition, // duplicate of line below only for better error message
|
|
277
|
-
type: renameTo( 'elements', dictionaryOf( definition ) ),
|
|
278
|
-
defaultKind: 'element',
|
|
279
|
-
validKinds: [],
|
|
280
|
-
inKind: [ 'event' ],
|
|
281
|
-
},
|
|
282
279
|
actions: {
|
|
283
280
|
dictionaryOf: actions,
|
|
284
281
|
defaultKind: 'action',
|
|
@@ -364,6 +361,7 @@ const schema = compileSchema( {
|
|
|
364
361
|
},
|
|
365
362
|
targetAspect: {
|
|
366
363
|
type: artifactRef,
|
|
364
|
+
xorException: 'target', // see xorGroup :type
|
|
367
365
|
msgVariant: 'or-object', // for 'syntax-expecting-string',
|
|
368
366
|
requires: 'elements',
|
|
369
367
|
optional: [ 'elements' ], // 'elements' for ad-hoc aspect compositions
|
|
@@ -371,6 +369,7 @@ const schema = compileSchema( {
|
|
|
371
369
|
},
|
|
372
370
|
target: {
|
|
373
371
|
type: artifactRef,
|
|
372
|
+
xorException: 'targetAspect', // see xorGroup :type
|
|
374
373
|
msgVariant: 'or-object', // for 'syntax-expecting-string',
|
|
375
374
|
requires: 'elements',
|
|
376
375
|
optional: [ 'elements' ], // 'elements' for ad-hoc COMPOSITION OF (gensrc style CSN)
|
|
@@ -398,10 +397,12 @@ const schema = compileSchema( {
|
|
|
398
397
|
},
|
|
399
398
|
precision: {
|
|
400
399
|
type: natnum,
|
|
400
|
+
xorException: 'scale', // see xorGroup :type
|
|
401
401
|
inKind: [ 'element', 'type', 'param', 'annotation', 'extend' ],
|
|
402
402
|
},
|
|
403
403
|
scale: {
|
|
404
404
|
type: scalenum,
|
|
405
|
+
xorException: 'precision', // see xorGroup :type
|
|
405
406
|
inKind: [ 'element', 'type', 'param', 'annotation', 'extend' ],
|
|
406
407
|
},
|
|
407
408
|
srid: {
|
|
@@ -990,15 +991,12 @@ function definition( def, spec, xsn, csn, name ) {
|
|
|
990
991
|
const kind0 = (spec.validKinds.length || spec.prop === 'extensions') && kind;
|
|
991
992
|
const csnProps = Object.keys( def );
|
|
992
993
|
|
|
993
|
-
//
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
def.type === undefined && def.elements === undefined) {
|
|
1000
|
-
r.$syntax = 'enum';
|
|
1001
|
-
kind = 'enum'; // for function expected()
|
|
994
|
+
// For compatibility, extension property `elements` could actually be an `enum`:
|
|
995
|
+
if (savedInExtensions === '' && prop === 'elements' && // in extend property `elements`
|
|
996
|
+
!Object.keys( def ).some( couldNotBeEnumProperty )) {
|
|
997
|
+
r.$syntax = 'enum'; // could be an enum
|
|
998
|
+
if (def.val !== undefined || def['#'] !== undefined)
|
|
999
|
+
kind = 'enum'; // for function expected(), i.e. allow property `val`/`#`
|
|
1002
1000
|
}
|
|
1003
1001
|
|
|
1004
1002
|
if (csnProps.length) {
|
|
@@ -1018,15 +1016,6 @@ function definition( def, spec, xsn, csn, name ) {
|
|
|
1018
1016
|
r.name = { id: name, location: r.location };
|
|
1019
1017
|
if (prop === 'columns' || prop === 'keys' || prop === 'foreignKeys')
|
|
1020
1018
|
r.name.$inferred = 'as';
|
|
1021
|
-
// TODO the following 'if' (if necessary) should be part of the core compiler
|
|
1022
|
-
if (prop === 'definitions' || prop === 'vocabularies') { // as spec property
|
|
1023
|
-
r.name = {
|
|
1024
|
-
absolute: name,
|
|
1025
|
-
id: name.substring( name.lastIndexOf('.') + 1 ),
|
|
1026
|
-
path: [ { id: name, location: r.location } ],
|
|
1027
|
-
location: r.location,
|
|
1028
|
-
};
|
|
1029
|
-
}
|
|
1030
1019
|
}
|
|
1031
1020
|
if (spec.requires)
|
|
1032
1021
|
onlyWith( spec, spec.requires, def, null, xor, () => true );
|
|
@@ -1054,6 +1043,13 @@ function definition( def, spec, xsn, csn, name ) {
|
|
|
1054
1043
|
}
|
|
1055
1044
|
}
|
|
1056
1045
|
|
|
1046
|
+
function couldNotBeEnumProperty( prop ) {
|
|
1047
|
+
// returns true for `value` (which we allow with warning when extending an enum with `elements`)
|
|
1048
|
+
const inKind = schema[prop]?.inKind; // undefined for annotations, $location, …
|
|
1049
|
+
// inKind for annotation assignments is function -> can be for enum
|
|
1050
|
+
return Array.isArray( inKind ) && inKind.includes( 'element' );
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1057
1053
|
function actions( def, spec, xsn, csn, name ) {
|
|
1058
1054
|
if (def.kind === 'extend' && (def.elements || def.enum)) {
|
|
1059
1055
|
// TODO: Handle this case in extend.js; already done for `returns`
|
|
@@ -1472,7 +1468,7 @@ function annoValue( val, spec ) {
|
|
|
1472
1468
|
function annotation( val, spec, xsn, csn, name ) {
|
|
1473
1469
|
const absolute = (xsn ? name.substring(1) : name);
|
|
1474
1470
|
// TODO: really care about variant (qualifier parts)?
|
|
1475
|
-
const variantIndex = absolute.indexOf('#') + 1 || absolute.length;
|
|
1471
|
+
const variantIndex = absolute.indexOf('#') + 1 || absolute.length; // including '#'
|
|
1476
1472
|
const n = refSplit( absolute.substring( 0, variantIndex ), !xsn && '{}' );
|
|
1477
1473
|
if (!n)
|
|
1478
1474
|
return undefined;
|
|
@@ -1941,7 +1937,8 @@ function replaceZeroValue( spec, msgVariant, newValue ) {
|
|
|
1941
1937
|
*/
|
|
1942
1938
|
function location( enforceJsonPos ) {
|
|
1943
1939
|
return !enforceJsonPos && dollarLocations.length &&
|
|
1944
|
-
|
|
1940
|
+
dollarLocations[dollarLocations.length - 1] || {
|
|
1941
|
+
__proto__: CsnLocation.prototype,
|
|
1945
1942
|
file: csnFilename,
|
|
1946
1943
|
line: virtualLine,
|
|
1947
1944
|
col: 0,
|
|
@@ -1954,7 +1951,7 @@ function pushLocation( obj ) {
|
|
|
1954
1951
|
if (loc === undefined)
|
|
1955
1952
|
return;
|
|
1956
1953
|
if (loc && typeof loc === 'object' && !Array.isArray( loc )) {
|
|
1957
|
-
dollarLocations.push( loc.line ? loc : null );
|
|
1954
|
+
dollarLocations.push( loc.line ? { __proto__: CsnLocation.prototype, ...loc } : null );
|
|
1958
1955
|
return;
|
|
1959
1956
|
}
|
|
1960
1957
|
else if (!loc || typeof loc !== 'string') {
|
|
@@ -1970,10 +1967,9 @@ function pushLocation( obj ) {
|
|
|
1970
1967
|
else {
|
|
1971
1968
|
const line = Number( m[1] );
|
|
1972
1969
|
const column = m[2] && Number( m[2] ) || 0;
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
line,
|
|
1976
|
-
col: column,
|
|
1970
|
+
const file = loc.substring( 0, m.index );
|
|
1971
|
+
dollarLocations.push({
|
|
1972
|
+
__proto__: CsnLocation.prototype, file, line, col: column,
|
|
1977
1973
|
} );
|
|
1978
1974
|
}
|
|
1979
1975
|
}
|
|
@@ -2011,7 +2007,8 @@ function toXsn( csn, filename, options, messageFunctions ) {
|
|
|
2011
2007
|
inExtensions = null;
|
|
2012
2008
|
vocabInDefinitions = null;
|
|
2013
2009
|
|
|
2014
|
-
const xsn =
|
|
2010
|
+
const xsn = new XsnSource();
|
|
2011
|
+
xsn.$frontend = 'json';
|
|
2015
2012
|
|
|
2016
2013
|
// eslint-disable-next-line object-curly-newline
|
|
2017
2014
|
({ message, error, warning, info } = messageFunctions);
|
|
@@ -2050,7 +2047,7 @@ function parse( source, filename = 'csn.json', options = {}, messageFunctions =
|
|
|
2050
2047
|
resetHeapModuleVars();
|
|
2051
2048
|
if (!(e instanceof SyntaxError))
|
|
2052
2049
|
throw e;
|
|
2053
|
-
const xsn =
|
|
2050
|
+
const xsn = new XsnSource();
|
|
2054
2051
|
const msg = e.message;
|
|
2055
2052
|
const p = /in JSON at position ([0-9]+)/.exec( msg );
|
|
2056
2053
|
let line = 1;
|
|
@@ -2067,12 +2064,11 @@ function parse( source, filename = 'csn.json', options = {}, messageFunctions =
|
|
|
2067
2064
|
}
|
|
2068
2065
|
column = end - eol + 1;
|
|
2069
2066
|
}
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
file: filename,
|
|
2067
|
+
const loc = new CsnLocation(
|
|
2068
|
+
filename,
|
|
2073
2069
|
line,
|
|
2074
|
-
|
|
2075
|
-
|
|
2070
|
+
column
|
|
2071
|
+
);
|
|
2076
2072
|
messageFunctions.error( 'syntax-invalid-json', loc, { msg },
|
|
2077
2073
|
'Invalid JSON: $(MSG)' );
|
|
2078
2074
|
return xsn;
|
package/lib/json/to-csn.js
CHANGED
|
@@ -335,7 +335,8 @@ function compactModel( model, options = model.options || {} ) {
|
|
|
335
335
|
break;
|
|
336
336
|
}
|
|
337
337
|
set( 'definitions', csn, model );
|
|
338
|
-
|
|
338
|
+
if (Object.keys(model.vocabularies || {}).length > 0)
|
|
339
|
+
set( 'vocabularies', csn, model );
|
|
339
340
|
const exts = extensions( model.extensions || [], csn, model );
|
|
340
341
|
if (exts && exts.length)
|
|
341
342
|
csn.extensions = exts;
|
|
@@ -493,10 +494,12 @@ function standard( node ) {
|
|
|
493
494
|
// XSN input node, not the CSN result node. Not really an issue...
|
|
494
495
|
const keys = Object.keys( node ).sort( compareProperties );
|
|
495
496
|
for (const prop of keys) {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
497
|
+
if (node[prop] !== undefined) {
|
|
498
|
+
const transformer = transformers[prop] || transformers[prop.charAt(0)] || unexpected;
|
|
499
|
+
const sub = transformer( node[prop], csn, node, prop );
|
|
500
|
+
if (sub !== undefined)
|
|
501
|
+
csn[prop] = sub;
|
|
502
|
+
}
|
|
500
503
|
}
|
|
501
504
|
return csn;
|
|
502
505
|
}
|
|
@@ -715,14 +718,12 @@ function actions( dict, _csn, node ) {
|
|
|
715
718
|
const keys = Object.keys( dict );
|
|
716
719
|
if (strictMode && node.kind === 'annotate')
|
|
717
720
|
keys.sort(); // TODO: always sort with --test-mode ?
|
|
718
|
-
return (keys
|
|
719
|
-
? dictionary( dict, keys, 'actions' )
|
|
720
|
-
: undefined;
|
|
721
|
+
return dictionary( dict, keys, 'actions' );
|
|
721
722
|
}
|
|
722
723
|
|
|
723
724
|
function params( dict ) {
|
|
724
725
|
const keys = Object.keys( dict );
|
|
725
|
-
return (keys.length)
|
|
726
|
+
return (keys.length) // TODO: still?
|
|
726
727
|
? insertOrderDict( dict )
|
|
727
728
|
: undefined;
|
|
728
729
|
}
|
|
@@ -1212,8 +1213,7 @@ function value( node ) {
|
|
|
1212
1213
|
function enumValueOrCalc( v, csn, node ) {
|
|
1213
1214
|
if (v.$inferred && (universalCsn || gensrcFlavor))
|
|
1214
1215
|
return undefined;
|
|
1215
|
-
// Enums
|
|
1216
|
-
// In v4, we don't check `node.$syntax === 'enum'` anymore.
|
|
1216
|
+
// Enums values in CSN are without outer `value: { … }`:
|
|
1217
1217
|
if (node.kind === 'enum') {
|
|
1218
1218
|
Object.assign( csn, expression( v ) );
|
|
1219
1219
|
}
|
|
@@ -12,6 +12,7 @@ const antlr4 = require('antlr4');
|
|
|
12
12
|
|
|
13
13
|
const { CompileMessage } = require('../base/messages');
|
|
14
14
|
const errorStrategy = require('./errorStrategy');
|
|
15
|
+
const { XsnSource } = require('../compiler/classes');
|
|
15
16
|
|
|
16
17
|
const Parser = require('../gen/languageParser').default;
|
|
17
18
|
const Lexer = require('../gen/languageLexer').default;
|
|
@@ -167,7 +168,7 @@ function parse( source, filename = '<undefined>.cds',
|
|
|
167
168
|
throw e;
|
|
168
169
|
}
|
|
169
170
|
}
|
|
170
|
-
const ast = tree && tree[rulespec.returns] ||
|
|
171
|
+
const ast = tree && tree[rulespec.returns] || new XsnSource();
|
|
171
172
|
ast.options = options;
|
|
172
173
|
if (rulespec.$frontend)
|
|
173
174
|
ast.$frontend = rulespec.$frontend;
|
|
@@ -18,6 +18,9 @@ const {
|
|
|
18
18
|
quotedLiteralPatterns,
|
|
19
19
|
} = require('../compiler/builtins');
|
|
20
20
|
const { pathName } = require('../compiler/utils');
|
|
21
|
+
const {
|
|
22
|
+
XsnArtifact, XsnName, CsnLocation, XsnSource,
|
|
23
|
+
} = require('../compiler/classes');
|
|
21
24
|
const { isBetaEnabled } = require('../base/model');
|
|
22
25
|
const { weakLocation } = require('../base/messages');
|
|
23
26
|
const { normalizeNewLine } = require('./textUtils');
|
|
@@ -110,7 +113,6 @@ Object.assign(GenericAntlrParser.prototype, {
|
|
|
110
113
|
addDef,
|
|
111
114
|
addItem,
|
|
112
115
|
addExtension,
|
|
113
|
-
aspectWithoutElements,
|
|
114
116
|
createSource,
|
|
115
117
|
createDict,
|
|
116
118
|
createArray,
|
|
@@ -139,6 +141,8 @@ Object.assign(GenericAntlrParser.prototype, {
|
|
|
139
141
|
prepareGenericKeywords,
|
|
140
142
|
reportErrorForGenericKeyword,
|
|
141
143
|
parseMultiLineStringLiteral,
|
|
144
|
+
XsnArtifact,
|
|
145
|
+
XsnName,
|
|
142
146
|
});
|
|
143
147
|
|
|
144
148
|
// Use the following function for language constructs which we (currently)
|
|
@@ -160,7 +164,13 @@ function csnParseOnly( msgId, tokens, textArgs ) {
|
|
|
160
164
|
this.error( msgId, loc, textArgs );
|
|
161
165
|
}
|
|
162
166
|
|
|
163
|
-
/**
|
|
167
|
+
/**
|
|
168
|
+
* Do not propose a `;` or closing brace `}` at this position.
|
|
169
|
+
*
|
|
170
|
+
* Attention: May conflict with excludeExpected()!
|
|
171
|
+
*
|
|
172
|
+
* @this {object}
|
|
173
|
+
* */
|
|
164
174
|
function noSemicolonHere() {
|
|
165
175
|
const handler = this._errHandler;
|
|
166
176
|
const t = this.getCurrentToken();
|
|
@@ -173,10 +183,21 @@ function noSemicolonHere() {
|
|
|
173
183
|
handler.reportIgnoredWith( this, t );
|
|
174
184
|
}
|
|
175
185
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Using this function "during ATN decision making" has no effect
|
|
188
|
+
* In front of an ATN decision, you might specify dedicated excludes
|
|
189
|
+
* for non-LA1 tokens via a sub-array in excludes[0].
|
|
190
|
+
* TODO: consider $nextTokens…, see commented use in rule `elementProperties`
|
|
191
|
+
*
|
|
192
|
+
* Usage Note:
|
|
193
|
+
* Must be used at all positions where sync() is called in the generated coding.
|
|
194
|
+
* ```antlr4
|
|
195
|
+
* { this.excludeExpected(['ACTIONS']); }
|
|
196
|
+
* ( WITH { this.excludeExpected(['ACTIONS']); } )?
|
|
197
|
+
* annotationAssignment_ll1[ $art ]* { this.excludeExpected(['ACTIONS']); }
|
|
198
|
+
* ACTIONS
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
180
201
|
function excludeExpected( excludes ) {
|
|
181
202
|
if (excludes) {
|
|
182
203
|
// @ts-ignore
|
|
@@ -414,6 +435,12 @@ function checkExtensionDict( dict ) {
|
|
|
414
435
|
def[prop] = dup[prop]; // continuation semantics: last wins
|
|
415
436
|
}
|
|
416
437
|
}
|
|
438
|
+
if (dup.$annotations) { // update deprecated $annotations for cds-lsp / annotation modeler
|
|
439
|
+
if (def.$annotations)
|
|
440
|
+
def.$annotations.push( ...dup.$annotations );
|
|
441
|
+
else
|
|
442
|
+
def.$annotations = dup.$annotations;
|
|
443
|
+
}
|
|
417
444
|
}
|
|
418
445
|
def.$duplicates = null;
|
|
419
446
|
}
|
|
@@ -445,14 +472,14 @@ function handleDuplicateExtension( ext, name, numDefines ) {
|
|
|
445
472
|
* Return start location of `token`, or the first token matched by the current
|
|
446
473
|
* rule if `token` is undefined
|
|
447
474
|
*
|
|
448
|
-
* @returns {
|
|
475
|
+
* @returns {CsnLocation}
|
|
449
476
|
*/
|
|
450
477
|
function startLocation( token = this._ctx.start ) {
|
|
451
|
-
return
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
478
|
+
return new CsnLocation(
|
|
479
|
+
this.filename,
|
|
480
|
+
token.line,
|
|
481
|
+
token.column + 1
|
|
482
|
+
);
|
|
456
483
|
}
|
|
457
484
|
|
|
458
485
|
/**
|
|
@@ -461,7 +488,7 @@ function startLocation( token = this._ctx.start ) {
|
|
|
461
488
|
*
|
|
462
489
|
* @param {object} token
|
|
463
490
|
* @param {object} endToken
|
|
464
|
-
* @return {
|
|
491
|
+
* @return {CsnLocation}
|
|
465
492
|
*/
|
|
466
493
|
function tokenLocation( token, endToken = null ) {
|
|
467
494
|
if (!token)
|
|
@@ -469,16 +496,11 @@ function tokenLocation( token, endToken = null ) {
|
|
|
469
496
|
if (!endToken) // including null
|
|
470
497
|
endToken = token;
|
|
471
498
|
|
|
472
|
-
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
// Default for single line tokens
|
|
478
|
-
endLine: endToken.line,
|
|
479
|
-
// after the last char (special for EOF?)
|
|
480
|
-
endCol: endToken.stop - endToken.start + endToken.column + 2,
|
|
481
|
-
};
|
|
499
|
+
// Default for single line tokens
|
|
500
|
+
const endLine = endToken.line;
|
|
501
|
+
// after the last char (special for EOF?)
|
|
502
|
+
const endCol = endToken.stop - endToken.start + endToken.column + 2;
|
|
503
|
+
const loc = new CsnLocation( this.filename, token.line, token.column + 1, endLine, endCol );
|
|
482
504
|
|
|
483
505
|
// This check is done for performance reason. No need to access a token's
|
|
484
506
|
// data if we know that it spans only one single line.
|
|
@@ -579,7 +601,7 @@ function secureParens( expr ) {
|
|
|
579
601
|
return {
|
|
580
602
|
op: { val: 'xpr', location: this.startLocation() },
|
|
581
603
|
args: [ expr ],
|
|
582
|
-
location: { ...expr.location },
|
|
604
|
+
location: { __proto__: CsnLocation.prototype, ...expr.location },
|
|
583
605
|
$parens,
|
|
584
606
|
};
|
|
585
607
|
}
|
|
@@ -733,7 +755,11 @@ function argsExpression( args, nary, location ) {
|
|
|
733
755
|
val, // there is no n-ary in rule conditionTerm
|
|
734
756
|
location: this.startLocation(),
|
|
735
757
|
};
|
|
736
|
-
return this.attachLocation( {
|
|
758
|
+
return this.attachLocation( {
|
|
759
|
+
op,
|
|
760
|
+
args,
|
|
761
|
+
location: location && { __proto__: CsnLocation.prototype, ...location },
|
|
762
|
+
} );
|
|
737
763
|
}
|
|
738
764
|
|
|
739
765
|
function pushXprToken( args ) {
|
|
@@ -1097,16 +1123,6 @@ function addExtension( ext, parent, kind, artName, elemPath ) {
|
|
|
1097
1123
|
}
|
|
1098
1124
|
}
|
|
1099
1125
|
|
|
1100
|
-
function aspectWithoutElements( art ) {
|
|
1101
|
-
// Empty dictionary to allow element extensions. NO, please NO empty dict.
|
|
1102
|
-
// TODO: Checking it here does not prevent aspect in CSN input having no elements!
|
|
1103
|
-
art.elements = this.createDict();
|
|
1104
|
-
if (!isBetaEnabled( this.options, 'aspectWithoutElements' )) {
|
|
1105
|
-
this.error( null, [ art.name.location, null ], {},
|
|
1106
|
-
'Aspects without elements are not supported, yet' );
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
1126
|
// must be in action directly after having parsed '{', '(`, or a keyword before
|
|
1111
1127
|
function createDict() {
|
|
1112
1128
|
const dict = Object.create(null);
|
|
@@ -1132,14 +1148,7 @@ function finalizeDictOrArray( dict ) {
|
|
|
1132
1148
|
}
|
|
1133
1149
|
|
|
1134
1150
|
function createSource() {
|
|
1135
|
-
return
|
|
1136
|
-
kind: 'source',
|
|
1137
|
-
usings: [],
|
|
1138
|
-
dependencies: [],
|
|
1139
|
-
artifacts: Object.create(null),
|
|
1140
|
-
// vocabularies: Object.create(null),
|
|
1141
|
-
extensions: [],
|
|
1142
|
-
};
|
|
1151
|
+
return new XsnSource();
|
|
1143
1152
|
}
|
|
1144
1153
|
|
|
1145
1154
|
// Create AST node for prefix operator `op` and arguments `args`
|