@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.
- package/build/abaplint.d.ts +4 -3
- package/build/src/abap/2_statements/expressions/select.js +1 -2
- package/build/src/abap/2_statements/expressions/select_loop.js +1 -2
- package/build/src/abap/2_statements/expressions/sql_client.js +2 -1
- package/build/src/abap/2_statements/statements/delete_internal.js +3 -2
- package/build/src/abap/2_statements/statements/insert_database.js +3 -4
- package/build/src/abap/2_statements/statements/modify_database.js +1 -2
- package/build/src/abap/5_syntax/_current_scope.js +3 -0
- package/build/src/abap/5_syntax/statements/move_corresponding.js +15 -4
- package/build/src/registry.js +1 -1
- package/build/src/rules/obsolete_statement.js +19 -2
- package/build/src/rules/select_performance.js +5 -0
- package/package.json +5 -5
package/build/abaplint.d.ts
CHANGED
|
@@ -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
|
|
2745
|
-
skipGeneratedPersistentClasses
|
|
2746
|
-
skipGeneratedFunctionGroups
|
|
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,
|
|
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,
|
|
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
|
|
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),
|
|
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)(
|
|
12
|
-
const from = (0, combi_1.seq)(expressions_1.DatabaseTable, (0, combi_1.opt)((0, combi_1.alt)(f,
|
|
13
|
-
const into = (0, combi_1.seq)("INTO", expressions_1.DatabaseTable, (0, combi_1.opt)(
|
|
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
|
|
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
|
}
|
|
@@ -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
|
-
|
|
10
|
-
|
|
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
|
-
|
|
13
|
-
|
|
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
|
}
|
package/build/src/registry.js
CHANGED
|
@@ -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.
|
|
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
|
+
"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.
|
|
48
|
+
"@microsoft/api-extractor": "^7.28.3",
|
|
49
49
|
"@types/chai": "^4.3.1",
|
|
50
50
|
"@types/mocha": "^9.1.1",
|
|
51
|
-
"@types/node": "^
|
|
51
|
+
"@types/node": "^18.0.3",
|
|
52
52
|
"chai": "^4.3.6",
|
|
53
|
-
"eslint": "^8.
|
|
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.
|
|
58
|
+
"typescript": "^4.7.4"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"fast-xml-parser": "^4.0.8",
|