@abaplint/core 2.91.3 → 2.91.6

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.
@@ -1124,6 +1124,7 @@ export declare class CurrentScope {
1124
1124
  static buildDefault(reg: IRegistry, obj: IObject): CurrentScope;
1125
1125
  private static addBuiltIn;
1126
1126
  private constructor();
1127
+ getVersion(): Version;
1127
1128
  addType(type: TypedIdentifier | undefined): void;
1128
1129
  addTypeNamed(name: string, type: TypedIdentifier | undefined): void;
1129
1130
  addExtraLikeType(type: TypedIdentifier | undefined): void;
@@ -2741,9 +2742,9 @@ declare interface IFunctionModuleParameter {
2741
2742
  declare interface IGlobalConfig {
2742
2743
  /** input files, glob format */
2743
2744
  files: string;
2744
- skipGeneratedGatewayClasses: boolean;
2745
- skipGeneratedPersistentClasses: boolean;
2746
- skipGeneratedFunctionGroups: boolean;
2745
+ skipGeneratedGatewayClasses?: boolean;
2746
+ skipGeneratedPersistentClasses?: boolean;
2747
+ skipGeneratedFunctionGroups?: boolean;
2747
2748
  /** Clone and parse dependencies specified in .apack-manifest.xml if it is present */
2748
2749
  useApackDependencies?: boolean;
2749
2750
  /** Do not report any issues for includes without main programs */
@@ -14,10 +14,9 @@ class Select extends combi_1.Expression {
14
14
  const into = (0, combi_1.altPrio)(_1.SQLIntoTable, sql_into_structure_1.SQLIntoStructure);
15
15
  const where = (0, combi_1.seq)("WHERE", _1.SQLCond);
16
16
  const offset = (0, combi_1.ver)(version_1.Version.v751, (0, combi_1.seq)("OFFSET", _1.SQLSource));
17
- const client = (0, combi_1.str)("CLIENT SPECIFIED");
18
17
  const bypass = (0, combi_1.str)("BYPASSING BUFFER");
19
18
  const fields = (0, combi_1.seq)("FIELDS", _1.SQLFieldList);
20
- const perm = (0, combi_1.per)(_1.SQLFrom, into, _1.SQLForAllEntries, where, _1.SQLOrderBy, sql_up_to_1.SQLUpTo, offset, client, _1.SQLHaving, bypass, sql_group_by_1.SQLGroupBy, fields, _1.DatabaseConnection);
19
+ const perm = (0, combi_1.per)(_1.SQLFrom, into, _1.SQLForAllEntries, where, _1.SQLOrderBy, sql_up_to_1.SQLUpTo, offset, _1.SQLClient, _1.SQLHaving, bypass, sql_group_by_1.SQLGroupBy, fields, _1.DatabaseConnection);
21
20
  const paren = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.WParenLeftW), sql_field_name_1.SQLFieldName, (0, combi_1.tok)(tokens_1.WParenRightW));
22
21
  const ret = (0, combi_1.seq)("SELECT", (0, combi_1.altPrio)("DISTINCT", (0, combi_1.optPrio)((0, combi_1.seq)("SINGLE", (0, combi_1.optPrio)("FOR UPDATE")))), (0, combi_1.optPrio)((0, combi_1.altPrio)(_1.SQLFieldList, paren)), perm, (0, combi_1.optPrio)(_1.SQLHints));
23
22
  return ret;
@@ -13,11 +13,10 @@ const sql_up_to_1 = require("./sql_up_to");
13
13
  class SelectLoop extends combi_1.Expression {
14
14
  getRunnable() {
15
15
  const where = (0, combi_1.seq)("WHERE", _1.SQLCond);
16
- const client = "CLIENT SPECIFIED";
17
16
  const bypass = "BYPASSING BUFFER";
18
17
  const pack = (0, combi_1.seq)("PACKAGE SIZE", _1.SQLSource);
19
18
  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)));
20
- const perm = (0, combi_1.per)(_1.SQLFrom, where, sql_up_to_1.SQLUpTo, 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));
19
+ const perm = (0, combi_1.per)(_1.SQLFrom, where, sql_up_to_1.SQLUpTo, sql_order_by_1.SQLOrderBy, sql_having_1.SQLHaving, _1.SQLClient, bypass, _1.SQLGroupBy, _1.SQLForAllEntries, (0, combi_1.alt)(tab, sql_into_structure_1.SQLIntoStructure));
21
20
  const strict = (0, combi_1.seq)(_1.SQLFrom, "FIELDS", sql_field_list_1.SQLFieldList, where, sql_into_structure_1.SQLIntoStructure, sql_up_to_1.SQLUpTo);
