@abaplint/core 2.94.4 → 2.94.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 +2 -0
- package/build/src/abap/5_syntax/_builtin.js +2 -1
- package/build/src/abap/5_syntax/basic_types.js +4 -0
- package/build/src/abap/5_syntax/expressions/method_call_body.js +5 -0
- package/build/src/abap/5_syntax/spaghetti_scope.js +9 -0
- package/build/src/abap/5_syntax/statements/modify_database.js +11 -6
- package/build/src/registry.js +1 -1
- package/build/src/rules/change_if_to_case.js +6 -1
- package/build/src/rules/modify_only_own_db_tables.js +47 -28
- package/build/src/rules/omit_parameter_name.js +11 -5
- package/build/src/rules/static_call_via_instance.js +8 -0
- package/package.json +3 -3
package/build/abaplint.d.ts
CHANGED
|
@@ -3502,6 +3502,7 @@ export declare interface ISpaghettiScopeNode {
|
|
|
3502
3502
|
findScopeForVariable(name: string): IScopeIdentifier | undefined;
|
|
3503
3503
|
findWriteReference(pos: Position): TypedIdentifier | undefined;
|
|
3504
3504
|
findTableReference(pos: Position): string | undefined;
|
|
3505
|
+
findTableVoidReference(pos: Position): boolean;
|
|
3505
3506
|
}
|
|
3506
3507
|
|
|
3507
3508
|
export declare class Issue {
|
|
@@ -5101,6 +5102,7 @@ export declare class SpaghettiScopeNode extends ScopeData implements ISpaghettiS
|
|
|
5101
5102
|
findVariable(name: string): TypedIdentifier | undefined;
|
|
5102
5103
|
findWriteReference(pos: Position): TypedIdentifier | undefined;
|
|
5103
5104
|
findTableReference(pos: Position): string | undefined;
|
|
5105
|
+
findTableVoidReference(pos: Position): boolean;
|
|
5104
5106
|
findScopeForVariable(name: string): IScopeIdentifier | undefined;
|
|
5105
5107
|
}
|
|
5106
5108
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BuiltIn = void 0;
|
|
3
|
+
exports.BuiltIn = exports.BuiltInMethod = void 0;
|
|
4
4
|
/* eslint-disable max-len */
|
|
5
5
|
const _typed_identifier_1 = require("../types/_typed_identifier");
|
|
6
6
|
const basic_1 = require("../types/basic");
|
|
@@ -84,6 +84,7 @@ class BuiltInMethod extends _identifier_1.Identifier {
|
|
|
84
84
|
return undefined;
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
+
exports.BuiltInMethod = BuiltInMethod;
|
|
87
88
|
class BuiltIn {
|
|
88
89
|
constructor() {
|
|
89
90
|
this.row = 1;
|
|
@@ -675,6 +675,7 @@ class BasicTypes {
|
|
|
675
675
|
}
|
|
676
676
|
resolveConstantValue(expr) {
|
|
677
677
|
var _a, _b;
|
|
678
|
+
// todo: rewrite this method
|
|
678
679
|
if (!(expr.get() instanceof Expressions.SimpleFieldChain)) {
|
|
679
680
|
throw new Error("resolveConstantValue");
|
|
680
681
|
}
|
|
@@ -688,6 +689,9 @@ class BasicTypes {
|
|
|
688
689
|
this.scope.addReference(firstToken, found, _reference_1.ReferenceType.DataReadReference, this.filename);
|
|
689
690
|
return val;
|
|
690
691
|
}
|
|
692
|
+
else if ((found === null || found === void 0 ? void 0 : found.getType()) instanceof basic_1.StructureType) {
|
|
693
|
+
this.scope.addReference(firstToken, found, _reference_1.ReferenceType.DataReadReference, this.filename);
|
|
694
|
+
}
|
|
691
695
|
return undefined;
|
|
692
696
|
}
|
|
693
697
|
else if (firstNode.get() instanceof Expressions.ClassName
|
|
@@ -4,12 +4,17 @@ exports.MethodCallBody = void 0;
|
|
|
4
4
|
const Expressions = require("../../2_statements/expressions");
|
|
5
5
|
const method_parameters_1 = require("./method_parameters");
|
|
6
6
|
const source_1 = require("./source");
|
|
7
|
+
const method_call_param_1 = require("./method_call_param");
|
|
7
8
|
class MethodCallBody {
|
|
8
9
|
runSyntax(node, scope, filename, method) {
|
|
9
10
|
const parameters = node.findDirectExpression(Expressions.MethodParameters);
|
|
10
11
|
if (parameters) {
|
|
11
12
|
new method_parameters_1.MethodParameters().runSyntax(parameters, scope, method, filename);
|
|
12
13
|
}
|
|
14
|
+
const param = node.findDirectExpression(Expressions.MethodCallParam);
|
|
15
|
+
if (param) {
|
|
16
|
+
new method_call_param_1.MethodCallParam().runSyntax(param, scope, method, filename);
|
|
17
|
+
}
|
|
13
18
|
for (const s of node.findDirectExpressions(Expressions.Source)) {
|
|
14
19
|
new source_1.Source().runSyntax(s, scope, filename);
|
|
15
20
|
}
|
|
@@ -171,6 +171,15 @@ class SpaghettiScopeNode extends ScopeData {
|
|
|
171
171
|
}
|
|
172
172
|
return undefined;
|
|
173
173
|
}
|
|
174
|
+
findTableVoidReference(pos) {
|
|
175
|
+
for (const r of this.getData().references) {
|
|
176
|
+
if (r.referenceType === _reference_1.ReferenceType.TableVoidReference
|
|
177
|
+
&& r.position.getStart().equals(pos)) {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
174
183
|
// TODO, this method can be deleted? its only used in tests?
|
|
175
184
|
findScopeForVariable(name) {
|
|
176
185
|
let search = this;
|
|
@@ -5,6 +5,7 @@ const Expressions = require("../../2_statements/expressions");
|
|
|
5
5
|
const dynamic_1 = require("../expressions/dynamic");
|
|
6
6
|
const database_table_1 = require("../expressions/database_table");
|
|
7
7
|
const source_1 = require("../expressions/source");
|
|
8
|
+
const _reference_1 = require("../_reference");
|
|
8
9
|
class ModifyDatabase {
|
|
9
10
|
runSyntax(node, scope, filename) {
|
|
10
11
|
for (const d of node.findAllExpressions(Expressions.Dynamic)) {
|
|
@@ -12,14 +13,18 @@ class ModifyDatabase {
|
|
|
12
13
|
}
|
|
13
14
|
const dbtab = node.findFirstExpression(Expressions.DatabaseTable);
|
|
14
15
|
if (dbtab !== undefined) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
if (node.getChildren().length === 5) {
|
|
17
|
+
const found = scope.findVariable(dbtab.concatTokens());
|
|
18
|
+
if (found) {
|
|
19
|
+
scope.addReference(dbtab.getFirstToken(), found, _reference_1.ReferenceType.DataWriteReference, filename);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
new database_table_1.DatabaseTable().runSyntax(dbtab, scope, filename);
|
|
21
23
|
}
|
|
22
24
|
}
|
|
25
|
+
else {
|
|
26
|
+
new database_table_1.DatabaseTable().runSyntax(dbtab, scope, filename);
|
|
27
|
+
}
|
|
23
28
|
}
|
|
24
29
|
for (const s of node.findAllExpressions(Expressions.Source)) {
|
|
25
30
|
new source_1.Source().runSyntax(s, scope, filename);
|
package/build/src/registry.js
CHANGED
|
@@ -29,7 +29,9 @@ class ChangeIfToCase extends _abap_rule_1.ABAPRule {
|
|
|
29
29
|
title: "Change IF to CASE",
|
|
30
30
|
shortDescription: `Finds IF constructs that can be changed to CASE`,
|
|
31
31
|
// eslint-disable-next-line max-len
|
|
32
|
-
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-case-to-else-if-for-multiple-alternative-conditions
|
|
32
|
+
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-case-to-else-if-for-multiple-alternative-conditions
|
|
33
|
+
|
|
34
|
+
If the first comparison is a boolean compare, no issue is reported.`,
|
|
33
35
|
tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Styleguide],
|
|
34
36
|
badExample: `IF l_fcat-fieldname EQ 'FOO'.
|
|
35
37
|
ELSEIF l_fcat-fieldname = 'BAR'
|
|
@@ -60,6 +62,9 @@ ENDCASE.`,
|
|
|
60
62
|
if (ifStatement === undefined) {
|
|
61
63
|
continue;
|
|
62
64
|
}
|
|
65
|
+
if (ifStatement.concatTokens().match(/ (abap_true|abap_false)\s*\./i)) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
63
68
|
conds.push(ifStatement === null || ifStatement === void 0 ? void 0 : ifStatement.findDirectExpression(Expressions.Cond));
|
|
64
69
|
for (const ei of i.findDirectStructures(Structures.ElseIf)) {
|
|
65
70
|
conds.push((_a = ei.findDirectStatement(Statements.ElseIf)) === null || _a === void 0 ? void 0 : _a.findDirectExpression(Expressions.Cond));
|
|
@@ -4,9 +4,10 @@ exports.ModifyOnlyOwnDBTables = exports.ModifyOnlyOwnDBTablesConf = void 0;
|
|
|
4
4
|
const Statements = require("../abap/2_statements/statements");
|
|
5
5
|
const Expressions = require("../abap/2_statements/expressions");
|
|
6
6
|
const issue_1 = require("../issue");
|
|
7
|
-
const _abap_rule_1 = require("./_abap_rule");
|
|
8
7
|
const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
9
8
|
const _irule_1 = require("./_irule");
|
|
9
|
+
const _abap_object_1 = require("../objects/_abap_object");
|
|
10
|
+
const syntax_1 = require("../abap/5_syntax/syntax");
|
|
10
11
|
class ModifyOnlyOwnDBTablesConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
11
12
|
constructor() {
|
|
12
13
|
super(...arguments);
|
|
@@ -16,9 +17,8 @@ class ModifyOnlyOwnDBTablesConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
exports.ModifyOnlyOwnDBTablesConf = ModifyOnlyOwnDBTablesConf;
|
|
19
|
-
class ModifyOnlyOwnDBTables
|
|
20
|
+
class ModifyOnlyOwnDBTables {
|
|
20
21
|
constructor() {
|
|
21
|
-
super(...arguments);
|
|
22
22
|
this.conf = new ModifyOnlyOwnDBTablesConf();
|
|
23
23
|
}
|
|
24
24
|
getMetadata() {
|
|
@@ -26,8 +26,8 @@ class ModifyOnlyOwnDBTables extends _abap_rule_1.ABAPRule {
|
|
|
26
26
|
key: "modify_only_own_db_tables",
|
|
27
27
|
title: "Modify only own DB tables",
|
|
28
28
|
shortDescription: `Modify only own DB tables`,
|
|
29
|
-
extendedInformation:
|
|
30
|
-
tags: [_irule_1.RuleTag.Security
|
|
29
|
+
extendedInformation: `https://docs.abapopenchecks.org/checks/26/`,
|
|
30
|
+
tags: [_irule_1.RuleTag.Security],
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
getConfig() {
|
|
@@ -36,33 +36,52 @@ class ModifyOnlyOwnDBTables extends _abap_rule_1.ABAPRule {
|
|
|
36
36
|
setConfig(conf) {
|
|
37
37
|
this.conf = conf;
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
initialize(reg) {
|
|
40
|
+
this.reg = reg;
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
43
|
+
run(obj) {
|
|
40
44
|
var _a;
|
|
41
|
-
|
|
42
|
-
const struc = file.getStructure();
|
|
43
|
-
if (struc === undefined) {
|
|
45
|
+
if (!(obj instanceof _abap_object_1.ABAPObject)) {
|
|
44
46
|
return [];
|
|
45
47
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
48
|
+
let spaghetti = undefined;
|
|
49
|
+
const output = [];
|
|
50
|
+
for (const file of obj.getABAPFiles()) {
|
|
51
|
+
const struc = file.getStructure();
|
|
52
|
+
if (struc === undefined) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
const regExp = new RegExp(this.getConfig().ownTables, "i");
|
|
56
|
+
for (const s of file.getStatements()) {
|
|
57
|
+
const g = s.get();
|
|
58
|
+
if (g instanceof Statements.DeleteDatabase
|
|
59
|
+
|| g instanceof Statements.UpdateDatabase
|
|
60
|
+
|| g instanceof Statements.InsertDatabase
|
|
61
|
+
|| g instanceof Statements.ModifyDatabase) {
|
|
62
|
+
const databaseTable = s.findFirstExpression(Expressions.DatabaseTable);
|
|
63
|
+
if (databaseTable === undefined) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (((_a = databaseTable.getFirstChild()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.Dynamic) {
|
|
67
|
+
if (this.getConfig().reportDynamic === true) {
|
|
68
|
+
output.push(issue_1.Issue.atStatement(file, s, this.getMetadata().title, this.getMetadata().key, this.getConfig().severity));
|
|
69
|
+
}
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const concat = databaseTable.concatTokens().toUpperCase();
|
|
73
|
+
if (regExp.test(concat) === false) {
|
|
74
|
+
// must contain a ReferenceType.TableVoidReference
|
|
75
|
+
if (spaghetti === undefined) {
|
|
76
|
+
spaghetti = new syntax_1.SyntaxLogic(this.reg, obj).run().spaghetti;
|
|
77
|
+
}
|
|
78
|
+
const start = databaseTable.getFirstToken().getStart();
|
|
79
|
+
const scope = spaghetti.lookupPosition(start, file.getFilename());
|
|
80
|
+
const found = scope === null || scope === void 0 ? void 0 : scope.findTableVoidReference(start);
|
|
81
|
+
if (found) {
|
|
82
|
+
output.push(issue_1.Issue.atStatement(file, s, this.getMetadata().title, this.getMetadata().key, this.getConfig().severity));
|
|
83
|
+
}
|
|
60
84
|
}
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
const concat = databaseTable.concatTokens().toUpperCase();
|
|
64
|
-
if (regExp.test(concat) === false && concat !== "SCREEN") {
|
|
65
|
-
output.push(issue_1.Issue.atStatement(file, s, this.getMetadata().title, this.getMetadata().key, this.getConfig().severity));
|
|
66
85
|
}
|
|
67
86
|
}
|
|
68
87
|
}
|
|
@@ -10,6 +10,7 @@ const syntax_1 = require("../abap/5_syntax/syntax");
|
|
|
10
10
|
const _reference_1 = require("../abap/5_syntax/_reference");
|
|
11
11
|
const method_definition_1 = require("../abap/types/method_definition");
|
|
12
12
|
const edit_helper_1 = require("../edit_helper");
|
|
13
|
+
const _builtin_1 = require("../abap/5_syntax/_builtin");
|
|
13
14
|
class OmitParameterNameConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
14
15
|
}
|
|
15
16
|
exports.OmitParameterNameConf = OmitParameterNameConf;
|
|
@@ -74,7 +75,7 @@ EXPORTING must already be omitted for this rule to take effect, https://rules.ab
|
|
|
74
75
|
if (ref === undefined) {
|
|
75
76
|
continue;
|
|
76
77
|
}
|
|
77
|
-
const i = ref.
|
|
78
|
+
const i = ref.getDefaultImporting();
|
|
78
79
|
if (i === undefined) {
|
|
79
80
|
continue;
|
|
80
81
|
}
|
|
@@ -101,12 +102,17 @@ EXPORTING must already be omitted for this rule to take effect, https://rules.ab
|
|
|
101
102
|
return undefined;
|
|
102
103
|
}
|
|
103
104
|
for (const r of scope.getData().references) {
|
|
104
|
-
if (r.referenceType !== _reference_1.ReferenceType.MethodReference
|
|
105
|
+
if (r.referenceType !== _reference_1.ReferenceType.MethodReference
|
|
106
|
+
&& r.referenceType !== _reference_1.ReferenceType.BuiltinMethodReference) {
|
|
105
107
|
continue;
|
|
106
108
|
}
|
|
107
|
-
else if (r.position.getStart().equals(token.getStart())
|
|
108
|
-
|
|
109
|
-
|
|
109
|
+
else if (r.position.getStart().equals(token.getStart())) {
|
|
110
|
+
if (r.resolved instanceof _builtin_1.BuiltInMethod) {
|
|
111
|
+
return r.resolved;
|
|
112
|
+
}
|
|
113
|
+
else if (r.resolved instanceof method_definition_1.MethodDefinition) {
|
|
114
|
+
return r.resolved.getParameters();
|
|
115
|
+
}
|
|
110
116
|
}
|
|
111
117
|
}
|
|
112
118
|
return undefined;
|
|
@@ -10,6 +10,11 @@ const syntax_1 = require("../abap/5_syntax/syntax");
|
|
|
10
10
|
const _reference_1 = require("../abap/5_syntax/_reference");
|
|
11
11
|
const types_1 = require("../abap/types");
|
|
12
12
|
class StaticCallViaInstanceConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
/** Allow in test class includes */
|
|
16
|
+
this.allowInTestclassIncludes = false;
|
|
17
|
+
}
|
|
13
18
|
}
|
|
14
19
|
exports.StaticCallViaInstanceConf = StaticCallViaInstanceConf;
|
|
15
20
|
class StaticCallViaInstance extends _abap_rule_1.ABAPRule {
|
|
@@ -34,6 +39,9 @@ class StaticCallViaInstance extends _abap_rule_1.ABAPRule {
|
|
|
34
39
|
}
|
|
35
40
|
runParsed(file, obj) {
|
|
36
41
|
const issues = [];
|
|
42
|
+
if (this.getConfig().allowInTestclassIncludes === true && file.getFilename().includes(".testclasses.")) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
37
45
|
const staticMethodCalls = this.listMethodCalls(file.getFilename(), new syntax_1.SyntaxLogic(this.reg, obj).run().spaghetti.getTop());
|
|
38
46
|
const tokens = file.getTokens();
|
|
39
47
|
for (let i = 0; i < tokens.length - 1; i++) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abaplint/core",
|
|
3
|
-
"version": "2.94.
|
|
3
|
+
"version": "2.94.6",
|
|
4
4
|
"description": "abaplint - Core API",
|
|
5
5
|
"main": "build/src/index.js",
|
|
6
6
|
"typings": "build/abaplint.d.ts",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@microsoft/api-extractor": "^7.33.7",
|
|
50
50
|
"@types/chai": "^4.3.4",
|
|
51
51
|
"@types/mocha": "^10.0.1",
|
|
52
|
-
"@types/node": "^18.11.
|
|
52
|
+
"@types/node": "^18.11.15",
|
|
53
53
|
"chai": "^4.3.7",
|
|
54
54
|
"eslint": "^8.29.0",
|
|
55
55
|
"mocha": "^10.2.0",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"fast-xml-parser": "^4.0.12",
|
|
63
|
-
"json5": "^2.2.
|
|
63
|
+
"json5": "^2.2.2",
|
|
64
64
|
"vscode-languageserver-types": "^3.17.2"
|
|
65
65
|
}
|
|
66
66
|
}
|