@abaplint/core 2.118.3 → 2.118.5

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.
@@ -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[];
@@ -491,6 +492,7 @@ declare namespace BasicTypes {
491
492
  DecFloatType,
492
493
  DecFloat16Type,
493
494
  DecFloat34Type,
495
+ EnumType,
494
496
  FloatType,
495
497
  FloatingPointType,
496
498
  GenericObjectReferenceType,
@@ -1188,6 +1190,7 @@ declare class ClassDefinition_3 extends Identifier implements IClassDefinition {
1188
1190
  private readonly globalValue;
1189
1191
  private readonly sharedMemory;
1190
1192
  private readonly aliases;
1193
+ private readonly createVisibilityValue;
1191
1194
  constructor(node: StructureNode, input: SyntaxInput);
1192
1195
  getFriends(): string[];
1193
1196
  getEvents(): IEventDefinition[];
@@ -1202,6 +1205,7 @@ declare class ClassDefinition_3 extends Identifier implements IClassDefinition {
1202
1205
  isForTesting(): boolean;
1203
1206
  isAbstract(): boolean;
1204
1207
  isSharedMemory(): boolean;
1208
+ getCreateVisibility(): Visibility;
1205
1209
  private findSuper;
1206
1210
  private checkMethodNameLength;
1207
1211
  private checkMethodsFromSuperClasses;
@@ -1532,6 +1536,7 @@ export declare class CurrentScope {
1532
1536
  protected current: SpaghettiScopeNode | undefined;
1533
1537
  protected allowHeaderUse: string | undefined;
1534
1538
  protected parentObj: IObject;
1539
+ private readonly localFriends;
1535
1540
  static buildDefault(reg: IRegistry, obj: IObject): CurrentScope;
1536
1541
  private static addBuiltIn;
1537
1542
  private constructor();
@@ -1580,6 +1585,9 @@ export declare class CurrentScope {
1580
1585
  push(stype: ScopeType, sname: string, start: Position, filename: string): void;
1581
1586
  isOO(): boolean;
1582
1587
  isAnyOO(): boolean;
1588
+ addLocalFriend(className: string, friendName: string): void;
1589
+ isLocalFriend(className: string, friendName: string): boolean;
1590
+ getEnclosingClassName(): string | undefined;
1583
1591
  isGlobalOO(): boolean;
1584
1592
  isTypePool(): boolean;
1585
1593
  setAllowHeaderUse(name: string): void;
@@ -2264,6 +2272,14 @@ declare class EntityType extends AbstractObject {
2264
2272
  getDescription(): string | undefined;
2265
2273
  }
2266
2274
 
2275
+ declare class EnumType extends AbstractType {
2276
+ toText(): string;
2277
+ isGeneric(): boolean;
2278
+ toABAP(): string;
2279
+ containsVoid(): boolean;
2280
+ toCDS(): string;
2281
+ }
2282
+
2267
2283
  declare class EventBinding extends AbstractObject {
2268
2284
  getType(): string;
2269
2285
  getAllowedNaming(): {
@@ -3268,6 +3284,7 @@ export declare interface IClassDefinition extends IInterfaceDefinition {
3268
3284
  isAbstract(): boolean;
3269
3285
  isSharedMemory(): boolean;
3270
3286
  getFriends(): string[];
3287
+ getCreateVisibility(): Visibility;
3271
3288
  }
3272
3289
 
3273
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 perm = (0, combi_1.per)((0, combi_1.alt)(index, key, from), expressions_1.ReadTableTarget, using, comparing, "CASTING", (0, combi_1.seq)("TRANSPORTING", (0, combi_1.altPrio)("ALL FIELDS", "NO FIELDS", transporting_fields_1.TransportingFields)), "BINARY SEARCH");
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.default }),
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.default }),
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,8 @@ 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");
7
+ const enum_type_1 = require("../types/basic/enum_type");
6
8
  const cgeneric_type_1 = require("../types/basic/cgeneric_type");
7
9
  const Expressions = require("../2_statements/expressions");
8
10
  // todo: refactor to static? for performance
@@ -79,7 +81,8 @@ class TypeUtils {
79
81
  || type instanceof basic_1.DataType
80
82
  || type instanceof basic_1.CLikeType
81
83
  || type instanceof basic_1.PackedType
82
- || type instanceof basic_1.TimeType) {
84
+ || type instanceof basic_1.TimeType
85
+ || type instanceof enum_type_1.EnumType) {
83
86
  return true;
84
87
  }
85
88
  return false;
@@ -429,6 +432,13 @@ class TypeUtils {
429
432
  }
430
433
  else if (source instanceof basic_1.TableType) {
431
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
+ }
432
442
  return this.isAssignableStrict(source.getRowType(), target.getRowType());
433
443
  }
434
444
  else if (target instanceof basic_1.UnknownType
@@ -486,6 +496,13 @@ class TypeUtils {
486
496
  return false;
487
497
  }
488
498
  }
499
+ const sourceKeyType = source.getOptions().keyType;
500
+ const targetKeyType = target.getOptions().keyType;
501
+ if (sourceKeyType !== targetKeyType
502
+ && sourceKeyType !== table_type_1.TableKeyType.user
503
+ && targetKeyType !== table_type_1.TableKeyType.user) {
504
+ return false;
505
+ }
489
506
  return true;
490
507
  }
491
508
  return false;
@@ -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.default });
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);
@@ -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
  }
@@ -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) {
@@ -11,7 +11,7 @@ const _syntax_input_1 = require("../_syntax_input");
11
11
  class Split {
12
12
  runSyntax(node, input) {
13
13
  const intoTable = node.findTokenSequencePosition("INTO", "TABLE") !== undefined;
14
- const type = intoTable ? new basic_1.TableType(basic_1.StringType.get(), { withHeader: false, keyType: basic_1.TableKeyType.default }) : basic_1.StringType.get();
14
+ const type = intoTable ? new basic_1.TableType(basic_1.StringType.get(), { withHeader: false, keyType: basic_1.TableKeyType.user }) : basic_1.StringType.get();
15
15
  for (const target of node.findAllExpressions(Expressions.Target)) {
16
16
  const inline = target.findDirectExpression(Expressions.InlineData);
17
17
  if (inline) {
@@ -25,6 +25,7 @@ __exportStar(require("./date_type"), exports);
25
25
  __exportStar(require("./decfloat_type"), exports);
26
26
  __exportStar(require("./decfloat16_type"), exports);
27
27
  __exportStar(require("./decfloat34_type"), exports);
28
+ __exportStar(require("./enum_type"), exports);
28
29
  __exportStar(require("./float_type"), exports);
29
30
  __exportStar(require("./floating_point_type"), exports);
30
31
  __exportStar(require("./generic_object_reference_type"), exports);
@@ -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;
@@ -74,7 +74,7 @@ class Registry {
74
74
  }
75
75
  static abaplintVersion() {
76
76
  // magic, see build script "version.sh"
77
- return "2.118.3";
77
+ return "2.118.5";
78
78
  }
79
79
  getDDICReferences() {
80
80
  return this.ddicReferences;
@@ -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
@@ -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",
3
+ "version": "2.118.5",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",