22
21
  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));
23
22
  return ret;
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SQLClient = void 0;
4
+ const version_1 = require("../../../version");
4
5
  const combi_1 = require("../combi");
5
6
  const sql_source_simple_1 = require("./sql_source_simple");
6
7
  class SQLClient extends combi_1.Expression {
7
8
  getRunnable() {
8
9
  // todo, client specified and connection not possible in Cloud
9
- const client = (0, combi_1.alt)("CLIENT SPECIFIED", (0, combi_1.seq)("USING CLIENT", sql_source_simple_1.SQLSourceSimple));
10
+ const client = (0, combi_1.alt)("CLIENT SPECIFIED", (0, combi_1.seq)("USING", (0, combi_1.alt)((0, combi_1.ver)(version_1.Version.v740sp05, (0, combi_1.seq)("CLIENT", sql_source_simple_1.SQLSourceSimple)), (0, combi_1.ver)(version_1.Version.v754, (0, combi_1.seq)("CLIENTS IN", (0, combi_1.alt)(sql_source_simple_1.SQLSourceSimple, "T000"))), (0, combi_1.ver)(version_1.Version.v754, "ALL CLIENTS"))));
10
11
  return client;
11
12
  }
12
13
  }
@@ -9,10 +9,11 @@ class DeleteInternal {
9
9
  const index = (0, combi_1.seq)("INDEX", expressions_1.Source);
10
10
  const keyName = (0, combi_1.altPrio)(expressions_1.SimpleName, expressions_1.Dynamic);
11
11
  const using = (0, combi_1.seq)("USING KEY", keyName);
12
- const fromTo = (0, combi_1.seq)((0, combi_1.optPrio)((0, combi_1.seq)("FROM", expressions_1.Source)), (0, combi_1.optPrio)((0, combi_1.seq)("TO", expressions_1.Source)));
12
+ const from = (0, combi_1.optPrio)((0, combi_1.seq)("FROM", expressions_1.Source));
13
+ const fromTo = (0, combi_1.seq)(from, (0, combi_1.optPrio)((0, combi_1.seq)("TO", expressions_1.Source)));
13
14
  const where = (0, combi_1.seq)("WHERE", (0, combi_1.alt)(expressions_1.ComponentCond, expressions_1.Dynamic));
14
15
  const key = (0, combi_1.seq)("WITH TABLE KEY", (0, combi_1.opt)((0, combi_1.seq)(keyName, "COMPONENTS")), (0, combi_1.plus)(expressions_1.ComponentCompare));
15
- const table = (0, combi_1.seq)("TABLE", expressions_1.Target, (0, combi_1.alt)((0, combi_1.per)(index, using), fromTo, key));
16
+ const table = (0, combi_1.seq)("TABLE", expressions_1.Target, (0, combi_1.alt)((0, combi_1.per)(index, using), from, key));
16
17
  const other = (0, combi_1.seq)(expressions_1.Target, (0, combi_1.alt)((0, combi_1.per)(index, using), fromTo, key), (0, combi_1.opt)(where));
17
18
  const f = (0, combi_1.seq)(expressions_1.FieldSub, (0, combi_1.optPrio)(expressions_1.FieldOffset), (0, combi_1.optPrio)(expressions_1.FieldLength));
18
19
  const adjacent = (0, combi_1.seq)("ADJACENT DUPLICATES FROM", expressions_1.Target, (0, combi_1.optPrio)(using), (0, combi_1.opt)((0, combi_1.seq)("COMPARING", (0, combi_1.altPrio)("ALL FIELDS", (0, combi_1.plus)((0, combi_1.altPrio)(f, expressions_1.Dynamic))))), (0, combi_1.optPrio)(using));
@@ -6,11 +6,10 @@ const expressions_1 = require("../expressions");
6
6
  const tokens_1 = require("../../1_lexer/tokens");
7
7
  class InsertDatabase {
8
8
  getMatcher() {
9
- const client = (0, combi_1.str)("CLIENT SPECIFIED");
10
9
  const sub = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.WParenLeftW), expressions_1.Select, (0, combi_1.tok)(tokens_1.WParenRightW));
11
- const f = (0, combi_1.seq)((0, combi_1.opt)(client), (0, combi_1.opt)(expressions_1.DatabaseConnection), "FROM", (0, combi_1.opt)("TABLE"), (0, combi_1.alt)(expressions_1.SQLSource, sub), (0, combi_1.opt)("ACCEPTING DUPLICATE KEYS"));
12
- const from = (0, combi_1.seq)(expressions_1.DatabaseTable, (0, combi_1.opt)((0, combi_1.alt)(f, client, expressions_1.DatabaseConnection)));
13
- const into = (0, combi_1.seq)("INTO", expressions_1.DatabaseTable, (0, combi_1.opt)("CLIENT SPECIFIED"), (0, combi_1.opt)(expressions_1.DatabaseConnection), "VALUES", expressions_1.SQLSource);
10
+ const f = (0, combi_1.seq)((0, combi_1.opt)(expressions_1.SQLClient), (0, combi_1.opt)(expressions_1.DatabaseConnection), "FROM", (0, combi_1.opt)("TABLE"), (0, combi_1.alt)(expressions_1.SQLSource, sub), (0, combi_1.opt)("ACCEPTING DUPLICATE KEYS"));
11
+ const from = (0, combi_1.seq)(expressions_1.DatabaseTable, (0, combi_1.opt)((0, combi_1.alt)(f, expressions_1.SQLClient, expressions_1.DatabaseConnection)));
12
+ const into = (0, combi_1.seq)("INTO", expressions_1.DatabaseTable, (0, combi_1.opt)(expressions_1.SQLClient), (0, combi_1.opt)(expressions_1.DatabaseConnection), "VALUES", expressions_1.SQLSource);
14
13
  return (0, combi_1.seq)("INSERT", (0, combi_1.alt)(from, into));
15
14
  }
