@sap/cds-compiler 3.1.2 → 3.4.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 +101 -3
- package/bin/cdsc.js +4 -2
- package/doc/CHANGELOG_BETA.md +35 -0
- package/lib/api/main.js +153 -29
- package/lib/api/validate.js +8 -3
- package/lib/base/dictionaries.js +6 -6
- package/lib/base/error.js +2 -2
- package/lib/base/keywords.js +106 -24
- package/lib/base/message-registry.js +177 -79
- package/lib/base/messages.js +78 -57
- package/lib/base/model.js +2 -1
- package/lib/checks/actionsFunctions.js +1 -1
- package/lib/checks/annotationsOData.js +2 -2
- package/lib/checks/arrayOfs.js +15 -7
- package/lib/checks/cdsPersistence.js +1 -1
- package/lib/checks/checkForTypes.js +53 -0
- package/lib/checks/defaultValues.js +4 -2
- package/lib/checks/elements.js +81 -6
- package/lib/checks/foreignKeys.js +12 -13
- package/lib/checks/invalidTarget.js +10 -11
- package/lib/checks/managedInType.js +21 -15
- package/lib/checks/nullableKeys.js +1 -1
- package/lib/checks/onConditions.js +9 -9
- package/lib/checks/parameters.js +23 -0
- package/lib/checks/queryNoDbArtifacts.js +1 -1
- package/lib/checks/selectItems.js +1 -1
- package/lib/checks/sql-snippets.js +12 -10
- package/lib/checks/types.js +2 -2
- package/lib/checks/utils.js +17 -7
- package/lib/checks/validator.js +36 -14
- package/lib/compiler/assert-consistency.js +21 -13
- package/lib/compiler/builtins.js +8 -0
- package/lib/compiler/checks.js +57 -40
- package/lib/compiler/define.js +139 -69
- package/lib/compiler/extend.js +319 -50
- package/lib/compiler/finalize-parse-cdl.js +14 -9
- package/lib/compiler/kick-start.js +2 -35
- package/lib/compiler/populate.js +111 -68
- package/lib/compiler/propagator.js +5 -3
- package/lib/compiler/resolve.js +71 -108
- package/lib/compiler/shared.js +82 -54
- package/lib/compiler/tweak-assocs.js +26 -14
- package/lib/compiler/utils.js +13 -2
- package/lib/edm/annotations/genericTranslation.js +10 -7
- package/lib/edm/csn2edm.js +11 -11
- package/lib/edm/edm.js +17 -9
- package/lib/edm/edmPreprocessor.js +53 -30
- package/lib/edm/edmUtils.js +7 -2
- package/lib/gen/Dictionary.json +14 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +3 -2
- package/lib/gen/languageParser.js +4312 -4186
- package/lib/inspect/inspectModelStatistics.js +1 -1
- package/lib/inspect/inspectPropagation.js +23 -9
- package/lib/json/csnVersion.js +13 -13
- package/lib/json/from-csn.js +161 -172
- package/lib/json/to-csn.js +70 -10
- package/lib/language/.eslintrc.json +4 -0
- package/lib/language/antlrParser.js +8 -11
- package/lib/language/docCommentParser.js +1 -2
- package/lib/language/errorStrategy.js +54 -27
- package/lib/language/genericAntlrParser.js +140 -93
- package/lib/language/language.g4 +57 -33
- package/lib/language/multiLineStringParser.js +75 -63
- package/lib/main.d.ts +3 -6
- package/lib/main.js +1 -0
- package/lib/model/.eslintrc.json +13 -0
- package/lib/model/api.js +4 -2
- package/lib/model/csnRefs.js +78 -50
- package/lib/model/csnUtils.js +272 -222
- package/lib/model/enrichCsn.js +41 -31
- package/lib/model/revealInternalProperties.js +61 -57
- package/lib/model/sortViews.js +35 -31
- package/lib/modelCompare/compare.js +52 -18
- package/lib/modelCompare/filter.js +83 -0
- package/lib/optionProcessor.js +10 -1
- package/lib/render/manageConstraints.js +11 -7
- package/lib/render/toCdl.js +151 -106
- package/lib/render/toHdbcds.js +8 -6
- package/lib/render/toRename.js +4 -4
- package/lib/render/toSql.js +17 -7
- package/lib/render/utils/common.js +27 -9
- package/lib/render/utils/sql.js +5 -5
- package/lib/sql-identifier.js +7 -0
- package/lib/transform/db/applyTransformations.js +32 -3
- package/lib/transform/db/assertUnique.js +27 -38
- package/lib/transform/db/expansion.js +92 -41
- package/lib/transform/db/flattening.js +1 -1
- package/lib/transform/db/temporal.js +3 -1
- package/lib/transform/db/transformExists.js +8 -2
- package/lib/transform/db/views.js +42 -13
- package/lib/transform/draft/db.js +2 -2
- package/lib/transform/forOdataNew.js +10 -7
- package/lib/transform/{forHanaNew.js → forRelationalDB.js} +18 -12
- package/lib/transform/localized.js +29 -20
- package/lib/transform/odata/toFinalBaseType.js +8 -11
- package/lib/transform/odata/typesExposure.js +2 -1
- package/lib/transform/parseExpr.js +245 -0
- package/lib/transform/transformUtilsNew.js +122 -51
- package/lib/transform/translateAssocsToJoins.js +17 -16
- package/lib/utils/moduleResolve.js +5 -5
- package/lib/utils/objectUtils.js +3 -3
- package/lib/utils/term.js +5 -5
- package/package.json +2 -2
- package/share/messages/anno-duplicate-unrelated-layer.md +6 -6
- package/share/messages/check-proper-type-of.md +4 -4
- package/share/messages/check-proper-type.md +2 -2
- package/share/messages/duplicate-autoexposed.md +4 -4
- package/share/messages/extend-repeated-intralayer.md +4 -5
- package/share/messages/extend-unrelated-layer.md +4 -4
- package/share/messages/message-explanations.json +3 -1
- package/share/messages/redirected-to-ambiguous.md +7 -6
- package/share/messages/redirected-to-complex.md +63 -0
- package/share/messages/redirected-to-unrelated.md +6 -5
- package/share/messages/rewrite-not-supported.md +4 -4
- package/share/messages/{syntax-expected-integer.md → syntax-expecting-integer.md} +4 -4
- package/share/messages/wildcard-excluding-one.md +37 -0
package/lib/json/to-csn.js
CHANGED
|
@@ -186,7 +186,7 @@ const propertyOrder = (function orderPositions() {
|
|
|
186
186
|
const typeProperties = [
|
|
187
187
|
'target', 'elements', 'enum', 'items',
|
|
188
188
|
'cardinality', // for association publishing in views
|
|
189
|
-
'type', 'length', 'precision', 'scale', 'srid', 'localized',
|
|
189
|
+
'type', 'length', 'precision', 'scale', 'srid', 'localized', 'notNull',
|
|
190
190
|
'foreignKeys', 'on', // for explicit ON/keys with REDIRECTED
|
|
191
191
|
];
|
|
192
192
|
|
|
@@ -252,9 +252,10 @@ function sortCsn( csn, cloneOptions = false ) {
|
|
|
252
252
|
const sortDict = n === 'definitions' &&
|
|
253
253
|
(!cloneOptions || cloneOptions.testMode || cloneOptions.testSortCsn);
|
|
254
254
|
const val = csn[n];
|
|
255
|
-
if (!val || typeof val !== 'object' ||
|
|
255
|
+
if (!val || typeof val !== 'object' || csnDirectValues.includes(n))
|
|
256
256
|
r[n] = val;
|
|
257
|
-
|
|
257
|
+
else if (n.charAt(0) === '@')
|
|
258
|
+
r[n] = cloneAnnotationValue( val );
|
|
258
259
|
else if (csnDictionaries.includes(n) && !Array.isArray(val))
|
|
259
260
|
// Array check for property `args` which may either be a dictionary or an array.
|
|
260
261
|
r[n] = csnDictionary( val, sortDict, cloneOptions );
|
|
@@ -279,6 +280,12 @@ function sortCsn( csn, cloneOptions = false ) {
|
|
|
279
280
|
return r;
|
|
280
281
|
}
|
|
281
282
|
|
|
283
|
+
function cloneAnnotationValue(val) {
|
|
284
|
+
if (typeof val !== 'object') // scalar
|
|
285
|
+
return val;
|
|
286
|
+
return JSON.parse( JSON.stringify( val ) );
|
|
287
|
+
}
|
|
288
|
+
|
|
282
289
|
/**
|
|
283
290
|
* Check whether the given object has non enumerable property.
|
|
284
291
|
* Ensure that we don't take it from the prototype, only "directly" - we accidentally
|
|
@@ -663,7 +670,9 @@ function elements( dict, csn, node ) {
|
|
|
663
670
|
// no 'elements' with SELECT or inferred elements with gensrc;
|
|
664
671
|
// hidden or visible 'elements' will be set in query()
|
|
665
672
|
return undefined;
|
|
666
|
-
|
|
673
|
+
if (dict !== 0)
|
|
674
|
+
return insertOrderDict( dict );
|
|
675
|
+
return undefined;
|
|
667
676
|
}
|
|
668
677
|
|
|
669
678
|
function enumDict( dict, csn, node ) {
|
|
@@ -873,7 +882,24 @@ function definition( art, _csn, _node, prop ) {
|
|
|
873
882
|
return c;
|
|
874
883
|
}
|
|
875
884
|
|
|
876
|
-
|
|
885
|
+
/**
|
|
886
|
+
* Create $origin specification for query/projection.
|
|
887
|
+
*/
|
|
888
|
+
function queryOrigin( xsn ) {
|
|
889
|
+
const source = xsn._from[0]._origin;
|
|
890
|
+
let $origin;
|
|
891
|
+
if (xsn.includes)
|
|
892
|
+
// includesOrigin() does originRef() on the first include.
|
|
893
|
+
// Use it to behave the same as entity includes.
|
|
894
|
+
$origin = includesOrigin( [ { _artifact: source }, ...xsn.includes ], xsn );
|
|
895
|
+
else
|
|
896
|
+
$origin = originRef( source );
|
|
897
|
+
return $origin;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
/**
|
|
901
|
+
* Create $origin specification for `includes` of `art`.
|
|
902
|
+
*/
|
|
877
903
|
function includesOrigin( includes, art ) {
|
|
878
904
|
const $origin = originRef( includes[0]._artifact );
|
|
879
905
|
if (includes.length === 1)
|
|
@@ -913,7 +939,7 @@ function addOrigin( csn, xsn, node ) {
|
|
|
913
939
|
}
|
|
914
940
|
if (xsn._from) {
|
|
915
941
|
const source = xsn._from[0]._origin;
|
|
916
|
-
csn.$origin =
|
|
942
|
+
csn.$origin = queryOrigin( xsn );
|
|
917
943
|
if (source.params && !xsn.params)
|
|
918
944
|
csn.params = null; // discontinue `params` inheritance
|
|
919
945
|
if (source.actions && !xsn.actions)
|
|
@@ -927,6 +953,11 @@ function addOrigin( csn, xsn, node ) {
|
|
|
927
953
|
let origin = getOrigin( node );
|
|
928
954
|
if (xsn.$inferred === 'composition-entity') {
|
|
929
955
|
csn.$origin = originRef( origin, xsn );
|
|
956
|
+
inferredPropertiesForOrigin( csn, node );
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
else if (xsn.$inferred === 'localized-entity') {
|
|
960
|
+
inferredPropertiesForOrigin( csn, node );
|
|
930
961
|
return;
|
|
931
962
|
}
|
|
932
963
|
else if (!isMember( xsn ) || xsn.kind === 'select') {
|
|
@@ -993,6 +1024,30 @@ function addOrigin( csn, xsn, node ) {
|
|
|
993
1024
|
}
|
|
994
1025
|
}
|
|
995
1026
|
|
|
1027
|
+
/**
|
|
1028
|
+
* Copy properties with $inferred === 'parent-origin' to $origin.
|
|
1029
|
+
* This indicates that the property is neither direct nor can be inferred through $origin.
|
|
1030
|
+
*
|
|
1031
|
+
* @param csn
|
|
1032
|
+
* @param node
|
|
1033
|
+
*/
|
|
1034
|
+
function inferredPropertiesForOrigin( csn, node ) {
|
|
1035
|
+
let hasProp = false;
|
|
1036
|
+
const props = {};
|
|
1037
|
+
for (const prop of Object.keys(node)) {
|
|
1038
|
+
if (node[prop]?.$inferred === 'parent-origin') {
|
|
1039
|
+
hasProp = true;
|
|
1040
|
+
props[prop] = value({ ...node[prop], $inferred: false });
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
const origin = csn.$origin;
|
|
1044
|
+
if (hasProp) {
|
|
1045
|
+
csn.$origin = props;
|
|
1046
|
+
if (origin)
|
|
1047
|
+
csn.$origin.$origin = origin;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
996
1051
|
function getParent( art ) {
|
|
997
1052
|
const parent = art._parent;
|
|
998
1053
|
const main = parent._main;
|
|
@@ -1021,10 +1076,11 @@ function getOrigin( art ) {
|
|
|
1021
1076
|
return (_origin.kind === 'builtin') ? undefined : _origin; // not $dollarVariable
|
|
1022
1077
|
if (hasExplicitProp( art.type, 'cast' ))
|
|
1023
1078
|
return art.type._artifact;
|
|
1024
|
-
if (art.includes)
|
|
1025
|
-
return art.includes[0]._artifact;
|
|
1026
1079
|
if (art._from)
|
|
1027
1080
|
return art._from[0]._origin;
|
|
1081
|
+
// must come after _from, since queries can have includes as well.
|
|
1082
|
+
if (art.includes)
|
|
1083
|
+
return art.includes[0]._artifact;
|
|
1028
1084
|
return undefined;
|
|
1029
1085
|
}
|
|
1030
1086
|
|
|
@@ -1092,7 +1148,9 @@ function type( node, csn, xsn ) {
|
|
|
1092
1148
|
return undefined;
|
|
1093
1149
|
if (xsn._origin) {
|
|
1094
1150
|
if (xsn._origin.$inferred === 'REDIRECTED') { // auto-redirected user-provided target
|
|
1095
|
-
|
|
1151
|
+
const $origin = definition( xsn._origin );
|
|
1152
|
+
if ($origin) // if not rendered as column
|
|
1153
|
+
csn.$origin = $origin;
|
|
1096
1154
|
}
|
|
1097
1155
|
}
|
|
1098
1156
|
return artifactRef( node, !node.$extra );
|
|
@@ -1210,7 +1268,8 @@ function value( node ) {
|
|
|
1210
1268
|
if (!node)
|
|
1211
1269
|
return true; // `@aBool` short for `@aBool: true`
|
|
1212
1270
|
if (universalCsn && node.$inferred) {
|
|
1213
|
-
if (node.$inferred === 'prop' || node.$inferred === '$generated'
|
|
1271
|
+
if (node.$inferred === 'prop' || node.$inferred === '$generated' || // via propagator.js
|
|
1272
|
+
node.$inferred === 'parent-origin')
|
|
1214
1273
|
return undefined;
|
|
1215
1274
|
else if (node.$inferred === 'NULL')
|
|
1216
1275
|
return null;
|
|
@@ -1610,6 +1669,7 @@ function initModuleVars( options = { csnFlavor: 'gensrc' } ) {
|
|
|
1610
1669
|
|
|
1611
1670
|
module.exports = {
|
|
1612
1671
|
cloneCsnDictionary: (csn, options) => csnDictionary(csn, false, options),
|
|
1672
|
+
cloneAnnotationValue,
|
|
1613
1673
|
compactModel,
|
|
1614
1674
|
compactQuery,
|
|
1615
1675
|
compactExpr,
|
|
@@ -18,22 +18,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 {
|
|
21
|
-
constructor(...args) {
|
|
22
|
-
super(...args);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
21
|
// method which is called by generated parser with --trace-parser[-amg]:
|
|
22
|
+
// eslint-disable-next-line class-methods-use-this
|
|
26
23
|
syntaxError( recognizer, offendingSymbol, line, column, msg, e ) {
|
|
27
24
|
if (!(e instanceof CompileMessage)) // not already reported
|
|
28
|
-
|
|
25
|
+
// Ignore warning, because only relevant for --trace-parser
|
|
26
|
+
// eslint-disable-next-line cds-compiler/message-call-format
|
|
27
|
+
recognizer.error( null, offendingSymbol, {}, msg );
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
class RewriteTypeTokenStream extends antlr4.CommonTokenStream {
|
|
33
|
-
constructor(...args) {
|
|
34
|
-
super(...args);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
32
|
LT( k ) {
|
|
38
33
|
const t = super.LT(k);
|
|
39
34
|
if (!t || !t.type)
|
|
@@ -112,7 +107,9 @@ const rules = {
|
|
|
112
107
|
expr: { func: 'conditionEOF', returns: 'cond' }, // yes, condition
|
|
113
108
|
};
|
|
114
109
|
|
|
115
|
-
function parse( source, filename = '<undefined>.cds',
|
|
110
|
+
function parse( source, filename = '<undefined>.cds',
|
|
111
|
+
options = {}, messageFunctions = null,
|
|
112
|
+
rule = 'cdl' ) {
|
|
116
113
|
const lexer = new Lexer( new antlr4.InputStream(source) );
|
|
117
114
|
const tokenStream = new RewriteTypeTokenStream(lexer);
|
|
118
115
|
/** @type {object} */
|
|
@@ -168,7 +165,7 @@ function parse( source, filename = '<undefined>.cds', options = {}, messageFunct
|
|
|
168
165
|
for (const token of tokenStream.tokens) {
|
|
169
166
|
if (token.type === parser.constructor.DocComment && !token.isUsed) {
|
|
170
167
|
messageFunctions.info('syntax-ignoring-doc-comment', parser.tokenLocation(token), {},
|
|
171
|
-
|
|
168
|
+
'Ignoring doc comment as it does not belong to any artifact');
|
|
172
169
|
}
|
|
173
170
|
}
|
|
174
171
|
}
|
|
@@ -93,9 +93,8 @@ function stripCommentIndentation(lines, ignoreFirstLine) {
|
|
|
93
93
|
|
|
94
94
|
let count = 0;
|
|
95
95
|
const length = Math.min(min, line.length);
|
|
96
|
-
while (count < length && isWhitespaceCharacterNoNewline(line[count]))
|
|
96
|
+
while (count < length && isWhitespaceCharacterNoNewline(line[count]))
|
|
97
97
|
count++;
|
|
98
|
-
}
|
|
99
98
|
return Math.min(min, count);
|
|
100
99
|
}, Number.MAX_SAFE_INTEGER);
|
|
101
100
|
|
|
@@ -29,10 +29,13 @@
|
|
|
29
29
|
'use strict';
|
|
30
30
|
|
|
31
31
|
const antlr4 = require('antlr4');
|
|
32
|
-
|
|
32
|
+
// eslint-disable-next-line camelcase
|
|
33
|
+
const Antlr4LL1Analyzer = require('antlr4/src/antlr4/LL1Analyzer');
|
|
33
34
|
const { DefaultErrorStrategy } = require('antlr4/src/antlr4/error/ErrorStrategy');
|
|
34
35
|
const { InputMismatchException } = require('antlr4/src/antlr4/error/Errors');
|
|
35
|
-
const {
|
|
36
|
+
const {
|
|
37
|
+
predictionContextFromRuleContext: predictionContext,
|
|
38
|
+
} = require('antlr4/src/antlr4/PredictionContext');
|
|
36
39
|
const { ATNState } = require('antlr4/src/antlr4/atn/ATNState');
|
|
37
40
|
const { IntervalSet, Interval } = require('antlr4/src/antlr4/IntervalSet');
|
|
38
41
|
|
|
@@ -53,8 +56,7 @@ function match( ttype ) {
|
|
|
53
56
|
if (token.type === identType || !keywordRegexp.test( token.text ))
|
|
54
57
|
return antlr4.Parser.prototype.match.call( this, ttype );
|
|
55
58
|
|
|
56
|
-
this.message( 'syntax-fragile-ident', token, { id: token.text, delimited: token.text }
|
|
57
|
-
'$(ID) is a reserved name here - write $(DELIMITED) instead if you want to use it' );
|
|
59
|
+
this.message( 'syntax-fragile-ident', token, { id: token.text, delimited: token.text } );
|
|
58
60
|
this._errHandler.reportMatch(this);
|
|
59
61
|
this.consume();
|
|
60
62
|
return token;
|
|
@@ -107,7 +109,8 @@ function sync( recognizer ) {
|
|
|
107
109
|
const s = recognizer._interp.atn.states[recognizer.state];
|
|
108
110
|
// try cheaper subset first; might get lucky. seems to shave a wee bit off
|
|
109
111
|
const nextTokens = recognizer.atn.nextTokens(s);
|
|
110
|
-
// console.log('SYNC:', recognizer._ctx._sync, s.stateType, token.text,
|
|
112
|
+
// console.log('SYNC:', recognizer._ctx._sync, s.stateType, token.text,
|
|
113
|
+
// intervalSetToArray( recognizer, nextTokens ))
|
|
111
114
|
|
|
112
115
|
if (nextTokens.contains(token.type)) { // we are sure the token matches
|
|
113
116
|
if (token.text === '}' && recognizer.$nextTokensToken !== token &&
|
|
@@ -124,7 +127,8 @@ function sync( recognizer ) {
|
|
|
124
127
|
// when exiting a (innermost) rule, remember the state to make
|
|
125
128
|
// getExpectedTokensForMessage() calculate the full "expected set"
|
|
126
129
|
if (recognizer.$nextTokensToken !== token) {
|
|
127
|
-
// console.log('SET:',token.type,recognizer.state,recognizer.$nextTokensToken &&
|
|
130
|
+
// console.log('SET:',token.type,recognizer.state,recognizer.$nextTokensToken &&
|
|
131
|
+
// recognizer.$nextTokensToken.type)
|
|
128
132
|
recognizer.$nextTokensToken = token;
|
|
129
133
|
recognizer.$nextTokensState = recognizer.state;
|
|
130
134
|
recognizer.$nextTokensContext = recognizer._ctx;
|
|
@@ -142,8 +146,7 @@ function sync( recognizer ) {
|
|
|
142
146
|
// interpreter to see behind EPSILON.
|
|
143
147
|
const identType = recognizer.constructor.Identifier;
|
|
144
148
|
if (keywordRegexp.test( token.text ) && nextTokens.contains( identType )) {
|
|
145
|
-
recognizer.message( 'syntax-fragile-ident', token, { id: token.text, delimited: token.text }
|
|
146
|
-
'$(ID) is a reserved name here - write $(DELIMITED) instead if you want to use it' );
|
|
149
|
+
recognizer.message( 'syntax-fragile-ident', token, { id: token.text, delimited: token.text } );
|
|
147
150
|
token.type = identType; // make next ANTLR decision assume identifier
|
|
148
151
|
return;
|
|
149
152
|
}
|
|
@@ -187,7 +190,8 @@ function sync( recognizer ) {
|
|
|
187
190
|
|
|
188
191
|
// Report `NoViableAltException e` signalled by parser `recognizer`
|
|
189
192
|
function reportNoViableAlternative( recognizer, e ) {
|
|
190
|
-
// console.log('NOV:',this.getTokenErrorDisplay(e.startToken),
|
|
193
|
+
// console.log('NOV:',this.getTokenErrorDisplay(e.startToken),
|
|
194
|
+
// this.getTokenErrorDisplay(e.offendingToken))
|
|
191
195
|
if (e.startToken === e.offendingToken) { // mismatch at LA(1)
|
|
192
196
|
this.reportInputMismatch( recognizer, e );
|
|
193
197
|
}
|
|
@@ -262,6 +266,7 @@ function reportIgnoredWith( recognizer, t ) {
|
|
|
262
266
|
const expecting = this.getExpectedTokensForMessage( recognizer, t );
|
|
263
267
|
const m = recognizer.warning( 'syntax-ignored-with', t,
|
|
264
268
|
{ offending: "';'", expecting },
|
|
269
|
+
// eslint-disable-next-line max-len
|
|
265
270
|
'Unexpected $(OFFENDING), expecting $(EXPECTING) - ignored previous WITH' );
|
|
266
271
|
m.expectedTokens = expecting;
|
|
267
272
|
}
|
|
@@ -279,7 +284,8 @@ function consumeUntil( recognizer, set ) {
|
|
|
279
284
|
}
|
|
280
285
|
else if (set.contains(SEMI)) { // do not check for RBRACE here!
|
|
281
286
|
this._super.consumeUntil.call( this, recognizer, set );
|
|
282
|
-
// console.log('CONSUMED-ORIG:',s,this.getTokenDisplay( recognizer.getCurrentToken(),
|
|
287
|
+
// console.log('CONSUMED-ORIG:',s,this.getTokenDisplay( recognizer.getCurrentToken(),
|
|
288
|
+
// recognizer ),recognizer.getCurrentToken().line,intervalSetToArray( recognizer, set ));
|
|
283
289
|
}
|
|
284
290
|
else {
|
|
285
291
|
// DO NOT modify input param `set`, as the set might be cached in the ATN
|
|
@@ -300,7 +306,8 @@ function consumeUntil( recognizer, set ) {
|
|
|
300
306
|
recognizer.consume();
|
|
301
307
|
this.reportMatch(recognizer); // we know current token is correct
|
|
302
308
|
}
|
|
303
|
-
// console.log('CONSUMED:',s,this.getTokenDisplay( recognizer.getCurrentToken(),
|
|
309
|
+
// console.log('CONSUMED:',s,this.getTokenDisplay( recognizer.getCurrentToken(),
|
|
310
|
+
// recognizer ),recognizer.getCurrentToken().line);
|
|
304
311
|
// throw new Error('Sync')
|
|
305
312
|
}
|
|
306
313
|
}
|
|
@@ -321,8 +328,7 @@ function recoverInline( recognizer ) {
|
|
|
321
328
|
if (!keywordRegexp.test( token.text ))
|
|
322
329
|
return this._super.recoverInline.call( this, recognizer );
|
|
323
330
|
|
|
324
|
-
recognizer.message( 'syntax-fragile-ident', token, { id: token.text, delimited: token.text }
|
|
325
|
-
'$(ID) is a reserved name here - write $(DELIMITED) instead if you want to use it' );
|
|
331
|
+
recognizer.message( 'syntax-fragile-ident', token, { id: token.text, delimited: token.text } );
|
|
326
332
|
this.reportMatch(recognizer); // we know current token is correct
|
|
327
333
|
recognizer.consume();
|
|
328
334
|
return token;
|
|
@@ -362,7 +368,8 @@ function intervalSetToArray( recognizer, expected, excludesForNextToken ) {
|
|
|
362
368
|
}
|
|
363
369
|
}
|
|
364
370
|
// The parser method excludeExpected() additionally removes some tokens from the message:
|
|
365
|
-
if (recognizer.$adaptExpectedToken &&
|
|
371
|
+
if (recognizer.$adaptExpectedToken &&
|
|
372
|
+
recognizer.$nextTokensToken === recognizer.$adaptExpectedToken) {
|
|
366
373
|
const excludes = (excludesForNextToken && Array.isArray(recognizer.$adaptExpectedExcludes[0]))
|
|
367
374
|
? recognizer.$adaptExpectedExcludes[0]
|
|
368
375
|
: recognizer.$adaptExpectedExcludes;
|
|
@@ -381,13 +388,32 @@ function intervalSetToArray( recognizer, expected, excludesForNextToken ) {
|
|
|
381
388
|
const token1sort = {
|
|
382
389
|
// 0: Identifier, Number, ...
|
|
383
390
|
// 1: separators:
|
|
384
|
-
',': 1,
|
|
391
|
+
',': 1,
|
|
392
|
+
'.': 1,
|
|
393
|
+
':': 1,
|
|
394
|
+
';': 1,
|
|
385
395
|
// 2: parentheses:
|
|
386
|
-
'(': 2,
|
|
396
|
+
'(': 2,
|
|
397
|
+
')': 2,
|
|
398
|
+
'[': 2,
|
|
399
|
+
']': 2,
|
|
400
|
+
'{': 2,
|
|
401
|
+
'}': 2,
|
|
387
402
|
// 3: special:
|
|
388
|
-
'!': 3,
|
|
403
|
+
'!': 3,
|
|
404
|
+
'#': 3,
|
|
405
|
+
$: 3,
|
|
406
|
+
'?': 3,
|
|
407
|
+
'@': 3,
|
|
389
408
|
// 4: operators:
|
|
390
|
-
'*': 4,
|
|
409
|
+
'*': 4,
|
|
410
|
+
'+': 4,
|
|
411
|
+
'-': 4,
|
|
412
|
+
'/': 4,
|
|
413
|
+
'<': 4,
|
|
414
|
+
'=': 4,
|
|
415
|
+
'>': 4,
|
|
416
|
+
'|': 4,
|
|
391
417
|
// 8: KEYWORD
|
|
392
418
|
// 9: <EOF>
|
|
393
419
|
};
|
|
@@ -425,7 +451,7 @@ function getExpectedTokensForMessage( recognizer, offendingToken, deadEnds ) {
|
|
|
425
451
|
if (recognizer.state < 0)
|
|
426
452
|
return [];
|
|
427
453
|
if (recognizer.state >= atn.states.length) {
|
|
428
|
-
throw ( `Invalid state number ${ recognizer.state } for ${
|
|
454
|
+
throw new Error( `Invalid state number ${ recognizer.state } for ${
|
|
429
455
|
this.getTokenErrorDisplay( offendingToken ) }`);
|
|
430
456
|
}
|
|
431
457
|
|
|
@@ -435,10 +461,10 @@ function getExpectedTokensForMessage( recognizer, offendingToken, deadEnds ) {
|
|
|
435
461
|
if (!identType || !beforeUnreserved || beforeUnreserved + 2 > identType)
|
|
436
462
|
return intervalSetToArray( recognizer, this._super.getExpectedTokens.call( this, recognizer ) );
|
|
437
463
|
|
|
438
|
-
const ll1 = new
|
|
464
|
+
const ll1 = new Antlr4LL1Analyzer(atn);
|
|
439
465
|
const expected = new IntervalSet();
|
|
440
|
-
const
|
|
441
|
-
const
|
|
466
|
+
const origAddInterval = expected.addInterval;
|
|
467
|
+
const origAddSet = expected.addSet;
|
|
442
468
|
expected.addInterval = addInterval;
|
|
443
469
|
expected.addSet = addSet;
|
|
444
470
|
const lookBusy = new antlr4.Utils.Set();
|
|
@@ -466,23 +492,24 @@ function getExpectedTokensForMessage( recognizer, offendingToken, deadEnds ) {
|
|
|
466
492
|
predictionContext( atn, recognizer._ctx ),
|
|
467
493
|
expected, lookBusy, calledRules, true, true );
|
|
468
494
|
}
|
|
469
|
-
// console.log(state, recognizer.$nextTokensState,
|
|
495
|
+
// console.log(state, recognizer.$nextTokensState,
|
|
496
|
+
// expected.toString(recognizer.literalNames, recognizer.symbolicNames));
|
|
470
497
|
return intervalSetToArray( recognizer, expected );
|
|
471
498
|
|
|
472
499
|
function addSet(other) {
|
|
473
500
|
if (!other.contains( hideAltsType ))
|
|
474
|
-
|
|
501
|
+
origAddSet.call( this, other );
|
|
475
502
|
}
|
|
476
503
|
|
|
477
504
|
// Add an interval `v` to the IntervalSet `this`. If `v` contains the token
|
|
478
505
|
// type `Identifier`, do not add non-reserved keywords in `v`.
|
|
479
506
|
function addInterval(v) {
|
|
480
507
|
if (v.stop <= identType) {
|
|
481
|
-
|
|
508
|
+
origAddInterval.call(this, v);
|
|
482
509
|
}
|
|
483
510
|
else if (v.start >= identType) {
|
|
484
511
|
if (v.stop === identType + 1 || !recognizer.tokenRewrite) {
|
|
485
|
-
|
|
512
|
+
origAddInterval.call(this, v);
|
|
486
513
|
}
|
|
487
514
|
else {
|
|
488
515
|
for (let j = v.start; j < v.stop; j++)
|
|
@@ -497,7 +524,7 @@ function getExpectedTokensForMessage( recognizer, offendingToken, deadEnds ) {
|
|
|
497
524
|
}
|
|
498
525
|
|
|
499
526
|
function addRange( interval, start, stop ) {
|
|
500
|
-
|
|
527
|
+
origAddInterval.call( interval, new Interval( start, stop || start + 1 ) );
|
|
501
528
|
}
|
|
502
529
|
}
|
|
503
530
|
|