@abaplint/core 2.119.51 → 2.119.52

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.
@@ -28,7 +28,7 @@ export declare abstract class ABAPObject extends AbstractObject {
28
28
  abstract getDescription(): string | undefined;
29
29
  constructor(name: string);
30
30
  static is(x: any): x is ABAPObject;
31
- parse(release: ABAPRelease, globalMacros?: readonly string[], reg?: IRegistry, languageVersion?: LanguageVersion, openABAP?: boolean): IParseResult;
31
+ parse(release: ABAPRelease, globalMacros?: readonly string[], reg?: IRegistry, languageVersion?: LanguageVersion): IParseResult;
32
32
  setDirty(): void;
33
33
  private getParsedXML;
34
34
  getABAPFiles(): readonly ABAPFile[];
@@ -122,7 +122,7 @@ declare abstract class AbstractObject implements IObject {
122
122
  abstract getDescription(): string | undefined;
123
123
  constructor(name: string);
124
124
  getParsingIssues(): readonly Issue[];
125
- parse(_release?: ABAPRelease, _globalMacros?: readonly string[], _reg?: IRegistry, _languageVersion?: LanguageVersion, _openABAP?: boolean): IParseResult;
125
+ parse(_release?: ABAPRelease, _globalMacros?: readonly string[], _reg?: IRegistry, _languageVersion?: LanguageVersion): IParseResult;
126
126
  getName(): string;
127
127
  setDirty(): void;
128
128
  addFile(file: IFile): void;
@@ -1463,7 +1463,7 @@ declare class CondSub extends Expression {
1463
1463
 
1464
1464
  export declare class Config implements IConfiguration {
1465
1465
  private readonly config;
1466
- static getDefault(ver?: VersionOldOrNew, langVer?: LanguageVersion, openABAP?: boolean): Config;
1466
+ static getDefault(ver?: VersionOldOrNew, langVer?: LanguageVersion): Config;
1467
1467
  getEnabledRules(): IRule[];
1468
1468
  constructor(json: string);
1469
1469
  get(): IConfig;
@@ -4076,7 +4076,7 @@ export declare interface IObject extends IArtifact {
4076
4076
  /** returns true if the object was parsed, false if no changes since last parse
4077
4077
  * registry for global cross object macros
4078
4078
  */
4079
- parse(release?: ABAPRelease, globalMacros?: readonly string[], reg?: IRegistry, languageVersion?: LanguageVersion, openABAP?: boolean): IParseResult;
4079
+ parse(release?: ABAPRelease, globalMacros?: readonly string[], reg?: IRegistry, languageVersion?: LanguageVersion): IParseResult;
4080
4080
  getParsingIssues(): readonly Issue[];
4081
4081
  getFiles(): readonly IFile[];
4082
4082
  addFile(file: IFile): void;
@@ -4371,8 +4371,6 @@ declare interface ISyntaxSettings {
4371
4371
  /** ABAP language version */
4372
4372
  version?: VersionOldOrNew;
4373
4373
  languageVersion?: LanguageVersion;
4374
- /** Use the OpenABAP dialect (v702 base + a set of additional language features). */
4375
- openABAP?: boolean;
4376
4374
  /** Report error for objects in this regex namespace. Types not in namespace will be void. Case insensitive */
4377
4375
  errorNamespace: string;
4378
4376
  /** List of full named global constants (regex not possible)
@@ -5990,6 +5988,12 @@ declare const releaseDefsRaw: readonly [readonly ["v700", {
5990
5988
  readonly op: 702;
5991
5989
  readonly cloud: null;
5992
5990
  readonly ce: null;
5991
+ }], readonly ["open-abap", {
5992
+ readonly abap: "open-abap";
5993
+ readonly kernel: null;
5994
+ readonly op: null;
5995
+ readonly cloud: null;
5996
+ readonly ce: null;
5993
5997
  }], readonly ["v710", {
5994
5998
  readonly abap: "710";
5995
5999
  readonly kernel: 710;
@@ -860,14 +860,13 @@ class Combi {
860
860
  return res;
861
861
  }
862
862
  // assumption: no pragmas supplied in tokens input
863
- static run(runnable, tokens, versionOrRelease, languageVersion = version_1.LanguageVersion.Normal, openABAP = false) {
864
- this.openABAP = openABAP || versionOrRelease === version_1.Version.OpenABAP;
863
+ static run(runnable, tokens, versionOrRelease, languageVersion = version_1.LanguageVersion.Normal) {
865
864
  this.langVer = languageVersion;
866
865
  if (typeof versionOrRelease === "string") {
867
- this.release = this.openABAP ? version_1.Release.v702 : (0, version_1.versionToABAPRelease)(versionOrRelease);
866
+ this.release = (0, version_1.versionToABAPRelease)(versionOrRelease);
868
867
  }
869
868
  else {
870
- this.release = this.openABAP ? version_1.Release.v702 : versionOrRelease;
869
+ this.release = versionOrRelease;
871
870
  }
872
871
  const input = new result_1.Result(tokens, 0);
873
872
  try {
@@ -900,14 +899,13 @@ class Combi {
900
899
  return this.langVer;
901
900
  }
902
901
  static isOpenABAP() {
903
- return this.openABAP;
902
+ return this.release === version_1.Release["open-abap"];
904
903
  }
905
904
  }
906
905
  exports.Combi = Combi;
907
906
  // todo, change this class to be instantiated, constructor(runnable) ?
908
907
  Combi.release = version_1.Release.v758;
909
908
  Combi.langVer = version_1.LanguageVersion.Normal;
910
- Combi.openABAP = false;
911
909
  // -----------------------------------------------------------------------------
912
910
  function str(s) {
913
911
  if (s.indexOf(" ") > 0 || s.indexOf("-") > 0) {
@@ -103,13 +103,12 @@ class WorkArea {
103
103
  }
104
104
  }
105
105
  class StatementParser {
106
- constructor(release, reg, languageVersion = version_1.LanguageVersion.Normal, openABAP = false) {
106
+ constructor(release, reg, languageVersion = version_1.LanguageVersion.Normal) {
107
107
  if (!StatementParser.map) {
108
108
  StatementParser.map = new StatementMap();
109
109
  }
110
110
  this.release = release;
111
111
  this.languageVersion = languageVersion;
112
- this.openABAP = openABAP;
113
112
  this.reg = reg;
114
113
  }
115
114
  /** input is one full object */
@@ -266,7 +265,7 @@ class StatementParser {
266
265
  return new nodes_1.StatementNode(new _statement_1.Empty()).setChildren(this.tokensToNodes(tokens));
267
266
  }
268
267
  for (const st of StatementParser.map.lookup(filtered[0].getStr())) {
269
- const match = combi_1.Combi.run(st.matcher, filtered, this.release, this.languageVersion, this.openABAP);
268
+ const match = combi_1.Combi.run(st.matcher, filtered, this.release, this.languageVersion);
270
269
  if (match) {
271
270
  const last = tokens[tokens.length - 1];
272
271
  match.push(new nodes_1.TokenNode(last));
@@ -276,7 +275,7 @@ class StatementParser {
276
275
  }
277
276
  // next try the statements without specific keywords
278
277
  for (const st of StatementParser.map.lookup("")) {
279
- const match = combi_1.Combi.run(st.matcher, filtered, this.release, this.languageVersion, this.openABAP);
278
+ const match = combi_1.Combi.run(st.matcher, filtered, this.release, this.languageVersion);
280
279
  if (match) {
281
280
  const last = tokens[tokens.length - 1];
282
281
  match.push(new nodes_1.TokenNode(last));
@@ -116,10 +116,18 @@ class Select {
116
116
  for (const s of node.findDirectExpressions(Expressions.SQLSource)) {
117
117
  sql_source_1.SQLSource.runSyntax(s, input);
118
118
  }
119
+ const upToWhere = node.findDirectExpression(Expressions.SQLCond);
120
+ const isCloud = input.scope.getLanguageVersion() === version_1.LanguageVersion.Cloud;
119
121
  for (const up of node.findDirectExpressions(Expressions.SQLUpTo)) {
122
+ // in classic Open SQL (INTO before WHERE) "UP TO" is allowed before INTO,
123
+ // in strict Open SQL (INTO after WHERE) "UP TO" must be placed after INTO
124
+ const intoAfterWhere = upToWhere !== undefined
125
+ && intoExpression !== undefined
126
+ && intoExpression.getFirstToken().getStart().isAfter(upToWhere.getFirstToken().getStart());
120
127
  if (intoExpression
121
128
  && this.isStrictMode(node, input)
122
- && (selectLoop === false || input.scope.getLanguageVersion() === version_1.LanguageVersion.Cloud)
129
+ && (isCloud || (this.upToUsesHostVariable(up) && intoAfterWhere))
130
+ && (selectLoop === false || isCloud)
123
131
  && from.getFirstToken().getStart().isBefore(up.getFirstToken().getStart())
124
132
  && up.getFirstToken().getStart().isBefore(intoExpression.getFirstToken().getStart())) {
125
133
  const message = `The addition "UP TO n ROWS" must only be placed after the INTO/APPENDING clause.`;
@@ -157,6 +165,10 @@ class Select {
157
165
  input.scope.pop(node.getLastToken().getEnd());
158
166
  }
159
167
  }
168
+ static upToUsesHostVariable(up) {
169
+ var _a;
170
+ return ((_a = up.findFirstExpression(Expressions.SQLSource)) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr()) === "@";
171
+ }
160
172
  static buildUpToRowsFix(node, input, up, intoExpression) {
161
173
  const tokens = node.getTokens();
162
174
  const upLast = up.getLastToken();
@@ -10,19 +10,17 @@ const structure_parser_1 = require("./3_structures/structure_parser");
10
10
  const version_1 = require("../version");
11
11
  class ABAPParser {
12
12
  constructor(optionsOrRelease, globalMacros, reg) {
13
- var _a, _b, _c, _d;
13
+ var _a, _b, _c;
14
14
  if (optionsOrRelease === undefined || ABAPParser.isRelease(optionsOrRelease)) {
15
15
  this.release = optionsOrRelease !== null && optionsOrRelease !== void 0 ? optionsOrRelease : version_1.defaultRelease;
16
16
  this.languageVersion = version_1.LanguageVersion.Normal;
17
- this.openABAP = false;
18
17
  this.globalMacros = globalMacros !== null && globalMacros !== void 0 ? globalMacros : [];
19
18
  this.reg = reg;
20
19
  }
21
20
  else {
22
21
  this.release = (_a = optionsOrRelease.release) !== null && _a !== void 0 ? _a : version_1.defaultRelease;
23
22
  this.languageVersion = (_b = optionsOrRelease.languageVersion) !== null && _b !== void 0 ? _b : version_1.LanguageVersion.Normal;
24
- this.openABAP = (_c = optionsOrRelease.openABAP) !== null && _c !== void 0 ? _c : false;
25
- this.globalMacros = (_d = optionsOrRelease.globalMacros) !== null && _d !== void 0 ? _d : [];
23
+ this.globalMacros = (_c = optionsOrRelease.globalMacros) !== null && _c !== void 0 ? _c : [];
26
24
  this.reg = optionsOrRelease.reg;
27
25
  }
28
26
  }
@@ -40,7 +38,7 @@ class ABAPParser {
40
38
  const lexingRuntime = Date.now() - b1;
41
39
  // 2: statements
42
40
  const b2 = Date.now();
43
- const statementResult = new statement_parser_1.StatementParser(this.release, this.reg, this.languageVersion, this.openABAP)
41
+ const statementResult = new statement_parser_1.StatementParser(this.release, this.reg, this.languageVersion)
44
42
  .run(lexerResult, this.globalMacros);
45
43
  const statementsRuntime = Date.now() - b2;
46
44
  // 3: structures
@@ -39,7 +39,7 @@ const artifacts_rules_1 = require("./artifacts_rules");
39
39
  const JSON5 = __importStar(require("json5"));
40
40
  // assumption: this class is immutable
41
41
  class Config {
42
- static getDefault(ver, langVer, openABAP) {
42
+ static getDefault(ver, langVer) {
43
43
  const rules = {};
44
44
  const sorted = artifacts_rules_1.ArtifactsRules.getRules().sort((a, b) => {
45
45
  return a.getMetadata().key.localeCompare(b.getMetadata().key);
@@ -73,7 +73,6 @@ class Config {
73
73
  syntax: {
74
74
  version,
75
75
  languageVersion: langVer,
76
- openABAP,
77
76
  errorNamespace: "^(Z|Y|LCL\_|TY\_|LIF\_)",
78
77
  globalConstants: [],
79
78
  globalMacros: [],
@@ -165,7 +164,7 @@ class Config {
165
164
  return (0, version_1.versionToABAPRelease)(v);
166
165
  }
167
166
  getOpenABAP() {
168
- return this.config.syntax.openABAP === true;
167
+ return this.getRelease() === version_1.Release["open-abap"];
169
168
  }
170
169
  getVersion() {
171
170
  const v = this.config.syntax.version;
@@ -202,10 +201,8 @@ class Config {
202
201
  if (version === version_1.Version.Cloud) {
203
202
  this.config.syntax.languageVersion = version_1.LanguageVersion.Cloud;
204
203
  }
205
- else if (version === version_1.Version.OpenABAP) {
206
- this.config.syntax.version = version_1.Version.v702;
207
- this.config.syntax.openABAP = true;
208
- }
204
+ // OpenABAP keeps its own version identity; open-abap-ness is derived from the
205
+ // release in getOpenABAP() rather than a separate stored flag.
209
206
  }
210
207
  }
211
208
  exports.Config = Config;
@@ -18,12 +18,12 @@ class ABAPObject extends _abstract_object_1.AbstractObject {
18
18
  static is(x) {
19
19
  return !!x && x instanceof ABAPObject;
20
20
  }
21
- parse(release, globalMacros, reg, languageVersion = version_1.LanguageVersion.Normal, openABAP = false) {
21
+ parse(release, globalMacros, reg, languageVersion = version_1.LanguageVersion.Normal) {
22
22
  if (this.isDirty() === false) {
23
23
  return { updated: false, runtime: 0 };
24
24
  }
25
25
  const abapFiles = this.getFiles().filter(f => f.getFilename().endsWith(".abap"));
26
- const result = new abap_parser_1.ABAPParser({ release, globalMacros, reg, languageVersion, openABAP }).parse(abapFiles);
26
+ const result = new abap_parser_1.ABAPParser({ release, globalMacros, reg, languageVersion }).parse(abapFiles);
27
27
  this.parsed = result.output;
28
28
  this.old = result.issues;
29
29
  this.dirty = false;
@@ -15,7 +15,7 @@ class AbstractObject {
15
15
  getParsingIssues() {
16
16
  return this.old;
17
17
  }
18
- parse(_release, _globalMacros, _reg, _languageVersion, _openABAP) {
18
+ parse(_release, _globalMacros, _reg, _languageVersion) {
19
19
  return { updated: false, runtime: 0 };
20
20
  }
21
21
  getName() {
@@ -74,7 +74,7 @@ class Registry {
74
74
  }
75
75
  static abaplintVersion() {
76
76
  // magic, see build script "version.js"
77
- return "2.119.51";
77
+ return "2.119.52";
78
78
  }
79
79
  getDDICReferences() {
80
80
  return this.ddicReferences;
@@ -322,7 +322,7 @@ class Registry {
322
322
  // todo, refactor, this is a mess, see where-used, a lot of the code should be in this method instead
323
323
  parsePrivate(input) {
324
324
  const config = this.getConfig();
325
- const result = input.parse(config.getRelease(), config.getSyntaxSetttings().globalMacros, this, config.getLanguageVersion(), config.getOpenABAP());
325
+ const result = input.parse(config.getRelease(), config.getSyntaxSetttings().globalMacros, this, config.getLanguageVersion());
326
326
  ParsingPerformance.push(input, result);
327
327
  }
328
328
  isDirty() {
@@ -51,6 +51,12 @@ const releaseDefsRaw = [
51
51
  ["v700", { abap: "700", kernel: 700, op: 700, cloud: null, ce: null }],
52
52
  ["v701", { abap: "701", kernel: 701, op: 701, cloud: null, ce: null }],
53
53
  ["v702", { abap: "702", kernel: 702, op: 702, cloud: null, ce: null }],
54
+ // OpenABAP: not a real SAP release. A dialect that is "702 baseline + a curated set
55
+ // of newer features" (opted in per-statement via AlsoIn.OpenABAP). Placed right after
56
+ // v702 on purpose: its ordinal must behave exactly like v702 for releaseAtLeast() gates
57
+ // (nothing else gates between v702 and v710), while staying a distinct identity so
58
+ // open-abap can be detected without a separate boolean flag.
59
+ ["open-abap", { abap: "open-abap", kernel: null, op: null, cloud: null, ce: null }],
54
60
  ["v710", { abap: "710", kernel: 710, op: 710, cloud: null, ce: null }],
55
61
  ["v711", { abap: "711", kernel: 711, op: 711, cloud: null, ce: null }],
56
62
  ["v720", { abap: "720", kernel: 720, op: 720, cloud: null, ce: null }],
@@ -125,10 +131,13 @@ const releaseDefsRaw = [
125
131
  ];
126
132
  /** All known releases in chronological order. Declaration order IS the ordering. */
127
133
  exports.ReleaseList = releaseDefsRaw.map(([name, r], i) => Object.freeze(Object.assign(Object.assign({}, r), { name, ordinal: i })));
134
+ /** Base lookup, keyed by the raw release name (e.g. `"v762"`, `"Newest"`). */
135
+ const byName = Object.fromEntries(releaseDefsRaw.map(([name], i) => [name, exports.ReleaseList[i]]));
128
136
  /** Lookup table keyed by release name (e.g. `Release.v740sp05`, `Release.Newest`). */
129
- exports.Release = Object.freeze(Object.assign(Object.assign({}, Object.fromEntries(releaseDefsRaw.map(([name], i) => [name, exports.ReleaseList[i]]))), {
130
- // Deprecated aliases: on-prem v750–v758 map to last cloud row at that op
131
- v750: exports.ReleaseList[14], v751: exports.ReleaseList[17], v752: exports.ReleaseList[21], v753: exports.ReleaseList[25], v754: exports.ReleaseList[29], v755: exports.ReleaseList[33], v756: exports.ReleaseList[37], v757: exports.ReleaseList[41], v758: exports.ReleaseList[45], v816: exports.ReleaseList[53] }));
137
+ exports.Release = Object.freeze(Object.assign(Object.assign({}, byName), {
138
+ // Deprecated aliases: on-prem v750–v758 map to last cloud row at that op.
139
+ // Referenced by cloud name (not array index) so inserting rows can't silently repoint them.
140
+ v750: byName["v762"], v751: byName["v765"], v752: byName["v769"], v753: byName["v773"], v754: byName["v777"], v755: byName["v781"], v756: byName["v785"], v757: byName["v789"], v758: byName["v793"], v816: byName["v916"] }));
132
141
  /**
133
142
  * Is `running` at least as new as `required`?
134
143
  * Comparison is purely by ordinal (declaration order in ReleaseList).
@@ -157,7 +166,7 @@ const byDeprecated = Object.freeze({
157
166
  [Version.v758]: exports.Release["v758"],
158
167
  [Version.v816]: exports.Release["v816"],
159
168
  [Version.Cloud]: exports.Release["Newest"], // Cloud → Newest sentinel
160
- [Version.OpenABAP]: exports.Release["v702"], // OpenABAP shares v702 release identity
169
+ [Version.OpenABAP]: exports.Release["open-abap"], // OpenABAP is its own release identity (702 baseline + curated features)
161
170
  });
162
171
  function versionToABAPRelease(v) {
163
172
  const found = byDeprecated[v];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.119.51",
3
+ "version": "2.119.52",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",