@abaplint/core 2.102.46 → 2.102.48
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 +5 -0
- package/build/src/abap/2_statements/expressions/behavior_definition_name.js +11 -0
- package/build/src/abap/2_statements/expressions/index.js +1 -0
- package/build/src/abap/2_statements/statements/class_definition.js +1 -1
- package/build/src/abap/5_syntax/_type_utils.js +5 -0
- package/build/src/abap/5_syntax/expressions/select.js +60 -1
- package/build/src/lsp/symbols.js +30 -11
- package/build/src/registry.js +1 -1
- package/build/src/rules/check_subrc.js +11 -0
- package/build/src/rules/uncaught_exception.js +9 -3
- package/package.json +4 -4
package/build/abaplint.d.ts
CHANGED
|
@@ -475,6 +475,10 @@ declare class BehaviorDefinition extends AbstractObject {
|
|
|
475
475
|
getDescription(): string | undefined;
|
|
476
476
|
}
|
|
477
477
|
|
|
478
|
+
declare class BehaviorDefinitionName extends Expression {
|
|
479
|
+
getRunnable(): IStatementRunnable;
|
|
480
|
+
}
|
|
481
|
+
|
|
478
482
|
declare class BlockName extends Expression {
|
|
479
483
|
getRunnable(): IStatementRunnable;
|
|
480
484
|
}
|
|
@@ -2016,6 +2020,7 @@ declare namespace Expressions {
|
|
|
2016
2020
|
AssociationName,
|
|
2017
2021
|
AttributeChain,
|
|
2018
2022
|
AttributeName,
|
|
2023
|
+
BehaviorDefinitionName,
|
|
2019
2024
|
BlockName,
|
|
2020
2025
|
CallTransformationOptions,
|
|
2021
2026
|
CallTransformationParameters,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BehaviorDefinitionName = void 0;
|
|
4
|
+
const combi_1 = require("../combi");
|
|
5
|
+
class BehaviorDefinitionName extends combi_1.Expression {
|
|
6
|
+
getRunnable() {
|
|
7
|
+
return (0, combi_1.regex)(/^((\w*\/\w+\/)|(\w*\/\w+\/)?[\w\*$%]+)$/);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.BehaviorDefinitionName = BehaviorDefinitionName;
|
|
11
|
+
//# sourceMappingURL=behavior_definition_name.js.map
|
|
@@ -24,6 +24,7 @@ __exportStar(require("./assign_source"), exports);
|
|
|
24
24
|
__exportStar(require("./association_name"), exports);
|
|
25
25
|
__exportStar(require("./attribute_chain"), exports);
|
|
26
26
|
__exportStar(require("./attribute_name"), exports);
|
|
27
|
+
__exportStar(require("./behavior_definition_name"), exports);
|
|
27
28
|
__exportStar(require("./block_name"), exports);
|
|
28
29
|
__exportStar(require("./call_transformation_options"), exports);
|
|
29
30
|
__exportStar(require("./call_transformation_parameters"), exports);
|
|
@@ -11,7 +11,7 @@ class ClassDefinition {
|
|
|
11
11
|
const risk = (0, combi_1.seq)("RISK LEVEL", level);
|
|
12
12
|
const time = (0, combi_1.altPrio)("LONG", "MEDIUM", "SHORT");
|
|
13
13
|
const duration = (0, combi_1.seq)("DURATION", time);
|
|
14
|
-
const blah = (0, combi_1.per)(expressions_1.ClassGlobal, expressions_1.ClassFinal, "ABSTRACT", (0, combi_1.seq)("INHERITING FROM", expressions_1.SuperClassName), create, "FOR TESTING", risk, "SHARED MEMORY ENABLED", duration, (0, combi_1.ver)(version_1.Version.v754, (0, combi_1.seq)("FOR BEHAVIOR OF", expressions_1.
|
|
14
|
+
const blah = (0, combi_1.per)(expressions_1.ClassGlobal, expressions_1.ClassFinal, "ABSTRACT", (0, combi_1.seq)("INHERITING FROM", expressions_1.SuperClassName), create, "FOR TESTING", risk, "SHARED MEMORY ENABLED", duration, (0, combi_1.ver)(version_1.Version.v754, (0, combi_1.seq)("FOR BEHAVIOR OF", expressions_1.BehaviorDefinitionName)), expressions_1.ClassFriends);
|
|
15
15
|
const def = (0, combi_1.seq)("DEFINITION", (0, combi_1.optPrio)(blah));
|
|
16
16
|
return (0, combi_1.seq)("CLASS", expressions_1.ClassName, def);
|
|
17
17
|
}
|
|
@@ -320,6 +320,11 @@ class TypeUtils {
|
|
|
320
320
|
return false;
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
|
+
else if (source instanceof basic_1.GenericObjectReferenceType) {
|
|
324
|
+
if (target instanceof basic_1.ObjectReferenceType) {
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
323
328
|
else if (source instanceof basic_1.ObjectReferenceType) {
|
|
324
329
|
if (target instanceof basic_1.XSequenceType
|
|
325
330
|
|| target instanceof basic_1.IntegerType
|
|
@@ -16,9 +16,15 @@ class Select {
|
|
|
16
16
|
const token = node.getFirstToken();
|
|
17
17
|
const from = node.findDirectExpression(Expressions.SQLFrom);
|
|
18
18
|
const dbSources = from ? new sql_from_1.SQLFrom().runSyntax(from, scope, filename) : [];
|
|
19
|
+
const fields = this.findFields(node);
|
|
20
|
+
if (fields.length === 0
|
|
21
|
+
&& node.findDirectExpression(Expressions.SQLFieldListLoop) === undefined) {
|
|
22
|
+
throw new Error(`fields missing`);
|
|
23
|
+
}
|
|
24
|
+
this.checkFields(fields, dbSources, scope);
|
|
19
25
|
for (const inline of node.findAllExpressions(Expressions.InlineData)) {
|
|
20
26
|
// todo, for now these are voided
|
|
21
|
-
new inline_data_1.InlineData().runSyntax(inline, scope, filename,
|
|
27
|
+
new inline_data_1.InlineData().runSyntax(inline, scope, filename, this.buildType(fields));
|
|
22
28
|
}
|
|
23
29
|
const fae = node.findDirectExpression(Expressions.SQLForAllEntries);
|
|
24
30
|
if (fae) {
|
|
@@ -62,6 +68,59 @@ class Select {
|
|
|
62
68
|
scope.pop(node.getLastToken().getEnd());
|
|
63
69
|
}
|
|
64
70
|
}
|
|
71
|
+
checkFields(fields, dbSources, scope) {
|
|
72
|
+
if (dbSources.length > 1) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const first = dbSources[0];
|
|
76
|
+
if (first === undefined) {
|
|
77
|
+
// then its voided
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const type = first.parseType(scope.getRegistry());
|
|
81
|
+
if (type instanceof basic_1.VoidType || type instanceof basic_1.UnknownType) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (!(type instanceof basic_1.StructureType)) {
|
|
85
|
+
throw new Error("checkFields, expected structure, " + type.constructor.name);
|
|
86
|
+
}
|
|
87
|
+
const isSimple = /^\w+$/;
|
|
88
|
+
for (const field of fields) {
|
|
89
|
+
if (field.code === "*") {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (isSimple.test(field.code) && type.getComponentByName(field.code) === undefined) {
|
|
93
|
+
throw new Error(`checkFields, field ${field.code} not found`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
buildType(_fields) {
|
|
98
|
+
return new basic_1.VoidType("SELECT_todo");
|
|
99
|
+
}
|
|
100
|
+
findFields(node) {
|
|
101
|
+
var _a;
|
|
102
|
+
let expr = undefined;
|
|
103
|
+
const ret = [];
|
|
104
|
+
expr = node.findDirectExpression(Expressions.SQLFieldList);
|
|
105
|
+
if (expr === undefined) {
|
|
106
|
+
expr = node.findDirectExpression(Expressions.SQLFields);
|
|
107
|
+
}
|
|
108
|
+
if (expr === undefined) {
|
|
109
|
+
node.findDirectExpression(Expressions.SQLFieldName);
|
|
110
|
+
}
|
|
111
|
+
for (const field of (expr === null || expr === void 0 ? void 0 : expr.findAllExpressions(Expressions.SQLField)) || []) {
|
|
112
|
+
let code = field.concatTokens().toUpperCase();
|
|
113
|
+
const as = ((_a = field.findDirectExpression(Expressions.SQLAsName)) === null || _a === void 0 ? void 0 : _a.concatTokens()) || "";
|
|
114
|
+
if (as !== "") {
|
|
115
|
+
code = code.replace(" AS " + as, "");
|
|
116
|
+
}
|
|
117
|
+
ret.push({ code, as, expression: field });
|
|
118
|
+
}
|
|
119
|
+
if (ret.length === 0 && expr) {
|
|
120
|
+
ret.push({ code: expr.concatTokens(), as: "", expression: expr });
|
|
121
|
+
}
|
|
122
|
+
return ret;
|
|
123
|
+
}
|
|
65
124
|
}
|
|
66
125
|
exports.Select = Select;
|
|
67
126
|
//# sourceMappingURL=select.js.map
|
package/build/src/lsp/symbols.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Symbols = void 0;
|
|
4
|
+
/* eslint-disable max-len */
|
|
4
5
|
const LServer = require("vscode-languageserver-types");
|
|
5
6
|
const _lsp_utils_1 = require("./_lsp_utils");
|
|
7
|
+
const statements_1 = require("../abap/2_statements/statements");
|
|
6
8
|
class Symbols {
|
|
7
9
|
constructor(reg) {
|
|
8
10
|
this.reg = reg;
|
|
@@ -27,6 +29,16 @@ class Symbols {
|
|
|
27
29
|
const end = identifer.getEnd();
|
|
28
30
|
return LServer.Range.create(start.getRow() - 1, start.getCol() - 1, end.getRow() - 1, end.getCol() - 1);
|
|
29
31
|
}
|
|
32
|
+
newSymbolRanged(identifier, kind, children, range) {
|
|
33
|
+
const symbol = {
|
|
34
|
+
name: identifier.getName(),
|
|
35
|
+
kind: kind,
|
|
36
|
+
range: range,
|
|
37
|
+
selectionRange: this.selectionRange(identifier),
|
|
38
|
+
children,
|
|
39
|
+
};
|
|
40
|
+
return symbol;
|
|
41
|
+
}
|
|
30
42
|
newSymbol(identifier, kind, children) {
|
|
31
43
|
const symbol = {
|
|
32
44
|
name: identifier.getName(),
|
|
@@ -50,22 +62,36 @@ class Symbols {
|
|
|
50
62
|
for (const cla of file.getInfo().listClassDefinitions()) {
|
|
51
63
|
const children = [];
|
|
52
64
|
children.push(...this.outputClassAttributes(cla.attributes));
|
|
53
|
-
children.push(...this.outputMethodDefinitions(cla.methods));
|
|
54
65
|
const symbol = this.newSymbol(cla.identifier, LServer.SymbolKind.Class, children);
|
|
55
66
|
ret.push(symbol);
|
|
56
67
|
}
|
|
57
68
|
for (const cla of file.getInfo().listClassImplementations()) {
|
|
58
69
|
const children = [];
|
|
59
|
-
children.push(...this.outputMethodImplementations(cla.methods));
|
|
70
|
+
children.push(...this.outputMethodImplementations(cla.methods, file));
|
|
60
71
|
const symbol = this.newSymbol(cla.identifier, LServer.SymbolKind.Class, children);
|
|
61
72
|
ret.push(symbol);
|
|
62
73
|
}
|
|
63
74
|
return ret;
|
|
64
75
|
}
|
|
65
|
-
outputMethodImplementations(methods) {
|
|
76
|
+
outputMethodImplementations(methods, file) {
|
|
66
77
|
const ret = [];
|
|
67
78
|
for (const method of methods) {
|
|
68
|
-
const
|
|
79
|
+
const start = method.getStart();
|
|
80
|
+
let end = undefined;
|
|
81
|
+
for (const s of file.getStatements()) {
|
|
82
|
+
if (s.getFirstToken().getStart().isBefore(start)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (s.get() instanceof statements_1.EndMethod) {
|
|
86
|
+
end = s.getLastToken().getEnd();
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (end === undefined) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const range = LServer.Range.create(start.getRow() - 1, start.getCol() - 1, end.getRow() - 1, end.getCol() - 1);
|
|
94
|
+
const symbol = this.newSymbolRanged(method, LServer.SymbolKind.Method, [], range);
|
|
69
95
|
ret.push(symbol);
|
|
70
96
|
}
|
|
71
97
|
return ret;
|
|
@@ -81,13 +107,6 @@ class Symbols {
|
|
|
81
107
|
// todo, also add constants
|
|
82
108
|
return ret;
|
|
83
109
|
}
|
|
84
|
-
outputMethodDefinitions(methods) {
|
|
85
|
-
if (methods === undefined) {
|
|
86
|
-
return [];
|
|
87
|
-
}
|
|
88
|
-
// todo
|
|
89
|
-
return [];
|
|
90
|
-
}
|
|
91
110
|
}
|
|
92
111
|
exports.Symbols = Symbols;
|
|
93
112
|
//# sourceMappingURL=symbols.js.map
|
package/build/src/registry.js
CHANGED
|
@@ -118,6 +118,7 @@ FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
|
|
|
118
118
|
}
|
|
119
119
|
else if (config.assign === true
|
|
120
120
|
&& statement.get() instanceof Statements.Assign
|
|
121
|
+
&& this.isSimpleAssign(statement) === false
|
|
121
122
|
&& this.isChecked(i, statements) === false) {
|
|
122
123
|
issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
|
|
123
124
|
}
|
|
@@ -131,6 +132,16 @@ FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
|
|
|
131
132
|
return issues;
|
|
132
133
|
}
|
|
133
134
|
////////////////
|
|
135
|
+
isSimpleAssign(statement) {
|
|
136
|
+
if (statement.getChildren().length === 5) {
|
|
137
|
+
const source = statement.findDirectExpression(Expressions.AssignSource);
|
|
138
|
+
if ((source === null || source === void 0 ? void 0 : source.getChildren().length) === 1
|
|
139
|
+
&& source.findDirectExpression(Expressions.Source) !== undefined) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
134
145
|
isExemptedFind(s) {
|
|
135
146
|
// see https://github.com/abaplint/abaplint/issues/2130
|
|
136
147
|
return s.concatTokens().toUpperCase().includes(" MATCH COUNT ") === true;
|
|
@@ -72,7 +72,7 @@ class UncaughtException extends _abap_rule_1.ABAPRule {
|
|
|
72
72
|
return this.issues;
|
|
73
73
|
}
|
|
74
74
|
traverse(n, file) {
|
|
75
|
-
var _a;
|
|
75
|
+
var _a, _b, _c, _d;
|
|
76
76
|
const get = n.get();
|
|
77
77
|
if (get instanceof Structures.ClassDefinition
|
|
78
78
|
|| get instanceof Structures.Interface) {
|
|
@@ -83,10 +83,16 @@ class UncaughtException extends _abap_rule_1.ABAPRule {
|
|
|
83
83
|
// note that TRY-CATCH might be arbitrarily nested
|
|
84
84
|
const previous = this.sinked ? this.sinked.slice() : undefined;
|
|
85
85
|
this.addFromTryStructure(n);
|
|
86
|
-
for (const c of n.getChildren()) {
|
|
86
|
+
for (const c of ((_a = n.findDirectStructure(Structures.Body)) === null || _a === void 0 ? void 0 : _a.getChildren()) || []) {
|
|
87
87
|
this.traverse(c, file);
|
|
88
88
|
}
|
|
89
89
|
this.sinked = previous;
|
|
90
|
+
for (const c of ((_b = n.findDirectStructure(Structures.Catch)) === null || _b === void 0 ? void 0 : _b.getChildren()) || []) {
|
|
91
|
+
this.traverse(c, file);
|
|
92
|
+
}
|
|
93
|
+
for (const c of ((_c = n.findDirectStructure(Structures.Cleanup)) === null || _c === void 0 ? void 0 : _c.getChildren()) || []) {
|
|
94
|
+
this.traverse(c, file);
|
|
95
|
+
}
|
|
90
96
|
return;
|
|
91
97
|
}
|
|
92
98
|
else {
|
|
@@ -116,7 +122,7 @@ class UncaughtException extends _abap_rule_1.ABAPRule {
|
|
|
116
122
|
let name = undefined;
|
|
117
123
|
const concat = n.concatTokens().toUpperCase();
|
|
118
124
|
if (concat.startsWith("RAISE EXCEPTION TYPE ")) {
|
|
119
|
-
name = (
|
|
125
|
+
name = (_d = n.findFirstExpression(Expressions.ClassName)) === null || _d === void 0 ? void 0 : _d.getFirstToken().getStr().toUpperCase();
|
|
120
126
|
}
|
|
121
127
|
this.check(name, n, file);
|
|
122
128
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abaplint/core",
|
|
3
|
-
"version": "2.102.
|
|
3
|
+
"version": "2.102.48",
|
|
4
4
|
"description": "abaplint - Core API",
|
|
5
5
|
"main": "build/src/index.js",
|
|
6
6
|
"typings": "build/abaplint.d.ts",
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
},
|
|
51
51
|
"homepage": "https://abaplint.org",
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@microsoft/api-extractor": "^7.37.
|
|
53
|
+
"@microsoft/api-extractor": "^7.37.1",
|
|
54
54
|
"@types/chai": "^4.3.6",
|
|
55
55
|
"@types/mocha": "^10.0.1",
|
|
56
|
-
"@types/node": "^20.
|
|
56
|
+
"@types/node": "^20.7.0",
|
|
57
57
|
"chai": "^4.3.8",
|
|
58
58
|
"eslint": "^8.50.0",
|
|
59
59
|
"mocha": "^10.2.0",
|
|
@@ -65,6 +65,6 @@
|
|
|
65
65
|
"dependencies": {
|
|
66
66
|
"fast-xml-parser": "^4.3.1",
|
|
67
67
|
"json5": "^2.2.3",
|
|
68
|
-
"vscode-languageserver-types": "^3.17.
|
|
68
|
+
"vscode-languageserver-types": "^3.17.5"
|
|
69
69
|
}
|
|
70
70
|
}
|