@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.
Files changed (117) hide show
  1. package/CHANGELOG.md +101 -3
  2. package/bin/cdsc.js +4 -2
  3. package/doc/CHANGELOG_BETA.md +35 -0
  4. package/lib/api/main.js +153 -29
  5. package/lib/api/validate.js +8 -3
  6. package/lib/base/dictionaries.js +6 -6
  7. package/lib/base/error.js +2 -2
  8. package/lib/base/keywords.js +106 -24
  9. package/lib/base/message-registry.js +177 -79
  10. package/lib/base/messages.js +78 -57
  11. package/lib/base/model.js +2 -1
  12. package/lib/checks/actionsFunctions.js +1 -1
  13. package/lib/checks/annotationsOData.js +2 -2
  14. package/lib/checks/arrayOfs.js +15 -7
  15. package/lib/checks/cdsPersistence.js +1 -1
  16. package/lib/checks/checkForTypes.js +53 -0
  17. package/lib/checks/defaultValues.js +4 -2
  18. package/lib/checks/elements.js +81 -6
  19. package/lib/checks/foreignKeys.js +12 -13
  20. package/lib/checks/invalidTarget.js +10 -11
  21. package/lib/checks/managedInType.js +21 -15
  22. package/lib/checks/nullableKeys.js +1 -1
  23. package/lib/checks/onConditions.js +9 -9
  24. package/lib/checks/parameters.js +23 -0
  25. package/lib/checks/queryNoDbArtifacts.js +1 -1
  26. package/lib/checks/selectItems.js +1 -1
  27. package/lib/checks/sql-snippets.js +12 -10
  28. package/lib/checks/types.js +2 -2
  29. package/lib/checks/utils.js +17 -7
  30. package/lib/checks/validator.js +36 -14
  31. package/lib/compiler/assert-consistency.js +21 -13
  32. package/lib/compiler/builtins.js +8 -0
  33. package/lib/compiler/checks.js +57 -40
  34. package/lib/compiler/define.js +139 -69
  35. package/lib/compiler/extend.js +319 -50
  36. package/lib/compiler/finalize-parse-cdl.js +14 -9
  37. package/lib/compiler/kick-start.js +2 -35
  38. package/lib/compiler/populate.js +111 -68
  39. package/lib/compiler/propagator.js +5 -3
  40. package/lib/compiler/resolve.js +71 -108
  41. package/lib/compiler/shared.js +82 -54
  42. package/lib/compiler/tweak-assocs.js +26 -14
  43. package/lib/compiler/utils.js +13 -2
  44. package/lib/edm/annotations/genericTranslation.js +10 -7
  45. package/lib/edm/csn2edm.js +11 -11
  46. package/lib/edm/edm.js +17 -9
  47. package/lib/edm/edmPreprocessor.js +53 -30
  48. package/lib/edm/edmUtils.js +7 -2
  49. package/lib/gen/Dictionary.json +14 -0
  50. package/lib/gen/language.checksum +1 -1
  51. package/lib/gen/language.interp +3 -2
  52. package/lib/gen/languageParser.js +4312 -4186
  53. package/lib/inspect/inspectModelStatistics.js +1 -1
  54. package/lib/inspect/inspectPropagation.js +23 -9
  55. package/lib/json/csnVersion.js +13 -13
  56. package/lib/json/from-csn.js +161 -172
  57. package/lib/json/to-csn.js +70 -10
  58. package/lib/language/.eslintrc.json +4 -0
  59. package/lib/language/antlrParser.js +8 -11
  60. package/lib/language/docCommentParser.js +1 -2
  61. package/lib/language/errorStrategy.js +54 -27
  62. package/lib/language/genericAntlrParser.js +140 -93
  63. package/lib/language/language.g4 +57 -33
  64. package/lib/language/multiLineStringParser.js +75 -63
  65. package/lib/main.d.ts +3 -6
  66. package/lib/main.js +1 -0
  67. package/lib/model/.eslintrc.json +13 -0
  68. package/lib/model/api.js +4 -2
  69. package/lib/model/csnRefs.js +78 -50
  70. package/lib/model/csnUtils.js +272 -222
  71. package/lib/model/enrichCsn.js +41 -31
  72. package/lib/model/revealInternalProperties.js +61 -57
  73. package/lib/model/sortViews.js +35 -31
  74. package/lib/modelCompare/compare.js +52 -18
  75. package/lib/modelCompare/filter.js +83 -0
  76. package/lib/optionProcessor.js +10 -1
  77. package/lib/render/manageConstraints.js +11 -7
  78. package/lib/render/toCdl.js +151 -106
  79. package/lib/render/toHdbcds.js +8 -6
  80. package/lib/render/toRename.js +4 -4
  81. package/lib/render/toSql.js +17 -7
  82. package/lib/render/utils/common.js +27 -9
  83. package/lib/render/utils/sql.js +5 -5
  84. package/lib/sql-identifier.js +7 -0
  85. package/lib/transform/db/applyTransformations.js +32 -3
  86. package/lib/transform/db/assertUnique.js +27 -38
  87. package/lib/transform/db/expansion.js +92 -41
  88. package/lib/transform/db/flattening.js +1 -1
  89. package/lib/transform/db/temporal.js +3 -1
  90. package/lib/transform/db/transformExists.js +8 -2
  91. package/lib/transform/db/views.js +42 -13
  92. package/lib/transform/draft/db.js +2 -2
  93. package/lib/transform/forOdataNew.js +10 -7
  94. package/lib/transform/{forHanaNew.js → forRelationalDB.js} +18 -12
  95. package/lib/transform/localized.js +29 -20
  96. package/lib/transform/odata/toFinalBaseType.js +8 -11
  97. package/lib/transform/odata/typesExposure.js +2 -1
  98. package/lib/transform/parseExpr.js +245 -0
  99. package/lib/transform/transformUtilsNew.js +122 -51
  100. package/lib/transform/translateAssocsToJoins.js +17 -16
  101. package/lib/utils/moduleResolve.js +5 -5
  102. package/lib/utils/objectUtils.js +3 -3
  103. package/lib/utils/term.js +5 -5
  104. package/package.json +2 -2
  105. package/share/messages/anno-duplicate-unrelated-layer.md +6 -6
  106. package/share/messages/check-proper-type-of.md +4 -4
  107. package/share/messages/check-proper-type.md +2 -2
  108. package/share/messages/duplicate-autoexposed.md +4 -4
  109. package/share/messages/extend-repeated-intralayer.md +4 -5
  110. package/share/messages/extend-unrelated-layer.md +4 -4
  111. package/share/messages/message-explanations.json +3 -1
  112. package/share/messages/redirected-to-ambiguous.md +7 -6
  113. package/share/messages/redirected-to-complex.md +63 -0
  114. package/share/messages/redirected-to-unrelated.md +6 -5
  115. package/share/messages/rewrite-not-supported.md +4 -4
  116. package/share/messages/{syntax-expected-integer.md → syntax-expecting-integer.md} +4 -4
  117. package/share/messages/wildcard-excluding-one.md +37 -0
