@abaplint/core 2.113.217 → 2.113.219
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/src/abap/5_syntax/_type_utils.js +2 -2
- package/build/src/abap/5_syntax/expressions/corresponding_body.js +1 -1
- package/build/src/registry.js +1 -1
- package/build/src/rules/downport.js +0 -1
- package/build/src/rules/fully_type_constants.js +2 -2
- package/build/src/rules/implement_methods.js +36 -3
- package/build/src/rules/parser_702_chaining.js +38 -3
- package/build/src/rules/unnecessary_return.js +2 -2
- package/package.json +5 -5
|
@@ -448,7 +448,7 @@ class TypeUtils {
|
|
|
448
448
|
if (!(sourceRowType instanceof basic_1.StructureType)) {
|
|
449
449
|
return false;
|
|
450
450
|
}
|
|
451
|
-
else if (!
|
|
451
|
+
else if (!this.structureContainsString(sourceRowType)
|
|
452
452
|
&& this.structureContainsVoid(sourceRowType) === false) {
|
|
453
453
|
return false;
|
|
454
454
|
}
|
|
@@ -458,7 +458,7 @@ class TypeUtils {
|
|
|
458
458
|
if (!(targetRowType instanceof basic_1.StructureType)) {
|
|
459
459
|
return false;
|
|
460
460
|
}
|
|
461
|
-
else if (!
|
|
461
|
+
else if (!this.structureContainsString(targetRowType)
|
|
462
462
|
&& this.structureContainsVoid(targetRowType) === false) {
|
|
463
463
|
return false;
|
|
464
464
|
}
|
|
@@ -11,7 +11,7 @@ class CorrespondingBody {
|
|
|
11
11
|
}
|
|
12
12
|
const base = (_a = node.findDirectExpression(Expressions.CorrespondingBodyBase)) === null || _a === void 0 ? void 0 : _a.findDirectExpression(Expressions.Source);
|
|
13
13
|
if (base) {
|
|
14
|
-
source_1.Source.runSyntax(base, input);
|
|
14
|
+
source_1.Source.runSyntax(base, input, targetType);
|
|
15
15
|
}
|
|
16
16
|
let type = undefined;
|
|
17
17
|
for (const s of node.findDirectExpressions(Expressions.Source)) {
|
package/build/src/registry.js
CHANGED
|
@@ -939,7 +939,6 @@ ${indentation}${uniqueName} = ${source.concatTokens()}.\n${indentation}`);
|
|
|
939
939
|
const source = high.findExpressionAfterToken("MESSAGE");
|
|
940
940
|
if ((source === null || source === void 0 ? void 0 : source.get()) instanceof Expressions.MessageSourceSource
|
|
941
941
|
&& ((_a = source.getFirstChild()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.Source) {
|
|
942
|
-
;
|
|
943
942
|
const uniqueName = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
|
|
944
943
|
const indentation = " ".repeat(high.getFirstToken().getStart().getCol() - 1);
|
|
945
944
|
const firstToken = high.getFirstToken();
|
|
@@ -45,7 +45,7 @@ class FullyTypeConstants extends _abap_rule_1.ABAPRule {
|
|
|
45
45
|
for (const stat of file.getStatements()) {
|
|
46
46
|
if ((stat.get() instanceof Statements.Constant
|
|
47
47
|
|| (this.conf.checkData === true && stat.get() instanceof Statements.Data))
|
|
48
|
-
&&
|
|
48
|
+
&& !this.isTyped(stat)) {
|
|
49
49
|
const type = stat.get() instanceof Statements.Constant ? "constant definition" : "data definition";
|
|
50
50
|
let token = (_a = stat.findFirstExpression(expressions_1.NamespaceSimpleName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
51
51
|
if (token === undefined) {
|
|
@@ -60,7 +60,7 @@ class FullyTypeConstants extends _abap_rule_1.ABAPRule {
|
|
|
60
60
|
return issues;
|
|
61
61
|
}
|
|
62
62
|
isTyped(stat) {
|
|
63
|
-
return
|
|
63
|
+
return stat.findFirstExpression(expressions_1.Type) || stat.findFirstExpression(expressions_1.TypeTable);
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
exports.FullyTypeConstants = FullyTypeConstants;
|
|
@@ -77,7 +77,15 @@ class ImplementMethods extends _abap_rule_1.ABAPRule {
|
|
|
77
77
|
const issue = issue_1.Issue.atIdentifier(found, "Do not implement abstract method \"" + md.name + "\"", this.getMetadata().key, this.conf.severity);
|
|
78
78
|
ret.push(issue);
|
|
79
79
|
}
|
|
80
|
-
|
|
80
|
+
if (def.isAbstract) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
const message = "Abstract methods can only be defined in abstract classes.";
|
|
85
|
+
const issue = issue_1.Issue.atIdentifier(def.identifier, message, this.getMetadata().key, this.conf.severity);
|
|
86
|
+
ret.push(issue);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
81
89
|
}
|
|
82
90
|
if (impl === undefined) {
|
|
83
91
|
const message = "Class implementation for \"" + def.name + "\" not found";
|
|
@@ -180,8 +188,16 @@ class ImplementMethods extends _abap_rule_1.ABAPRule {
|
|
|
180
188
|
return [idef];
|
|
181
189
|
}
|
|
182
190
|
for (const m of this.findInterfaceMethods(idef)) {
|
|
183
|
-
if (
|
|
184
|
-
|
|
191
|
+
if (this.isAbstract(m, interfaceInfo, def)) {
|
|
192
|
+
if (def.isAbstract) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
const message = "Abstract methods can only be defined in abstract classes.";
|
|
197
|
+
const issue = issue_1.Issue.atIdentifier(def.identifier, message, this.getMetadata().key, this.conf.severity);
|
|
198
|
+
ret.push(issue);
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
185
201
|
}
|
|
186
202
|
if (this.isImplemented(m, def, impl) === false) {
|
|
187
203
|
const message = "Implement method \"" + m.method.name + "\" from interface \"" + m.objectName + "\"";
|
|
@@ -199,6 +215,23 @@ class ImplementMethods extends _abap_rule_1.ABAPRule {
|
|
|
199
215
|
}
|
|
200
216
|
return ret;
|
|
201
217
|
}
|
|
218
|
+
isAbstract(m, interfaceInfo, def) {
|
|
219
|
+
if (interfaceInfo.abstractMethods.includes(m.method.name.toUpperCase())) {
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
if (!def.superClassName) {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
// look up in superclass if method is abstract there
|
|
226
|
+
const superClass = this.findClass(def.superClassName);
|
|
227
|
+
const superInterface = superClass === null || superClass === void 0 ? void 0 : superClass.def.interfaces.find(iface => iface.name.toUpperCase() === m.objectName.toUpperCase());
|
|
228
|
+
if (superClass && superInterface) {
|
|
229
|
+
return this.isAbstract(m, superInterface, superClass.def);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
202
235
|
isImplemented(m, def, impl) {
|
|
203
236
|
if (impl === undefined) {
|
|
204
237
|
return false;
|
|
@@ -7,6 +7,7 @@ const _abap_rule_1 = require("./_abap_rule");
|
|
|
7
7
|
const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
8
8
|
const _irule_1 = require("./_irule");
|
|
9
9
|
const version_1 = require("../version");
|
|
10
|
+
const __1 = require("..");
|
|
10
11
|
class Parser702ChainingConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
11
12
|
}
|
|
12
13
|
exports.Parser702ChainingConf = Parser702ChainingConf;
|
|
@@ -18,7 +19,7 @@ class Parser702Chaining extends _abap_rule_1.ABAPRule {
|
|
|
18
19
|
getMetadata() {
|
|
19
20
|
return {
|
|
20
21
|
key: "parser_702_chaining",
|
|
21
|
-
title: "Parser Error, bad
|
|
22
|
+
title: "Parser Error, bad chaining on 702",
|
|
22
23
|
shortDescription: `ABAP on 702 does not allow for method chaining with IMPORTING/EXPORTING/CHANGING keywords,
|
|
23
24
|
this rule finds these and reports errors.
|
|
24
25
|
Only active on target version 702 and below.`,
|
|
@@ -59,13 +60,47 @@ Only active on target version 702 and below.`,
|
|
|
59
60
|
|| param.findDirectTokenByText("CHANGING")
|
|
60
61
|
|| param.findDirectTokenByText("EXCEPTIONS")) {
|
|
61
62
|
const message = "This kind of method chaining not possible in 702";
|
|
62
|
-
|
|
63
|
-
issues.push(issue);
|
|
63
|
+
this.pushIssue(message, file, param, issues);
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
+
// after a value assignment (move statement whose source is a method call, or method parameter assignment),
|
|
68
|
+
// there can't be any EXPORTING/IMPORTING/CHANGING/EXCEPTIONS
|
|
69
|
+
for (const statement of file.getStatements()) {
|
|
70
|
+
if (!(statement.get() instanceof __1.Statements.Move)) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const source = statement.findDirectExpression(Expressions.Source);
|
|
74
|
+
if (source === undefined) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
this.ensureSourceHasNoProceduralKeywords(source, file, issues);
|
|
78
|
+
}
|
|
79
|
+
for (const methodParameters of stru.findAllExpressions(Expressions.MethodParameters)) {
|
|
80
|
+
for (const params of methodParameters.findAllExpressions(Expressions.ParameterS)) {
|
|
81
|
+
const source = params.findDirectExpression(Expressions.Source);
|
|
82
|
+
if (source === undefined) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
this.ensureSourceHasNoProceduralKeywords(source, file, issues);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
67
88
|
return issues;
|
|
68
89
|
}
|
|
90
|
+
ensureSourceHasNoProceduralKeywords(source, file, issues) {
|
|
91
|
+
const forbiddenTokens = ["EXPORTING", "IMPORTING", "CHANGING", "EXCEPTIONS"];
|
|
92
|
+
for (const param of source.findAllExpressions(Expressions.MethodParameters)) {
|
|
93
|
+
const usedForbiddenToken = forbiddenTokens.find(text => param.findDirectTokenByText(text));
|
|
94
|
+
if (usedForbiddenToken) {
|
|
95
|
+
const message = `Unexpected word ${usedForbiddenToken} in functional method call`;
|
|
96
|
+
this.pushIssue(message, file, param, issues);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
pushIssue(message, file, node, issues) {
|
|
101
|
+
const issue = issue_1.Issue.atPosition(file, node.getFirstToken().getStart(), message, this.getMetadata().key, this.conf.severity);
|
|
102
|
+
issues.push(issue);
|
|
103
|
+
}
|
|
69
104
|
}
|
|
70
105
|
exports.Parser702Chaining = Parser702Chaining;
|
|
71
106
|
//# sourceMappingURL=parser_702_chaining.js.map
|
|
@@ -61,9 +61,9 @@ ENDFORM.`,
|
|
|
61
61
|
for (let i = 0; i < statements.length; i++) {
|
|
62
62
|
const node = statements[i];
|
|
63
63
|
const nodeType = node.get();
|
|
64
|
-
if (
|
|
64
|
+
if (nodeType instanceof Statements.MethodImplementation
|
|
65
65
|
|| nodeType instanceof Statements.Form
|
|
66
|
-
|| nodeType instanceof Statements.FunctionModule)
|
|
66
|
+
|| nodeType instanceof Statements.FunctionModule) {
|
|
67
67
|
statementCounter = 0;
|
|
68
68
|
continue;
|
|
69
69
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abaplint/core",
|
|
3
|
-
"version": "2.113.
|
|
3
|
+
"version": "2.113.219",
|
|
4
4
|
"description": "abaplint - Core API",
|
|
5
5
|
"main": "build/src/index.js",
|
|
6
6
|
"typings": "build/abaplint.d.ts",
|
|
@@ -50,17 +50,17 @@
|
|
|
50
50
|
},
|
|
51
51
|
"homepage": "https://abaplint.org",
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@microsoft/api-extractor": "^7.52.
|
|
53
|
+
"@microsoft/api-extractor": "^7.52.15",
|
|
54
54
|
"@types/chai": "^4.3.20",
|
|
55
55
|
"@types/mocha": "^10.0.10",
|
|
56
|
-
"@types/node": "^24.
|
|
56
|
+
"@types/node": "^24.6.2",
|
|
57
57
|
"chai": "^4.5.0",
|
|
58
58
|
"eslint": "^9.36.0",
|
|
59
|
-
"mocha": "^11.7.
|
|
59
|
+
"mocha": "^11.7.4",
|
|
60
60
|
"c8": "^10.1.3",
|
|
61
61
|
"source-map-support": "^0.5.21",
|
|
62
62
|
"ts-json-schema-generator": "^2.4.0",
|
|
63
|
-
"typescript": "^5.9.
|
|
63
|
+
"typescript": "^5.9.3"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
66
|
"fast-xml-parser": "^5.2.5",
|