@abaplint/core 2.118.4 → 2.118.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 +8 -0
- package/build/src/abap/2_statements/statements/read_table.js +3 -1
- package/build/src/abap/5_syntax/_builtin.js +2 -2
- package/build/src/abap/5_syntax/_current_scope.js +22 -0
- package/build/src/abap/5_syntax/_type_utils.js +12 -0
- package/build/src/abap/5_syntax/basic_types.js +1 -1
- package/build/src/abap/5_syntax/expressions/method_parameters.js +2 -2
- package/build/src/abap/5_syntax/expressions/new_object.js +15 -0
- package/build/src/abap/5_syntax/expressions/select.js +4 -3
- package/build/src/abap/5_syntax/expressions/source.js +5 -0
- package/build/src/abap/5_syntax/statements/class_local_friends.js +7 -0
- package/build/src/abap/5_syntax/statements/create_object.js +39 -0
- package/build/src/abap/types/class_attributes.js +20 -0
- package/build/src/abap/types/class_definition.js +26 -1
- package/build/src/registry.js +1 -1
- package/build/src/rules/catch_and_raise.js +82 -0
- package/build/src/rules/index.js +1 -0
- package/package.json +2 -2
package/build/abaplint.d.ts
CHANGED
|
@@ -383,6 +383,7 @@ declare class Attributes implements IAttributes {
|
|
|
383
383
|
private readonly tlist;
|
|
384
384
|
private readonly filename;
|
|
385
385
|
private readonly aliases;
|
|
386
|
+
private readonly declaredInterfaces;
|
|
386
387
|
constructor(node: StructureNode, input: SyntaxInput);
|
|
387
388
|
getTypes(): TypeDefinitions;
|
|
388
389
|
getStatic(): ClassAttribute[];
|
|
@@ -1189,6 +1190,7 @@ declare class ClassDefinition_3 extends Identifier implements IClassDefinition {
|
|
|
1189
1190
|
private readonly globalValue;
|
|
1190
1191
|
private readonly sharedMemory;
|
|
1191
1192
|
private readonly aliases;
|
|
1193
|
+
private readonly createVisibilityValue;
|
|
1192
1194
|
constructor(node: StructureNode, input: SyntaxInput);
|
|
1193
1195
|
getFriends(): string[];
|
|
1194
1196
|
getEvents(): IEventDefinition[];
|
|
@@ -1203,6 +1205,7 @@ declare class ClassDefinition_3 extends Identifier implements IClassDefinition {
|
|
|
1203
1205
|
isForTesting(): boolean;
|
|
1204
1206
|
isAbstract(): boolean;
|
|
1205
1207
|
isSharedMemory(): boolean;
|
|
1208
|
+
getCreateVisibility(): Visibility;
|
|
1206
1209
|
private findSuper;
|
|
1207
1210
|
private checkMethodNameLength;
|
|
1208
1211
|
private checkMethodsFromSuperClasses;
|
|
@@ -1533,6 +1536,7 @@ export declare class CurrentScope {
|
|
|
1533
1536
|
protected current: SpaghettiScopeNode | undefined;
|
|
1534
1537
|
protected allowHeaderUse: string | undefined;
|
|
1535
1538
|
protected parentObj: IObject;
|
|
1539
|
+
private readonly localFriends;
|
|
1536
1540
|
static buildDefault(reg: IRegistry, obj: IObject): CurrentScope;
|
|
1537
1541
|
private static addBuiltIn;
|
|
1538
1542
|
private constructor();
|
|
@@ -1581,6 +1585,9 @@ export declare class CurrentScope {
|
|
|
1581
1585
|
push(stype: ScopeType, sname: string, start: Position, filename: string): void;
|
|
1582
1586
|
isOO(): boolean;
|
|
1583
1587
|
isAnyOO(): boolean;
|
|
1588
|
+
addLocalFriend(className: string, friendName: string): void;
|
|
1589
|
+
isLocalFriend(className: string, friendName: string): boolean;
|
|
1590
|
+
getEnclosingClassName(): string | undefined;
|
|
1584
1591
|
isGlobalOO(): boolean;
|
|
1585
1592
|
isTypePool(): boolean;
|
|
1586
1593
|
setAllowHeaderUse(name: string): void;
|
|
@@ -3277,6 +3284,7 @@ export declare interface IClassDefinition extends IInterfaceDefinition {
|
|
|
3277
3284
|
isAbstract(): boolean;
|
|
3278
3285
|
isSharedMemory(): boolean;
|
|
3279
3286
|
getFriends(): string[];
|
|
3287
|
+
getCreateVisibility(): Visibility;
|
|
3280
3288
|
}
|
|
3281
3289
|
|
|
3282
3290
|
declare interface IClassImplementation extends Identifier {
|
|
@@ -13,7 +13,9 @@ class ReadTable {
|
|
|
13
13
|
const key = (0, combi_1.seq)((0, combi_1.altPrio)("WITH KEY", "WITH TABLE KEY"), (0, combi_1.alt)(expressions_1.ComponentCompareSimple, components, (0, combi_1.seq)((0, combi_1.optPrio)("="), expressions_1.Source)));
|
|
14
14
|
const using = (0, combi_1.seq)("USING KEY", (0, combi_1.alt)(expressions_1.Field, expressions_1.Dynamic));
|
|
15
15
|
const from = (0, combi_1.seq)("FROM", expressions_1.Source);
|
|
16
|
-
const
|
|
16
|
+
const transporting = (0, combi_1.seq)("TRANSPORTING", (0, combi_1.altPrio)("ALL FIELDS", "NO FIELDS", transporting_fields_1.TransportingFields));
|
|
17
|
+
const common = [expressions_1.ReadTableTarget, comparing, "CASTING", transporting, "BINARY SEARCH"];
|
|
18
|
+
const perm = (0, combi_1.alt)((0, combi_1.per)((0, combi_1.alt)(index, from), using, ...common), (0, combi_1.per)(key, ...common), (0, combi_1.per)(...common));
|
|
17
19
|
return (0, combi_1.seq)("READ TABLE", (0, combi_1.alt)(expressions_1.SimpleSource2, (0, combi_1.ver)(version_1.Version.v740sp02, expressions_1.Source, version_1.Version.OpenABAP)), (0, combi_1.opt)(perm));
|
|
18
20
|
}
|
|
19
21
|
}
|
|
@@ -504,7 +504,7 @@ BuiltIn.methods = {
|
|
|
504
504
|
"CONCAT_LINES_OF": {
|
|
505
505
|
counter: BuiltIn.counter++,
|
|
506
506
|
mandatory: {
|
|
507
|
-
"table": new basic_1.TableType(basic_1.AnyType.get(), { withHeader: false, keyType: basic_1.TableKeyType.
|
|
507
|
+
"table": new basic_1.TableType(basic_1.AnyType.get(), { withHeader: false, keyType: basic_1.TableKeyType.user }),
|
|
508
508
|
},
|
|
509
509
|
optional: {
|
|
510
510
|
"sep": basic_1.CLikeType.get(),
|
|
@@ -802,7 +802,7 @@ BuiltIn.methods = {
|
|
|
802
802
|
"LINES": {
|
|
803
803
|
counter: BuiltIn.counter++,
|
|
804
804
|
mandatory: {
|
|
805
|
-
"val": new basic_1.TableType(basic_1.AnyType.get(), { withHeader: false, keyType: basic_1.TableKeyType.
|
|
805
|
+
"val": new basic_1.TableType(basic_1.AnyType.get(), { withHeader: false, keyType: basic_1.TableKeyType.user }),
|
|
806
806
|
},
|
|
807
807
|
return: basic_1.IntegerType.get(),
|
|
808
808
|
},
|
|
@@ -29,6 +29,7 @@ class CurrentScope {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
constructor(reg, obj) {
|
|
32
|
+
this.localFriends = new Map();
|
|
32
33
|
this.current = undefined;
|
|
33
34
|
this.parentObj = obj;
|
|
34
35
|
this.reg = reg;
|
|
@@ -452,6 +453,27 @@ class CurrentScope {
|
|
|
452
453
|
}
|
|
453
454
|
return false;
|
|
454
455
|
}
|
|
456
|
+
addLocalFriend(className, friendName) {
|
|
457
|
+
var _a;
|
|
458
|
+
const key = className.toUpperCase();
|
|
459
|
+
const list = (_a = this.localFriends.get(key)) !== null && _a !== void 0 ? _a : [];
|
|
460
|
+
list.push(friendName.toUpperCase());
|
|
461
|
+
this.localFriends.set(key, list);
|
|
462
|
+
}
|
|
463
|
+
isLocalFriend(className, friendName) {
|
|
464
|
+
var _a;
|
|
465
|
+
return ((_a = this.localFriends.get(className.toUpperCase())) === null || _a === void 0 ? void 0 : _a.includes(friendName.toUpperCase())) === true;
|
|
466
|
+
}
|
|
467
|
+
getEnclosingClassName() {
|
|
468
|
+
let curr = this.current;
|
|
469
|
+
while (curr !== undefined) {
|
|
470
|
+
if (curr.getIdentifier().stype === _scope_type_1.ScopeType.ClassImplementation) {
|
|
471
|
+
return curr.getIdentifier().sname;
|
|
472
|
+
}
|
|
473
|
+
curr = curr.getParent();
|
|
474
|
+
}
|
|
475
|
+
return undefined;
|
|
476
|
+
}
|
|
455
477
|
isGlobalOO() {
|
|
456
478
|
return this.parentObj.getType() === "INTF" || this.parentObj.getType() === "CLAS";
|
|
457
479
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TypeUtils = void 0;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
5
|
const basic_1 = require("../types/basic");
|
|
6
|
+
const table_type_1 = require("../types/basic/table_type");
|
|
6
7
|
const enum_type_1 = require("../types/basic/enum_type");
|
|
7
8
|
const cgeneric_type_1 = require("../types/basic/cgeneric_type");
|
|
8
9
|
const Expressions = require("../2_statements/expressions");
|
|
@@ -431,6 +432,17 @@ class TypeUtils {
|
|
|
431
432
|
}
|
|
432
433
|
else if (source instanceof basic_1.TableType) {
|
|
433
434
|
if (target instanceof basic_1.TableType) {
|
|
435
|
+
const sourceKeyType = source.getOptions().keyType;
|
|
436
|
+
const targetKeyType = target.getOptions().keyType;
|
|
437
|
+
if (sourceKeyType !== targetKeyType
|
|
438
|
+
&& sourceKeyType !== table_type_1.TableKeyType.user
|
|
439
|
+
&& targetKeyType !== table_type_1.TableKeyType.user) {
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
if (sourceKeyType === table_type_1.TableKeyType.empty && targetKeyType !== table_type_1.TableKeyType.empty
|
|
443
|
+
&& !(target.getRowType() instanceof basic_1.AnyType)) {
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
434
446
|
return this.isAssignableStrict(source.getRowType(), target.getRowType());
|
|
435
447
|
}
|
|
436
448
|
else if (target instanceof basic_1.UnknownType
|
|
@@ -527,7 +527,7 @@ class BasicTypes {
|
|
|
527
527
|
|| text === "TYPE HASHED TABLE"
|
|
528
528
|
|| text === "TYPE INDEX TABLE"
|
|
529
529
|
|| text === "TYPE ANY TABLE") {
|
|
530
|
-
return new Types.TableType(Types.AnyType.get(), { withHeader: node.concatTokens().toUpperCase().includes("WITH HEADER LINE"), keyType: Types.TableKeyType.
|
|
530
|
+
return new Types.TableType(Types.AnyType.get(), { withHeader: node.concatTokens().toUpperCase().includes("WITH HEADER LINE"), keyType: Types.TableKeyType.user });
|
|
531
531
|
}
|
|
532
532
|
else if (text.startsWith("LIKE ")) {
|
|
533
533
|
let sub = node.findFirstExpression(Expressions.Type);
|
|
@@ -111,7 +111,7 @@ class MethodParameters {
|
|
|
111
111
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
112
112
|
return;
|
|
113
113
|
}
|
|
114
|
-
else if (item.targetType && new _type_utils_1.TypeUtils(input.scope).
|
|
114
|
+
else if (item.targetType && new _type_utils_1.TypeUtils(input.scope).isAssignableStrict(parameterType, item.targetType) === false) {
|
|
115
115
|
const message = "Method parameter type not compatible, " + item.name;
|
|
116
116
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
117
117
|
return;
|
|
@@ -139,7 +139,7 @@ class MethodParameters {
|
|
|
139
139
|
}
|
|
140
140
|
parameterType = parameter.getType();
|
|
141
141
|
}
|
|
142
|
-
if (item.targetType && new _type_utils_1.TypeUtils(input.scope).
|
|
142
|
+
if (item.targetType && new _type_utils_1.TypeUtils(input.scope).isAssignableStrict(parameterType, item.targetType) === false) {
|
|
143
143
|
const message = "Method parameter type not compatible, " + item.name;
|
|
144
144
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
145
145
|
return;
|
|
@@ -12,6 +12,7 @@ const _type_utils_1 = require("../_type_utils");
|
|
|
12
12
|
const _syntax_input_1 = require("../_syntax_input");
|
|
13
13
|
const assert_error_1 = require("../assert_error");
|
|
14
14
|
const _typed_identifier_1 = require("../../types/_typed_identifier");
|
|
15
|
+
const create_object_1 = require("../statements/create_object");
|
|
15
16
|
class NewObject {
|
|
16
17
|
static runSyntax(node, input, targetType) {
|
|
17
18
|
let ret = undefined;
|
|
@@ -45,6 +46,13 @@ class NewObject {
|
|
|
45
46
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
46
47
|
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
47
48
|
}
|
|
49
|
+
if (clas) {
|
|
50
|
+
const err = create_object_1.CreateObject.checkInstantiationAllowed(clas, input);
|
|
51
|
+
if (err) {
|
|
52
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), err));
|
|
53
|
+
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
48
56
|
}
|
|
49
57
|
else if (typeName === "#" && targetType) {
|
|
50
58
|
ret = targetType;
|
|
@@ -66,6 +74,13 @@ class NewObject {
|
|
|
66
74
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
67
75
|
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
68
76
|
}
|
|
77
|
+
if (clas) {
|
|
78
|
+
const err = create_object_1.CreateObject.checkInstantiationAllowed(clas, input);
|
|
79
|
+
if (err) {
|
|
80
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), err));
|
|
81
|
+
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
69
84
|
ret = objref;
|
|
70
85
|
}
|
|
71
86
|
}
|
|
@@ -322,16 +322,17 @@ class Select {
|
|
|
322
322
|
if (dbSources.length !== 1) {
|
|
323
323
|
return basic_1.VoidType.get("SELECT_todo3");
|
|
324
324
|
}
|
|
325
|
+
const tableOptions = { withHeader: false, keyType: basic_1.TableKeyType.empty };
|
|
325
326
|
if (dbSources[0] === undefined) {
|
|
326
327
|
// then its a voided table
|
|
327
|
-
return basic_1.VoidType.get("SELECT_todo4");
|
|
328
|
+
return new basic_1.TableType(basic_1.VoidType.get("SELECT_todo4"), tableOptions, undefined);
|
|
328
329
|
}
|
|
329
330
|
const dbType = dbSources[0].parseType(scope.getRegistry());
|
|
330
331
|
if (!(dbType instanceof basic_1.StructureType)) {
|
|
331
332
|
return basic_1.VoidType.get("SELECT_todo5");
|
|
332
333
|
}
|
|
333
334
|
if (fields.length === 1 && fields[0].code === "*") {
|
|
334
|
-
return new basic_1.TableType(dbType,
|
|
335
|
+
return new basic_1.TableType(dbType, tableOptions, undefined);
|
|
335
336
|
}
|
|
336
337
|
const allFieldsSimple = fields.every(f => isSimple.test(f.code));
|
|
337
338
|
if (allFieldsSimple === true) {
|
|
@@ -343,7 +344,7 @@ class Select {
|
|
|
343
344
|
}
|
|
344
345
|
components.push({ name: field.code, type });
|
|
345
346
|
}
|
|
346
|
-
return new basic_1.TableType(new basic_1.StructureType(components),
|
|
347
|
+
return new basic_1.TableType(new basic_1.StructureType(components), tableOptions, undefined);
|
|
347
348
|
}
|
|
348
349
|
return basic_1.VoidType.get("SELECT_todo7");
|
|
349
350
|
}
|
|
@@ -121,6 +121,11 @@ class Source {
|
|
|
121
121
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
122
122
|
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
123
123
|
}
|
|
124
|
+
else if (foundType === null || foundType === void 0 ? void 0 : foundType.isGeneric()) {
|
|
125
|
+
const message = "Cannot CONV to generic type";
|
|
126
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
127
|
+
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
128
|
+
}
|
|
124
129
|
this.addIfInferred(node, input, foundType);
|
|
125
130
|
return foundType;
|
|
126
131
|
}
|
|
@@ -6,6 +6,7 @@ const _reference_1 = require("../_reference");
|
|
|
6
6
|
const _syntax_input_1 = require("../_syntax_input");
|
|
7
7
|
class ClassLocalFriends {
|
|
8
8
|
runSyntax(node, input) {
|
|
9
|
+
var _a;
|
|
9
10
|
const classNames = node.findAllExpressions(Expressions.ClassName);
|
|
10
11
|
const found = classNames[0];
|
|
11
12
|
if (found) {
|
|
@@ -36,6 +37,12 @@ class ClassLocalFriends {
|
|
|
36
37
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
37
38
|
return;
|
|
38
39
|
}
|
|
40
|
+
else {
|
|
41
|
+
const befriendedName = (_a = classNames[0]) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr();
|
|
42
|
+
if (befriendedName) {
|
|
43
|
+
input.scope.addLocalFriend(befriendedName, className);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
39
46
|
}
|
|
40
47
|
}
|
|
41
48
|
}
|
|
@@ -11,6 +11,7 @@ const types_1 = require("../../types");
|
|
|
11
11
|
const _object_oriented_1 = require("../_object_oriented");
|
|
12
12
|
const _type_utils_1 = require("../_type_utils");
|
|
13
13
|
const _syntax_input_1 = require("../_syntax_input");
|
|
14
|
+
const visibility_1 = require("../../4_file_information/visibility");
|
|
14
15
|
class CreateObject {
|
|
15
16
|
runSyntax(node, input) {
|
|
16
17
|
var _a;
|
|
@@ -107,8 +108,46 @@ class CreateObject {
|
|
|
107
108
|
ooName = found.getVoided();
|
|
108
109
|
}
|
|
109
110
|
input.scope.addReference(t === null || t === void 0 ? void 0 : t.getFirstToken(), cdef, _reference_1.ReferenceType.ConstructorReference, input.filename, { ooName: ooName });
|
|
111
|
+
if (cdef !== undefined) {
|
|
112
|
+
const err = CreateObject.checkInstantiationAllowed(cdef, input);
|
|
113
|
+
if (err) {
|
|
114
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), err));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
110
118
|
this.validateParameters(cdef, node, input);
|
|
111
119
|
}
|
|
120
|
+
static checkInstantiationAllowed(cdef, input) {
|
|
121
|
+
var _a, _b;
|
|
122
|
+
const createVis = cdef.getCreateVisibility();
|
|
123
|
+
if (createVis === visibility_1.Visibility.Public) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
const enclosingClass = input.scope.getEnclosingClassName();
|
|
127
|
+
if (enclosingClass === undefined) {
|
|
128
|
+
return cdef.getName() + " cannot be instantiated, class is defined as " +
|
|
129
|
+
(createVis === visibility_1.Visibility.Private ? "private" : "protected");
|
|
130
|
+
}
|
|
131
|
+
if (enclosingClass.toUpperCase() === cdef.getName().toUpperCase()) {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
if (cdef.getFriends().some(f => f.toUpperCase() === enclosingClass.toUpperCase()) ||
|
|
135
|
+
input.scope.isLocalFriend(cdef.getName(), enclosingClass)) {
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
if (createVis === visibility_1.Visibility.Protected) {
|
|
139
|
+
// subclasses are also allowed
|
|
140
|
+
let sup = (_a = input.scope.findClassDefinition(enclosingClass)) === null || _a === void 0 ? void 0 : _a.getSuperClass();
|
|
141
|
+
while (sup !== undefined) {
|
|
142
|
+
if (sup.toUpperCase() === cdef.getName().toUpperCase()) {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
sup = (_b = input.scope.findClassDefinition(sup)) === null || _b === void 0 ? void 0 : _b.getSuperClass();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return cdef.getName() + " cannot be instantiated, class is defined as " +
|
|
149
|
+
(createVis === visibility_1.Visibility.Private ? "private" : "protected");
|
|
150
|
+
}
|
|
112
151
|
validateParameters(cdef, node, input) {
|
|
113
152
|
var _a, _b, _c, _d;
|
|
114
153
|
if (cdef === undefined) {
|
|
@@ -26,6 +26,7 @@ class Attributes {
|
|
|
26
26
|
this.instance = [];
|
|
27
27
|
this.constants = [];
|
|
28
28
|
this.aliases = [];
|
|
29
|
+
this.declaredInterfaces = [];
|
|
29
30
|
this.tlist = [];
|
|
30
31
|
this.filename = input.filename;
|
|
31
32
|
this.parse(node, input);
|
|
@@ -101,8 +102,15 @@ class Attributes {
|
|
|
101
102
|
}
|
|
102
103
|
/////////////////////////////
|
|
103
104
|
parse(node, input) {
|
|
105
|
+
var _a, _b;
|
|
104
106
|
const cdef = node.findDirectStructure(Structures.ClassDefinition);
|
|
105
107
|
if (cdef) {
|
|
108
|
+
for (const i of cdef.findAllStatements(Statements.InterfaceDef)) {
|
|
109
|
+
const name = (_a = i.findFirstExpression(Expressions.InterfaceName)) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr();
|
|
110
|
+
if (name) {
|
|
111
|
+
this.declaredInterfaces.push(name.toUpperCase());
|
|
112
|
+
}
|
|
113
|
+
}
|
|
106
114
|
this.parseSection(cdef.findDirectStructure(Structures.PublicSection), visibility_1.Visibility.Public, input);
|
|
107
115
|
this.parseSection(cdef.findDirectStructure(Structures.ProtectedSection), visibility_1.Visibility.Protected, input);
|
|
108
116
|
this.parseSection(cdef.findDirectStructure(Structures.PrivateSection), visibility_1.Visibility.Private, input);
|
|
@@ -110,6 +118,12 @@ class Attributes {
|
|
|
110
118
|
}
|
|
111
119
|
const idef = node.findDirectStructure(Structures.Interface);
|
|
112
120
|
if (idef) {
|
|
121
|
+
for (const i of idef.findAllStatements(Statements.InterfaceDef)) {
|
|
122
|
+
const name = (_b = i.findFirstExpression(Expressions.InterfaceName)) === null || _b === void 0 ? void 0 : _b.getFirstToken().getStr();
|
|
123
|
+
if (name) {
|
|
124
|
+
this.declaredInterfaces.push(name.toUpperCase());
|
|
125
|
+
}
|
|
126
|
+
}
|
|
113
127
|
this.parseSection(idef.findDirectStructure(Structures.SectionContents), visibility_1.Visibility.Public, input);
|
|
114
128
|
return;
|
|
115
129
|
}
|
|
@@ -218,6 +232,12 @@ class Attributes {
|
|
|
218
232
|
input.scope.addNamedIdentifier(aliasName.getStr(), foundAttribute);
|
|
219
233
|
}
|
|
220
234
|
}
|
|
235
|
+
else if (this.declaredInterfaces.includes(name.toUpperCase()) || input.scope.getDDIC().inErrorNamespace(name) === false) {
|
|
236
|
+
input.scope.addReference(compToken, undefined, _reference_1.ReferenceType.ObjectOrientedVoidReference, input.filename);
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
throw new Error("Interface " + name + " not found");
|
|
240
|
+
}
|
|
221
241
|
}
|
|
222
242
|
}
|
|
223
243
|
parseAttribute(node, visibility, input) {
|
|
@@ -13,6 +13,7 @@ const event_definition_1 = require("./event_definition");
|
|
|
13
13
|
const visibility_1 = require("../4_file_information/visibility");
|
|
14
14
|
const _object_oriented_1 = require("../5_syntax/_object_oriented");
|
|
15
15
|
const _reference_1 = require("../5_syntax/_reference");
|
|
16
|
+
const _syntax_input_1 = require("../5_syntax/_syntax_input");
|
|
16
17
|
class ClassDefinition extends _identifier_1.Identifier {
|
|
17
18
|
constructor(node, input) {
|
|
18
19
|
var _a;
|
|
@@ -50,6 +51,15 @@ class ClassDefinition extends _identifier_1.Identifier {
|
|
|
50
51
|
this.testing = concat.includes(" FOR TESTING");
|
|
51
52
|
this.sharedMemory = concat.includes(" SHARED MEMORY ENABLED");
|
|
52
53
|
this.abstract = (def === null || def === void 0 ? void 0 : def.findDirectTokenByText("ABSTRACT")) !== undefined;
|
|
54
|
+
if (concat.includes(" CREATE PRIVATE")) {
|
|
55
|
+
this.createVisibilityValue = visibility_1.Visibility.Private;
|
|
56
|
+
}
|
|
57
|
+
else if (concat.includes(" CREATE PROTECTED")) {
|
|
58
|
+
this.createVisibilityValue = visibility_1.Visibility.Protected;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
this.createVisibilityValue = visibility_1.Visibility.Public;
|
|
62
|
+
}
|
|
53
63
|
// perform checks after everything has been initialized
|
|
54
64
|
this.checkMethodsFromSuperClasses(input.scope);
|
|
55
65
|
this.checkMethodNameLength();
|
|
@@ -93,6 +103,9 @@ class ClassDefinition extends _identifier_1.Identifier {
|
|
|
93
103
|
isSharedMemory() {
|
|
94
104
|
return this.sharedMemory;
|
|
95
105
|
}
|
|
106
|
+
getCreateVisibility() {
|
|
107
|
+
return this.createVisibilityValue;
|
|
108
|
+
}
|
|
96
109
|
/*
|
|
97
110
|
public getEvents() {
|
|
98
111
|
}
|
|
@@ -148,8 +161,20 @@ class ClassDefinition extends _identifier_1.Identifier {
|
|
|
148
161
|
const result = [];
|
|
149
162
|
for (const n of ((_a = def === null || def === void 0 ? void 0 : def.findDirectExpression(Expressions.ClassFriends)) === null || _a === void 0 ? void 0 : _a.findDirectExpressions(Expressions.ClassName)) || []) {
|
|
150
163
|
const token = n.getFirstToken();
|
|
151
|
-
this.addReference(token, input);
|
|
152
164
|
const name = token.getStr();
|
|
165
|
+
const s = input.scope.findClassDefinition(name);
|
|
166
|
+
if (s) {
|
|
167
|
+
input.scope.addReference(token, s, _reference_1.ReferenceType.ObjectOrientedReference, input.filename, { ooName: name.toUpperCase(), ooType: "CLAS" });
|
|
168
|
+
}
|
|
169
|
+
else if (input.scope.existsObject(name) !== undefined) {
|
|
170
|
+
// DEFINITION DEFERRED friend
|
|
171
|
+
}
|
|
172
|
+
else if (input.scope.getDDIC().inErrorNamespace(name) === false) {
|
|
173
|
+
input.scope.addReference(token, undefined, _reference_1.ReferenceType.ObjectOrientedVoidReference, input.filename);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, token, name.toUpperCase() + " does not exist"));
|
|
177
|
+
}
|
|
153
178
|
result.push(name);
|
|
154
179
|
}
|
|
155
180
|
return result;
|
package/build/src/registry.js
CHANGED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CatchAndRaise = exports.CatchAndRaiseConf = void 0;
|
|
4
|
+
const issue_1 = require("../issue");
|
|
5
|
+
const _abap_rule_1 = require("./_abap_rule");
|
|
6
|
+
const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
7
|
+
const _irule_1 = require("./_irule");
|
|
8
|
+
const Structures = require("../abap/3_structures/structures");
|
|
9
|
+
const Statements = require("../abap/2_statements/statements");
|
|
10
|
+
const Expressions = require("../abap/2_statements/expressions");
|
|
11
|
+
class CatchAndRaiseConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
12
|
+
}
|
|
13
|
+
exports.CatchAndRaiseConf = CatchAndRaiseConf;
|
|
14
|
+
class CatchAndRaise extends _abap_rule_1.ABAPRule {
|
|
15
|
+
constructor() {
|
|
16
|
+
super(...arguments);
|
|
17
|
+
this.conf = new CatchAndRaiseConf();
|
|
18
|
+
}
|
|
19
|
+
getMetadata() {
|
|
20
|
+
return {
|
|
21
|
+
key: "catch_and_raise",
|
|
22
|
+
title: "Catch and re-raise same exception",
|
|
23
|
+
shortDescription: `Reports CATCH blocks that only re-raise the caught exception without any handling`,
|
|
24
|
+
badExample: `TRY.\n something( ).\nCATCH zcx_something INTO DATA(lv_exc).\n RAISE EXCEPTION lv_exc.\nENDTRY.`,
|
|
25
|
+
goodExample: `TRY.\n something( ).\nCATCH zcx_something.\n " handle exception\nENDTRY.`,
|
|
26
|
+
tags: [_irule_1.RuleTag.SingleFile],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
getConfig() {
|
|
30
|
+
return this.conf;
|
|
31
|
+
}
|
|
32
|
+
setConfig(conf) {
|
|
33
|
+
this.conf = conf;
|
|
34
|
+
}
|
|
35
|
+
runParsed(file) {
|
|
36
|
+
const issues = [];
|
|
37
|
+
const stru = file.getStructure();
|
|
38
|
+
if (stru === undefined) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
for (const catchStruct of stru.findAllStructures(Structures.Catch)) {
|
|
42
|
+
const catchStatement = catchStruct.findDirectStatement(Statements.Catch);
|
|
43
|
+
if (catchStatement === undefined) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const target = catchStatement.findFirstExpression(Expressions.Target);
|
|
47
|
+
if (target === undefined) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const targetField = target.findFirstExpression(Expressions.TargetField);
|
|
51
|
+
if (targetField === undefined) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const caughtVar = targetField.getFirstToken().getStr().toUpperCase();
|
|
55
|
+
const allStatements = catchStruct.findAllStatementNodes();
|
|
56
|
+
if (allStatements.length !== 2) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (!(allStatements[1].get() instanceof Statements.Raise)) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const raiseStatement = allStatements[1];
|
|
63
|
+
const raiseConcat = raiseStatement.concatTokens().toUpperCase().replace(/\.$/, "").trim();
|
|
64
|
+
if (!raiseConcat.startsWith("RAISE EXCEPTION ")) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const parts = raiseConcat.split(/\s+/);
|
|
68
|
+
if (parts.length !== 3) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (parts[2] === caughtVar) {
|
|
72
|
+
issues.push(issue_1.Issue.atStatement(file, catchStatement, this.getMessage(), this.getMetadata().key, this.conf.severity));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return issues;
|
|
76
|
+
}
|
|
77
|
+
getMessage() {
|
|
78
|
+
return "Caught exception is immediately re-raised, CATCH block has no effect";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.CatchAndRaise = CatchAndRaise;
|
|
82
|
+
//# sourceMappingURL=catch_and_raise.js.map
|
package/build/src/rules/index.js
CHANGED
|
@@ -28,6 +28,7 @@ __exportStar(require("./avoid_use"), exports);
|
|
|
28
28
|
__exportStar(require("./begin_end_names"), exports);
|
|
29
29
|
__exportStar(require("./begin_single_include"), exports);
|
|
30
30
|
__exportStar(require("./call_transaction_authority_check"), exports);
|
|
31
|
+
__exportStar(require("./catch_and_raise"), exports);
|
|
31
32
|
__exportStar(require("./cds_association_name"), exports);
|
|
32
33
|
__exportStar(require("./cds_comment_style"), exports);
|
|
33
34
|
__exportStar(require("./cds_field_order"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abaplint/core",
|
|
3
|
-
"version": "2.118.
|
|
3
|
+
"version": "2.118.6",
|
|
4
4
|
"description": "abaplint - Core API",
|
|
5
5
|
"main": "build/src/index.js",
|
|
6
6
|
"typings": "build/abaplint.d.ts",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"typescript": "^5.9.3"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"fast-xml-parser": "^5.5.
|
|
66
|
+
"fast-xml-parser": "^5.5.9",
|
|
67
67
|
"json5": "^2.2.3",
|
|
68
68
|
"vscode-languageserver-types": "^3.17.5"
|
|
69
69
|
}
|