@@ -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', // TODO: notNull?
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' || n.charAt(0) === '@' || csnDirectValues.includes(n))
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
- return insertOrderDict( dict );
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
- // create $origin specification for `includes` of `art`
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 = originRef( source );
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
- csn.$origin = definition( xsn._origin );
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') // via propagator.js
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,
@@ -0,0 +1,4 @@
1
+ {
2
+ "root": true,
3
+ "extends": "../../.eslintrc-ydkjsi.json"
4
+ }
@@ -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
- recognizer.error( null, offendingSymbol, msg );
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', options = {}, messageFunctions = null, rule = 'cdl' ) {
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
- "Ignoring doc-comment as it does not belong to any artifact");
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
- const antlr4_LL1Analyzer = require('antlr4/src/antlr4/LL1Analyzer');
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 { predictionContextFromRuleContext: predictionContext } = require('antlr4/src/antlr4/PredictionContext');
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, intervalSetToArray( recognizer, nextTokens ))
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 && recognizer.$nextTokensToken.type)
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), this.getTokenErrorDisplay(e.offendingToken))
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(), recognizer ),recognizer.getCurrentToken().line,intervalSetToArray( recognizer, set ));
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(), recognizer ),recognizer.getCurrentToken().line);
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 && recognizer.$nextTokensToken === 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, '.': 1, ':': 1, ';': 1,
391
+ ',': 1,
392
+ '.': 1,
393
+ ':': 1,
394
+ ';': 1,
385
395
  // 2: parentheses:
386
- '(': 2, ')': 2, '[': 2, ']':2, '{': 2, '}': 2,
396
+ '(': 2,
397
+ ')': 2,
398
+ '[': 2,
399
+ ']': 2,
400
+ '{': 2,
401
+ '}': 2,
387
402
  // 3: special:
388
- '!': 3, '#': 3, '$': 3, '?': 3, '@': 3,
403
+ '!': 3,
404
+ '#': 3,
405
+ $: 3,
406
+ '?': 3,
407
+ '@': 3,
389
408
  // 4: operators:
390
- '*': 4, '+': 4, '-': 4, '/': 4, '<': 4, '=': 4, '>': 4, '|': 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 antlr4_LL1Analyzer(atn);
464
+ const ll1 = new Antlr4LL1Analyzer(atn);
439
465
  const expected = new IntervalSet();
440
- const orig_addInterval = expected.addInterval;
441
- const orig_addSet = expected.addSet;
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, expected.toString(recognizer.literalNames, recognizer.symbolicNames));
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
- orig_addSet.call( this, other );
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
- orig_addInterval.call(this, v);
508
+ origAddInterval.call(this, v);
482
509
  }
483
510
  else if (v.start >= identType) {
484
511
  if (v.stop === identType + 1 || !recognizer.tokenRewrite) {
485
- orig_addInterval.call(this, v);
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
- orig_addInterval.call( interval, new Interval( start, stop || start + 1 ) );
527
+ origAddInterval.call( interval, new Interval( start, stop || start + 1 ) );
501
528
  }
502
529
  }
503
530