16
15
  }
@@ -6,8 +6,7 @@ const expressions_1 = require("../expressions");
6
6
  class ModifyDatabase {
7
7
  getMatcher() {
8
8
  const from = (0, combi_1.seq)("FROM", (0, combi_1.opt)("TABLE"), expressions_1.SQLSource);
9
- const client = (0, combi_1.str)("CLIENT SPECIFIED");
10
- const options = (0, combi_1.per)(expressions_1.DatabaseConnection, from, client);
9
+ const options = (0, combi_1.per)(expressions_1.DatabaseConnection, from, expressions_1.SQLClient);
11
10
  return (0, combi_1.seq)("MODIFY", expressions_1.DatabaseTable, options);
12
11
  }
13
12
  }
@@ -35,6 +35,9 @@ class CurrentScope {
35
35
  }
36
36
  }
37
37
  ///////////////////////////
38
+ getVersion() {
39
+ return this.reg.getConfig().getVersion();
40
+ }
38
41
  addType(type) {
39
42
  if (type === undefined) {
40
43
  return;
@@ -4,13 +4,24 @@ exports.MoveCorresponding = void 0;
4
4
  const Expressions = require("../../2_statements/expressions");
5
5
  const source_1 = require("../expressions/source");
6
6
  const target_1 = require("../expressions/target");
7
+ const version_1 = require("../../../version");
8
+ const basic_1 = require("../../types/basic");
7
9
  class MoveCorresponding {
8
10
  runSyntax(node, scope, filename) {
9
- for (const s of node.findDirectExpressions(Expressions.Source)) {
10
- new source_1.Source().runSyntax(s, scope, filename);
11
+ const s = node.findDirectExpression(Expressions.Source);
12
+ const t = node.findDirectExpression(Expressions.Target);
13
+ if (s === undefined || t === undefined) {
14
+ throw new Error("MoveCorresponding, source or target not found");
11
15
  }
12
- for (const t of node.findDirectExpressions(Expressions.Target)) {
13
- new target_1.Target().runSyntax(t, scope, filename);
16
+ const sourceType = new source_1.Source().runSyntax(s, scope, filename);
17
+ const targetType = new target_1.Target().runSyntax(t, scope, filename);
18
+ if (scope.getVersion() < version_1.Version.v740sp05) {
19
+ if (sourceType instanceof basic_1.TableType && sourceType.isWithHeader() === false) {
20
+ throw new Error("MOVE-CORRESPONSING with tables possible from v740sp05");
21
+ }
22
+ else if (targetType instanceof basic_1.TableType && targetType.isWithHeader() === false) {
23
+ throw new Error("MOVE-CORRESPONSING with tables possible from v740sp05");
24
+ }
14
25
  }
15
26
  }
16
27
  }
@@ -68,7 +68,7 @@ class Registry {
68
68
  }
69
69
  static abaplintVersion() {
70
70
  // magic, see build script "version.sh"
71
- return "2.91.3";
71
+ return "2.91.6";
72
72
  }
73
73
  getDDICReferences() {
74
74
  return this.references;
@@ -65,6 +65,8 @@ class ObsoleteStatementConf extends _basic_rule_config_1.BasicRuleConfig {
65
65
  this.regex = true;
66
66
  /** Check for OCCURENCES vs OCCURRENCES usage */
67
67
  this.occurences = true;
68
+ /** Check for CLIENT SPECIFIED */
69
+ this.clientSpecified = true;
68
70
  }
69
71
  }
70
72
  exports.ObsoleteStatementConf = ObsoleteStatementConf;
@@ -119,7 +121,9 @@ CALL TRANSFORMATION OBJECTS: https://help.sap.com/doc/abapdocu_752_index_htm/7.5
119
121
 
120
122
  POSIX REGEX: https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.htm
121
123
 
122
- OCCURENCES: check for OCCURENCES vs OCCURRENCES`,
124
+ OCCURENCES: check for OCCURENCES vs OCCURRENCES
125
+
126
+ CLIENT SPECIFIED, from 754: https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapselect_client_obsolete.htm`,
123
127
  };
124
128
  }
125
129
  getConfig() {
@@ -229,7 +233,7 @@ OCCURENCES: check for OCCURENCES vs OCCURRENCES`,
229
233
  }
230
234
  if (this.conf.withHeaderLine === true && sta instanceof Statements.Data) {
231
235
  if (staNode.concatTokens().toUpperCase().includes("WITH HEADER LINE")) {
232
- const token = staNode.getFirstToken();
236
+ const token = staNode.getTokens().find(t => t.getStr().toUpperCase() === "WITH");
233
237
  if (token) {
234
238
  const issue = issue_1.Issue.atToken(file, token, "WITH HEADER LINE is obsolete", this.getMetadata().key, this.conf.severity);
235
239
  issues.push(issue);
@@ -283,6 +287,19 @@ OCCURENCES: check for OCCURENCES vs OCCURRENCES`,
283
287
  issues.push(issue);
284
288
  }
285
289
  }
290
+ if (configVersion >= version_1.Version.v754 && this.conf.clientSpecified
291
+ && (sta instanceof Statements.Select
292
+ || sta instanceof Statements.SelectLoop
293
+ || sta instanceof Statements.DeleteDatabase
294
+ || sta instanceof Statements.InsertDatabase
295
+ || sta instanceof Statements.ModifyDatabase
296
+ || sta instanceof Statements.UpdateDatabase)) {
297
+ const concat = staNode.concatTokens().toUpperCase();
298
+ if (concat.includes(" CLIENT SPECIFIED")) {
299
+ const issue = issue_1.Issue.atStatement(file, staNode, "Use USING CLIENT", this.getMetadata().key, this.conf.severity);
300
+ issues.push(issue);
301
+ }
302
+ }
286
303
  if (configVersion >= version_1.Version.v756 && this.conf.regex) {
287
304
  if (sta instanceof Statements.Find || sta instanceof Statements.Replace) {
288
305
  if ((_c = staNode.findFirstExpression(Expressions.FindType)) === null || _c === void 0 ? void 0 : _c.concatTokens().includes("REGEX")) {
@@ -36,6 +36,11 @@ class SelectPerformance {
36
36
 
37
37
  SELECT *: not reported if using INTO/APPENDING CORRESPONDING FIELDS OF`,
38
38
  tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Performance],
39
+ badExample: `SELECT field1, field2 FROM table
40
+ INTO @DATA(structure) UP TO 1 ROWS ORDER BY field3 DESCENDING.
41
+ ENDSELECT.`,
42
+ goodExample: `SELECT field1, field2 FROM table UP TO 1 ROWS
43
+ INTO TABLE @DATA(table) ORDER BY field3 DESCENDING`,
39
44
  };
40
45
  }
41
46
  initialize(reg) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.91.3",
3
+ "version": "2.91.6",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -45,17 +45,17 @@
45
45
  },
46
46
  "homepage": "https://abaplint.org",
47
47
  "devDependencies": {
48
- "@microsoft/api-extractor": "^7.25.0",
48
+ "@microsoft/api-extractor": "^7.28.3",
49
49
  "@types/chai": "^4.3.1",
50
50
  "@types/mocha": "^9.1.1",
51
- "@types/node": "^17.0.41",
51
+ "@types/node": "^18.0.3",
52
52
  "chai": "^4.3.6",
53
- "eslint": "^8.17.0",
53
+ "eslint": "^8.19.0",
54
54
  "mocha": "^10.0.0",
55
55
  "c8": "^7.11.3",
56
56
  "source-map-support": "^0.5.21",
57
57
  "ts-json-schema-generator": "^1.0.0",
58
- "typescript": "^4.7.3"
58
+ "typescript": "^4.7.4"
59
59
  },
60
60
  "dependencies": {
61
61
  "fast-xml-parser": "^4.0.8",