@abaplint/core 2.120.24 → 2.120.26
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 -1
- package/build/src/abap/5_syntax/_type_utils.js +6 -0
- package/build/src/abap/5_syntax/expressions/_check_database_fields.js +35 -0
- package/build/src/abap/5_syntax/expressions/compare.js +10 -1
- package/build/src/abap/5_syntax/expressions/select.js +2 -30
- package/build/src/abap/5_syntax/statements/catch.js +7 -3
- package/build/src/abap/5_syntax/statements/delete_database.js +9 -1
- package/build/src/abap/5_syntax/statements/update_database.js +9 -1
- package/build/src/abap/5_syntax/structures/types.js +7 -0
- package/build/src/abap/types/class_definition.js +9 -3
- package/build/src/abap/types/method_parameters.js +9 -0
- package/build/src/registry.js +1 -1
- package/package.json +1 -1
package/build/abaplint.d.ts
CHANGED
|
@@ -1260,7 +1260,7 @@ declare class ClassDefinition_3 extends Identifier implements IClassDefinition {
|
|
|
1260
1260
|
private checkClassNameLength;
|
|
1261
1261
|
private findSuper;
|
|
1262
1262
|
private checkMethodNameLength;
|
|
1263
|
-
private
|
|
1263
|
+
private checkClassConstructor;
|
|
1264
1264
|
private checkInterfaceVisibility;
|
|
1265
1265
|
private checkMethodsFromSuperClasses;
|
|
1266
1266
|
private checkMethodNameConflicts;
|
|
@@ -4897,6 +4897,7 @@ declare class MethodParameters_2 implements IMethodParameters {
|
|
|
4897
4897
|
getParameterDefault(parameter: string): ExpressionNode;
|
|
4898
4898
|
private parse;
|
|
4899
4899
|
private checkDuplicateNames;
|
|
4900
|
+
private checkNameLengths;
|
|
4900
4901
|
private workaroundRAP;
|
|
4901
4902
|
private add;
|
|
4902
4903
|
private isPassByValue;
|
|
@@ -281,6 +281,12 @@ class TypeUtils {
|
|
|
281
281
|
if (source2 instanceof basic_1.HexType && this.isCalculated(node2) && source1 instanceof basic_1.IntegerType) {
|
|
282
282
|
return false;
|
|
283
283
|
}
|
|
284
|
+
if (source1 instanceof basic_1.DateType && this.isCalculated(node2) && source2 instanceof basic_1.IntegerType) {
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
if (source2 instanceof basic_1.DateType && this.isCalculated(node1) && source1 instanceof basic_1.IntegerType) {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
284
290
|
return true;
|
|
285
291
|
}
|
|
286
292
|
structureContainsString(structure) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkDatabaseFields = checkDatabaseFields;
|
|
4
|
+
const basic_1 = require("../../types/basic");
|
|
5
|
+
const _syntax_input_1 = require("../_syntax_input");
|
|
6
|
+
function checkDatabaseFields(fields, dbSources, input, token) {
|
|
7
|
+
if (dbSources.length > 1) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const first = dbSources[0];
|
|
11
|
+
if (first === undefined) {
|
|
12
|
+
// then its voided
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const type = first.parseType(input.scope.getRegistry());
|
|
16
|
+
if (type instanceof basic_1.VoidType || type instanceof basic_1.UnknownType) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (!(type instanceof basic_1.StructureType)) {
|
|
20
|
+
const message = "checkFields, expected structure, " + type.constructor.name;
|
|
21
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, token, message));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
for (const field of fields) {
|
|
25
|
+
if (field === "*") {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (/^\w+$/.test(field) && type.getComponentByName(field) === undefined) {
|
|
29
|
+
const message = `checkFields, field ${field} not found`;
|
|
30
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, token, message));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=_check_database_fields.js.map
|
|
@@ -39,6 +39,7 @@ const source_1 = require("./source");
|
|
|
39
39
|
const method_call_chain_1 = require("./method_call_chain");
|
|
40
40
|
const source_field_symbol_1 = require("./source_field_symbol");
|
|
41
41
|
const _syntax_input_1 = require("../_syntax_input");
|
|
42
|
+
const basic_1 = require("../../types/basic");
|
|
42
43
|
const _type_utils_1 = require("../_type_utils");
|
|
43
44
|
class Compare {
|
|
44
45
|
static runSyntax(node, input) {
|
|
@@ -56,7 +57,15 @@ class Compare {
|
|
|
56
57
|
if (node.findDirectExpression(Expressions.CompareOperator)
|
|
57
58
|
&& new _type_utils_1.TypeUtils(input.scope).isCompareable(sourceTypes[0], sourceTypes[1], sources[0], sources[1]) === false
|
|
58
59
|
&& sourceTypes.length === 2) {
|
|
59
|
-
|
|
60
|
+
let message = "Incompatible types for comparison";
|
|
61
|
+
if ((sourceTypes[0] instanceof basic_1.DateType
|
|
62
|
+
&& sourceTypes[1] instanceof basic_1.IntegerType
|
|
63
|
+
&& sources[1].findFirstExpression(Expressions.ArithOperator))
|
|
64
|
+
|| (sourceTypes[1] instanceof basic_1.DateType
|
|
65
|
+
&& sourceTypes[0] instanceof basic_1.IntegerType
|
|
66
|
+
&& sources[0].findFirstExpression(Expressions.ArithOperator))) {
|
|
67
|
+
message = "Date cannot be compared with arithmetic result of type Integer";
|
|
68
|
+
}
|
|
60
69
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
61
70
|
}
|
|
62
71
|
}
|
|
@@ -48,6 +48,7 @@ const dynamic_1 = require("./dynamic");
|
|
|
48
48
|
const _reference_1 = require("../_reference");
|
|
49
49
|
const _syntax_input_1 = require("../_syntax_input");
|
|
50
50
|
const version_1 = require("../../../version");
|
|
51
|
+
const _check_database_fields_1 = require("./_check_database_fields");
|
|
51
52
|
const isSimple = /^\w+$/;
|
|
52
53
|
class Select {
|
|
53
54
|
static runSyntax(node, input, skipImplicitInto = false, selectLoop = false) {
|
|
@@ -72,7 +73,7 @@ class Select {
|
|
|
72
73
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
73
74
|
return;
|
|
74
75
|
}
|
|
75
|
-
|
|
76
|
+
(0, _check_database_fields_1.checkDatabaseFields)(fields.map(field => field.code), dbSources, input, node.getFirstToken());
|
|
76
77
|
const intoExpression = this.handleInto(node, input, fields, dbSources);
|
|
77
78
|
const fae = node.findDirectExpression(Expressions.SQLForAllEntries);
|
|
78
79
|
if (fae) {
|
|
@@ -299,35 +300,6 @@ class Select {
|
|
|
299
300
|
}
|
|
300
301
|
return undefined;
|
|
301
302
|
}
|
|
302
|
-
static checkFields(fields, dbSources, input, node) {
|
|
303
|
-
if (dbSources.length > 1) {
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
const first = dbSources[0];
|
|
307
|
-
if (first === undefined) {
|
|
308
|
-
// then its voided
|
|
309
|
-
return;
|
|
310
|
-
}
|
|
311
|
-
const type = first.parseType(input.scope.getRegistry());
|
|
312
|
-
if (type instanceof basic_1.VoidType || type instanceof basic_1.UnknownType) {
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
if (!(type instanceof basic_1.StructureType)) {
|
|
316
|
-
const message = "checkFields, expected structure, " + type.constructor.name;
|
|
317
|
-
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
for (const field of fields) {
|
|
321
|
-
if (field.code === "*") {
|
|
322
|
-
continue;
|
|
323
|
-
}
|
|
324
|
-
if (isSimple.test(field.code) && type.getComponentByName(field.code) === undefined) {
|
|
325
|
-
const message = `checkFields, field ${field.code} not found`;
|
|
326
|
-
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
303
|
static countResultType(scope) {
|
|
332
304
|
if ((0, version_1.releaseAtLeast)(scope.getRelease(), version_1.Release.v750)
|
|
333
305
|
|| scope.getOpenABAP()
|
|
@@ -43,7 +43,12 @@ const _syntax_input_1 = require("../_syntax_input");
|
|
|
43
43
|
const _type_utils_1 = require("../_type_utils");
|
|
44
44
|
class Catch {
|
|
45
45
|
runSyntax(node, input) {
|
|
46
|
-
var _a;
|
|
46
|
+
var _a, _b, _c;
|
|
47
|
+
const target = node.findDirectExpression(Expressions.Target);
|
|
48
|
+
const inlineTarget = (_b = (_a = target === null || target === void 0 ? void 0 : target.findDirectExpression(Expressions.InlineData)) === null || _a === void 0 ? void 0 : _a.findFirstExpression(Expressions.TargetField)) === null || _b === void 0 ? void 0 : _b.getFirstToken();
|
|
49
|
+
if (inlineTarget && inlineTarget.getStr().length > 30) {
|
|
50
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, inlineTarget, "Inline exception name longer than 30 characters"));
|
|
51
|
+
}
|
|
47
52
|
const names = new Set();
|
|
48
53
|
for (const c of node.findDirectExpressions(Expressions.ClassName)) {
|
|
49
54
|
const token = c.getFirstToken();
|
|
@@ -67,9 +72,8 @@ class Catch {
|
|
|
67
72
|
}
|
|
68
73
|
names.add(className);
|
|
69
74
|
}
|
|
70
|
-
const target = node.findDirectExpression(Expressions.Target);
|
|
71
75
|
if (target === null || target === void 0 ? void 0 : target.findDirectExpression(Expressions.InlineData)) {
|
|
72
|
-
const token = (
|
|
76
|
+
const token = (_c = target.findFirstExpression(Expressions.TargetField)) === null || _c === void 0 ? void 0 : _c.getFirstToken();
|
|
73
77
|
if (token) {
|
|
74
78
|
const classNames = Array.from(names);
|
|
75
79
|
const unknownClass = classNames.find(name => input.scope.findClassDefinition(name) === undefined);
|
|
@@ -38,6 +38,7 @@ const Expressions = __importStar(require("../../2_statements/expressions"));
|
|
|
38
38
|
const source_1 = require("../expressions/source");
|
|
39
39
|
const dynamic_1 = require("../expressions/dynamic");
|
|
40
40
|
const database_table_1 = require("../expressions/database_table");
|
|
41
|
+
const _check_database_fields_1 = require("../expressions/_check_database_fields");
|
|
41
42
|
class DeleteDatabase {
|
|
42
43
|
runSyntax(node, input) {
|
|
43
44
|
for (const s of node.findAllExpressions(Expressions.Source)) {
|
|
@@ -51,7 +52,14 @@ class DeleteDatabase {
|
|
|
51
52
|
}
|
|
52
53
|
const dbtab = node.findFirstExpression(Expressions.DatabaseTable);
|
|
53
54
|
if (dbtab !== undefined) {
|
|
54
|
-
database_table_1.DatabaseTable.runSyntax(dbtab, input);
|
|
55
|
+
const dbSource = database_table_1.DatabaseTable.runSyntax(dbtab, input);
|
|
56
|
+
const fields = node.findAllExpressions(Expressions.SQLCompare)
|
|
57
|
+
.map(compare => { var _a; return (_a = compare.findDirectExpression(Expressions.SQLFieldName)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase(); })
|
|
58
|
+
.filter(field => field !== undefined);
|
|
59
|
+
for (const orderBy of node.findAllExpressions(Expressions.SQLOrderBy)) {
|
|
60
|
+
fields.push(...orderBy.findAllExpressions(Expressions.SQLFieldName).map(field => field.concatTokens().toUpperCase()));
|
|
61
|
+
}
|
|
62
|
+
(0, _check_database_fields_1.checkDatabaseFields)(fields, [dbSource], input, node.getFirstToken());
|
|
55
63
|
}
|
|
56
64
|
}
|
|
57
65
|
}
|
|
@@ -42,11 +42,19 @@ const _typed_identifier_1 = require("../../types/_typed_identifier");
|
|
|
42
42
|
const identifier_1 = require("../../1_lexer/tokens/identifier");
|
|
43
43
|
const database_table_1 = require("../expressions/database_table");
|
|
44
44
|
const dynamic_1 = require("../expressions/dynamic");
|
|
45
|
+
const _check_database_fields_1 = require("../expressions/_check_database_fields");
|
|
45
46
|
class UpdateDatabase {
|
|
46
47
|
runSyntax(node, input) {
|
|
47
48
|
const dbtab = node.findFirstExpression(Expressions.DatabaseTable);
|
|
48
49
|
if (dbtab !== undefined) {
|
|
49
|
-
database_table_1.DatabaseTable.runSyntax(dbtab, input);
|
|
50
|
+
const dbSource = database_table_1.DatabaseTable.runSyntax(dbtab, input);
|
|
51
|
+
const fields = node.findAllExpressions(Expressions.SQLFieldAndValue)
|
|
52
|
+
.flatMap(fieldAndValue => fieldAndValue.findDirectExpressions(Expressions.SQLFieldName))
|
|
53
|
+
.map(field => field.concatTokens().toUpperCase());
|
|
54
|
+
fields.push(...node.findAllExpressions(Expressions.SQLCompare)
|
|
55
|
+
.map(compare => { var _a; return (_a = compare.findDirectExpression(Expressions.SQLFieldName)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase(); })
|
|
56
|
+
.filter(field => field !== undefined));
|
|
57
|
+
(0, _check_database_fields_1.checkDatabaseFields)(fields, [dbSource], input, node.getFirstToken());
|
|
50
58
|
}
|
|
51
59
|
const tableName = node.findDirectExpression(Expressions.DatabaseTable);
|
|
52
60
|
const tokenName = tableName === null || tableName === void 0 ? void 0 : tableName.getFirstToken();
|
|
@@ -44,6 +44,7 @@ const include_type_1 = require("../statements/include_type");
|
|
|
44
44
|
const type_1 = require("../statements/type");
|
|
45
45
|
const Basic = __importStar(require("../../types/basic"));
|
|
46
46
|
const _scope_type_1 = require("../_scope_type");
|
|
47
|
+
const _syntax_input_1 = require("../_syntax_input");
|
|
47
48
|
class Types {
|
|
48
49
|
runSyntax(node, input, qualifiedNamePrefix) {
|
|
49
50
|
const name = node.findFirstExpression(Expressions.NamespaceSimpleName).getFirstToken();
|
|
@@ -58,6 +59,9 @@ class Types {
|
|
|
58
59
|
if (ctyp instanceof Statements.Type) {
|
|
59
60
|
const found = new type_1.Type().runSyntax(c, input, qualifiedNamePrefix + name.getStr() + "-");
|
|
60
61
|
if (found) {
|
|
62
|
+
if (found.getName().length > 30) {
|
|
63
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, found.getToken(), "Structure field name longer than 30 characters"));
|
|
64
|
+
}
|
|
61
65
|
components.push({ name: found.getName(), type: found.getType() });
|
|
62
66
|
}
|
|
63
67
|
}
|
|
@@ -74,6 +78,9 @@ class Types {
|
|
|
74
78
|
else if (c instanceof nodes_1.StructureNode && ctyp instanceof Structures.Types) {
|
|
75
79
|
const found = new Types().runSyntax(c, input, qualifiedNamePrefix + name.getStr() + "-");
|
|
76
80
|
if (found) {
|
|
81
|
+
if (found.getName().length > 30) {
|
|
82
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, found.getToken(), "Structure field name longer than 30 characters"));
|
|
83
|
+
}
|
|
77
84
|
components.push({ name: found.getName(), type: found.getType() });
|
|
78
85
|
}
|
|
79
86
|
}
|
|
@@ -101,7 +101,7 @@ class ClassDefinition extends _identifier_1.Identifier {
|
|
|
101
101
|
this.checkEventNameConflicts(input);
|
|
102
102
|
this.checkClassNameLength(input);
|
|
103
103
|
this.checkMethodNameLength(input);
|
|
104
|
-
this.
|
|
104
|
+
this.checkClassConstructor(input);
|
|
105
105
|
}
|
|
106
106
|
getFriends() {
|
|
107
107
|
return this.friends;
|
|
@@ -171,11 +171,17 @@ class ClassDefinition extends _identifier_1.Identifier {
|
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
|
-
|
|
174
|
+
checkClassConstructor(input) {
|
|
175
175
|
for (const m of this.methodDefs.getAll()) {
|
|
176
|
-
if (m.getName().toUpperCase()
|
|
176
|
+
if (m.getName().toUpperCase() !== "CLASS_CONSTRUCTOR") {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (m.isStatic() === false) {
|
|
177
180
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, m.getToken(), "CLASS_CONSTRUCTOR must be static"));
|
|
178
181
|
}
|
|
182
|
+
else if (m.getVisibility() !== visibility_1.Visibility.Public) {
|
|
183
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, m.getToken(), "CLASS_CONSTRUCTOR must be declared in the public section"));
|
|
184
|
+
}
|
|
179
185
|
}
|
|
180
186
|
}
|
|
181
187
|
checkInterfaceVisibility(input, node) {
|
|
@@ -45,6 +45,7 @@ const _object_oriented_1 = require("../5_syntax/_object_oriented");
|
|
|
45
45
|
const _reference_1 = require("../5_syntax/_reference");
|
|
46
46
|
const identifier_1 = require("../1_lexer/tokens/identifier");
|
|
47
47
|
const _scope_type_1 = require("../5_syntax/_scope_type");
|
|
48
|
+
const _syntax_input_1 = require("../5_syntax/_syntax_input");
|
|
48
49
|
// todo:
|
|
49
50
|
// this.exceptions = [];
|
|
50
51
|
// also consider RAISING vs EXCEPTIONS
|
|
@@ -67,6 +68,7 @@ class MethodParameters {
|
|
|
67
68
|
input.scope.push(_scope_type_1.ScopeType.MethodDefinition, "method definition", node.getStart(), input.filename);
|
|
68
69
|
try {
|
|
69
70
|
this.parse(node, input, parentName, abstractMethod);
|
|
71
|
+
this.checkNameLengths(input);
|
|
70
72
|
this.checkDuplicateNames();
|
|
71
73
|
}
|
|
72
74
|
finally {
|
|
@@ -218,6 +220,13 @@ class MethodParameters {
|
|
|
218
220
|
names.add(name);
|
|
219
221
|
}
|
|
220
222
|
}
|
|
223
|
+
checkNameLengths(input) {
|
|
224
|
+
for (const parameter of this.getAll()) {
|
|
225
|
+
if (parameter.getName().length > 30) {
|
|
226
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, parameter.getToken(), "Method parameter name longer than 30 characters"));
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
221
230
|
workaroundRAP(node, input, parentName) {
|
|
222
231
|
const resultName = node.findExpressionAfterToken("RESULT");
|
|
223
232
|
const concat = node.concatTokens().toUpperCase();
|
package/build/src/registry.js
CHANGED