@abaplint/core 2.85.29 → 2.85.32

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.
@@ -1912,6 +1912,7 @@ declare namespace Expressions {
1912
1912
  SQLCompareOperator,
1913
1913
  SQLCompare,
1914
1914
  SQLCond,
1915
+ SQLFieldListLoop,
1915
1916
  SQLFieldList,
1916
1917
  SQLFieldName,
1917
1918
  SQLForAllEntries,
@@ -4894,6 +4895,10 @@ declare class SQLFieldList extends Expression {
4894
4895
  getRunnable(): IStatementRunnable;
4895
4896
  }
4896
4897
 
4898
+ declare class SQLFieldListLoop extends Expression {
4899
+ getRunnable(): IStatementRunnable;
4900
+ }
4901
+
4897
4902
  declare class SQLFieldName extends Expression {
4898
4903
  getRunnable(): IStatementRunnable;
4899
4904
  }
@@ -158,6 +158,7 @@ __exportStar(require("./sql_client"), exports);
158
158
  __exportStar(require("./sql_compare_operator"), exports);
159
159
  __exportStar(require("./sql_compare"), exports);
160
160
  __exportStar(require("./sql_cond"), exports);
161
+ __exportStar(require("./sql_field_list_loop"), exports);
161
162
  __exportStar(require("./sql_field_list"), exports);
162
163
  __exportStar(require("./sql_field_name"), exports);
163
164
  __exportStar(require("./sql_for_all_entries"), exports);
@@ -3,25 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SelectLoop = void 0;
4
4
  const combi_1 = require("../combi");
5
5
  const _1 = require(".");
6
- const version_1 = require("../../../version");
7
6
  const sql_order_by_1 = require("./sql_order_by");
8
7
  const sql_having_1 = require("./sql_having");
9
- const sql_path_1 = require("./sql_path");
10
- const sql_as_name_1 = require("./sql_as_name");
11
- const sql_case_1 = require("./sql_case");
12
8
  const sql_into_structure_1 = require("./sql_into_structure");
13
9
  const sql_field_list_1 = require("./sql_field_list");
14
10
  const sql_hints_1 = require("./sql_hints");
15
- const sql_function_1 = require("./sql_function");
11
+ const sql_field_list_loop_1 = require("./sql_field_list_loop");
16
12
  class SelectLoop extends combi_1.Expression {
17
13
  getRunnable() {
18
14
  const where = (0, combi_1.seq)("WHERE", _1.SQLCond);
19
- const comma = (0, combi_1.opt)((0, combi_1.ver)(version_1.Version.v740sp05, ","));
20
- const as = (0, combi_1.seq)("AS", sql_as_name_1.SQLAsName);
21
- const someField = (0, combi_1.seq)((0, combi_1.alt)(_1.SQLFieldName, sql_path_1.SQLPath, _1.SQLAggregation, sql_function_1.SQLFunction, sql_case_1.SQLCase), (0, combi_1.optPrio)(as), comma);
22
- const fieldList = (0, combi_1.seq)((0, combi_1.star)(someField), (0, combi_1.alt)(_1.SQLFieldName, sql_path_1.SQLPath), (0, combi_1.optPrio)(as), comma, (0, combi_1.star)(someField));
23
- // todo, use SQLFieldList instead?
24
- const fields = (0, combi_1.alt)("*", _1.Dynamic, fieldList);
25
15
  const client = "CLIENT SPECIFIED";
26
16
  const bypass = "BYPASSING BUFFER";
27
17
  const up = (0, combi_1.seq)("UP TO", _1.SQLSource, "ROWS");
@@ -29,7 +19,7 @@ class SelectLoop extends combi_1.Expression {
29
19
  const tab = (0, combi_1.seq)(_1.SQLIntoTable, (0, combi_1.alt)(pack, (0, combi_1.seq)(_1.SQLFrom, pack), (0, combi_1.seq)(pack, _1.SQLFrom)));
30
20
  const perm = (0, combi_1.per)(_1.SQLFrom, where, up, sql_order_by_1.SQLOrderBy, sql_having_1.SQLHaving, client, bypass, _1.SQLGroupBy, _1.SQLForAllEntries, (0, combi_1.alt)(tab, sql_into_structure_1.SQLIntoStructure));
31
21
  const strict = (0, combi_1.seq)(_1.SQLFrom, "FIELDS", sql_field_list_1.SQLFieldList, where, sql_into_structure_1.SQLIntoStructure, up);
32
- const ret = (0, combi_1.seq)("SELECT", (0, combi_1.altPrio)((0, combi_1.seq)((0, combi_1.optPrio)("DISTINCT"), fields, perm), strict), (0, combi_1.optPrio)(sql_hints_1.SQLHints));
22
+ const ret = (0, combi_1.seq)("SELECT", (0, combi_1.altPrio)((0, combi_1.seq)((0, combi_1.optPrio)("DISTINCT"), sql_field_list_loop_1.SQLFieldListLoop, perm), strict), (0, combi_1.optPrio)(sql_hints_1.SQLHints));
33
23
  return ret;
34
24
  }
35
25
  }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SQLFieldListLoop = void 0;
4
+ const combi_1 = require("../combi");
5
+ const _1 = require(".");
6
+ const version_1 = require("../../../version");
7
+ const sql_function_1 = require("./sql_function");
8
+ const sql_path_1 = require("./sql_path");
9
+ // loop must include one field from the database table
10
+ class SQLFieldListLoop extends combi_1.Expression {
11
+ getRunnable() {
12
+ const comma = (0, combi_1.opt)((0, combi_1.ver)(version_1.Version.v740sp05, ","));
13
+ const as = (0, combi_1.seq)("AS", _1.SQLAsName);
14
+ const someField = (0, combi_1.seq)((0, combi_1.alt)(_1.SQLFieldName, sql_path_1.SQLPath, _1.SQLAggregation, sql_function_1.SQLFunction, _1.SQLCase), (0, combi_1.optPrio)(as), comma);
15
+ const fieldList = (0, combi_1.seq)((0, combi_1.star)(someField), (0, combi_1.alt)(_1.SQLFieldName, sql_path_1.SQLPath), (0, combi_1.optPrio)(as), comma, (0, combi_1.star)(someField));
16
+ const fields = (0, combi_1.alt)("*", _1.Dynamic, fieldList);
17
+ return fields;
18
+ }
19
+ }
20
+ exports.SQLFieldListLoop = SQLFieldListLoop;
21
+ //# sourceMappingURL=sql_field_list_loop.js.map
@@ -103,7 +103,9 @@ class StatementParser {
103
103
  lazyUnknown(wa) {
104
104
  const result = [];
105
105
  for (let statement of wa.statements) {
106
- if (statement.get() instanceof _statement_1.Unknown) {
106
+ // dont use CALL METHOD, when executing lazy, it easily gives a Move for the last statment if lazy logic is evaluated
107
+ if (statement.get() instanceof _statement_1.Unknown
108
+ && statement.concatTokens().toUpperCase().startsWith("CALL METHOD ") === false) {
107
109
  for (const { first, second } of this.buildSplits(statement.getTokens())) {
108
110
  const s = this.categorizeStatement(new nodes_1.StatementNode(new _statement_1.Unknown()).setChildren(this.tokensToNodes(second)));
109
111
  if (!(s.get() instanceof _statement_1.Unknown)) {
@@ -9,7 +9,11 @@ class Constant {
9
9
  return new basic_1.IntegerType("I");
10
10
  }
11
11
  else if (node.getFirstToken().getStr().startsWith("'")) {
12
- return new basic_1.CharacterType(10);
12
+ let len = node.getFirstToken().getStr().length - 2;
13
+ if (len <= 0) {
14
+ len = 1;
15
+ }
16
+ return new basic_1.CharacterType(len);
13
17
  }
14
18
  else {
15
19
  return new basic_1.StringType("STRING");
@@ -68,7 +68,7 @@ class Registry {
68
68
  }
69
69
  static abaplintVersion() {
70
70
  // magic, see build script "version.sh"
71
- return "2.85.29";
71
+ return "2.85.32";
72
72
  }
73
73
  getDDICReferences() {
74
74
  return this.references;
@@ -291,8 +291,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
291
291
  }
292
292
  }
293
293
  downportSelectInline(low, high, lowFile, highSyntax) {
294
- if (!(low.get() instanceof _statement_1.Unknown)
295
- || !(high.get() instanceof Statements.Select)) {
294
+ if (!(low.get() instanceof _statement_1.Unknown)) {
295
+ return undefined;
296
+ }
297
+ else if (!(high.get() instanceof Statements.Select) && !(high.get() instanceof Statements.SelectLoop)) {
296
298
  return undefined;
297
299
  }
298
300
  // as first step outline the @DATA, note that void types are okay, as long the field names are specified
@@ -307,7 +309,7 @@ Only one transformation is applied to a statement at a time, so multiple steps m
307
309
  return undefined;
308
310
  }
309
311
  downportSelectSingleInline(_low, high, lowFile, _highSyntax) {
310
- var _a, _b, _c;
312
+ var _a, _b, _c, _d;
311
313
  const targets = ((_a = high.findFirstExpression(Expressions.SQLIntoStructure)) === null || _a === void 0 ? void 0 : _a.findDirectExpressions(Expressions.SQLTarget)) || [];
312
314
  if (targets.length !== 1) {
313
315
  return undefined;
@@ -325,7 +327,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
325
327
  return undefined;
326
328
  }
327
329
  const indentation = " ".repeat(high.getFirstToken().getStart().getCol() - 1);
328
- const fieldList = high.findFirstExpression(Expressions.SQLFieldList);
330
+ let fieldList = high.findFirstExpression(Expressions.SQLFieldList);
331
+ if (fieldList === undefined) {
332
+ fieldList = high.findFirstExpression(Expressions.SQLFieldListLoop);
333
+ }
329
334
  if (fieldList === undefined) {
330
335
  return undefined;
331
336
  }
@@ -341,6 +346,13 @@ Only one transformation is applied to a statement at a time, so multiple steps m
341
346
  else if (fieldList.concatTokens().toUpperCase() === "COUNT( * )") {
342
347
  fieldDefinition = `DATA ${name} TYPE i.`;
343
348
  }
349
+ else if (fieldList.getChildren().length === 1 && fieldList.getChildren()[0].get() instanceof Expressions.SQLAggregation) {
350
+ const c = fieldList.getChildren()[0];
351
+ if (c instanceof nodes_1.ExpressionNode) {
352
+ const concat = (_d = c.findFirstExpression(Expressions.SQLArithmetics)) === null || _d === void 0 ? void 0 : _d.concatTokens();
353
+ fieldDefinition = `DATA ${name} TYPE ${tableName}-${concat}.`;
354
+ }
355
+ }
344
356
  else {
345
357
  for (const f of fields) {
346
358
  const fieldName = f.concatTokens();
@@ -361,26 +373,31 @@ ${indentation}`);
361
373
  if (targets.length !== 1) {
362
374
  return undefined;
363
375
  }
376
+ const indentation = " ".repeat(high.getFirstToken().getStart().getCol() - 1);
364
377
  const inlineData = targets[0].findFirstExpression(Expressions.InlineData);
365
378
  if (inlineData === undefined) {
366
379
  return undefined;
367
380
  }
368
381
  const sqlFrom = high.findAllExpressions(Expressions.SQLFromSource);
369
- if (sqlFrom.length !== 1) {
370
- return undefined;
382
+ if (sqlFrom.length === 0) {
383
+ return issue_1.Issue.atToken(lowFile, high.getFirstToken(), "Error outlining, sqlFrom not found", this.getMetadata().key, this.conf.severity);
371
384
  }
372
- const tableName = (_b = sqlFrom[0].findDirectExpression(Expressions.DatabaseTable)) === null || _b === void 0 ? void 0 : _b.concatTokens();
385
+ let tableName = (_b = sqlFrom[0].findDirectExpression(Expressions.DatabaseTable)) === null || _b === void 0 ? void 0 : _b.concatTokens();
373
386
  if (tableName === undefined) {
374
387
  return undefined;
375
388
  }
376
- const indentation = " ".repeat(high.getFirstToken().getStart().getCol() - 1);
377
389
  const fieldList = high.findFirstExpression(Expressions.SQLFieldList);
378
390
  if (fieldList === undefined) {
379
391
  return undefined;
380
392
  }
381
393
  let fieldDefinitions = "";
382
394
  for (const f of fieldList.findDirectExpressions(Expressions.SQLFieldName)) {
383
- const fieldName = f.concatTokens();
395
+ let fieldName = f.concatTokens();
396
+ if (fieldName.includes("~")) {
397
+ const split = fieldName.split("~");
398
+ fieldName = split[0];
399
+ tableName = split[1];
400
+ }
384
401
  fieldDefinitions += indentation + " " + fieldName + " TYPE " + tableName + "-" + fieldName + ",\n";
385
402
  }
386
403
  const uniqueName = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
@@ -477,6 +494,7 @@ ${indentation}`);
477
494
  if (!(((_a = target === null || target === void 0 ? void 0 : target.getFirstChild()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.InlineData)) {
478
495
  return undefined;
479
496
  }
497
+ let type = "";
480
498
  const source = node.findFirstExpression(Expressions.Source);
481
499
  if (source === undefined) {
482
500
  return undefined;
@@ -494,13 +512,25 @@ ${indentation}`);
494
512
  return undefined;
495
513
  }
496
514
  else if (source.findFirstExpression(Expressions.TableExpression)) {
497
- return undefined;
515
+ const chain = source.findDirectExpression(Expressions.FieldChain);
516
+ if (chain !== undefined
517
+ && chain.getChildren().length === 2
518
+ && chain.getChildren()[0].get() instanceof Expressions.SourceField
519
+ && chain.getChildren()[1].get() instanceof Expressions.TableExpression) {
520
+ type = "LINE OF " + chain.getChildren()[0].concatTokens();
521
+ }
522
+ else {
523
+ return undefined;
524
+ }
525
+ }
526
+ else {
527
+ type = source.concatTokens();
498
528
  }
499
529
  const targetName = (_c = target.findFirstExpression(Expressions.TargetField)) === null || _c === void 0 ? void 0 : _c.concatTokens();
500
530
  const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
501
531
  const firstToken = node.getFirstToken();
502
532
  const lastToken = node.getLastToken();
503
- const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, firstToken.getStart(), `DATA ${targetName} LIKE ${source.concatTokens()}.\n${indentation}`);
533
+ const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, firstToken.getStart(), `DATA ${targetName} LIKE ${type}.\n${indentation}`);
504
534
  const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, firstToken.getStart(), lastToken.getEnd(), `${targetName} = ${source.concatTokens()}.`);
505
535
  const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
506
536
  return issue_1.Issue.atToken(lowFile, node.getFirstToken(), "Outline DATA", this.getMetadata().key, this.conf.severity, fix);
@@ -1007,15 +1037,22 @@ ${indentation} output = ${topTarget}.`;
1007
1037
  if (spag === undefined) {
1008
1038
  continue;
1009
1039
  }
1010
- const found = spag.findVariable(name);
1011
- if (found === undefined) {
1012
- continue;
1040
+ let type = "";
1041
+ if (node.concatTokens().toUpperCase().startsWith("APPEND INITIAL LINE TO ")) {
1042
+ type = "LIKE LINE OF " + ((_b = node.findFirstExpression(Expressions.Target)) === null || _b === void 0 ? void 0 : _b.concatTokens());
1013
1043
  }
1014
- else if (found.getType() instanceof basic_1.VoidType) {
1015
- return issue_1.Issue.atToken(lowFile, i.getFirstToken(), "Error outlining voided type", this.getMetadata().key, this.conf.severity);
1044
+ else {
1045
+ const found = spag.findVariable(name);
1046
+ if (found === undefined) {
1047
+ continue;
1048
+ }
1049
+ else if (found.getType() instanceof basic_1.VoidType) {
1050
+ return issue_1.Issue.atToken(lowFile, i.getFirstToken(), "Error outlining voided type", this.getMetadata().key, this.conf.severity);
1051
+ }
1052
+ type = "TYPE ";
1053
+ type += found.getType().getQualifiedName() ? found.getType().getQualifiedName().toLowerCase() : found.getType().toABAP();
1016
1054
  }
1017
- const type = found.getType().getQualifiedName() ? (_b = found.getType().getQualifiedName()) === null || _b === void 0 ? void 0 : _b.toLowerCase() : found.getType().toABAP();
1018
- const code = `FIELD-SYMBOLS ${name} TYPE ${type}.\n` +
1055
+ const code = `FIELD-SYMBOLS ${name} ${type}.\n` +
1019
1056
  " ".repeat(node.getFirstToken().getStart().getCol() - 1);
1020
1057
  const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), code);
1021
1058
  const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, i.getFirstToken().getStart(), i.getLastToken().getEnd(), name);
@@ -1076,11 +1113,18 @@ ${indentation} output = ${topTarget}.`;
1076
1113
  }
1077
1114
  buildCondBody(body, uniqueName, indent, lowFile, highSyntax) {
1078
1115
  let code = "";
1116
+ let first = true;
1079
1117
  for (const c of body.getChildren()) {
1080
1118
  if (c instanceof nodes_1.TokenNode) {
1081
1119
  switch (c.getFirstToken().getStr().toUpperCase()) {
1082
1120
  case "WHEN":
1083
- code += indent + "IF ";
1121
+ if (first === true) {
1122
+ code += indent + "IF ";
1123
+ first = false;
1124
+ }
1125
+ else {
1126
+ code += indent + "ELSEIF ";
1127
+ }
1084
1128
  break;
1085
1129
  case "THEN":
1086
1130
  code += ".\n";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.85.29",
3
+ "version": "2.85.32",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",