@abaplint/cli 2.120.67 → 2.120.70
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/cli.js +202 -12
- package/package.json +2 -3
package/build/cli.js
CHANGED
|
@@ -26579,6 +26579,17 @@ class CurrentScope {
|
|
|
26579
26579
|
var _a;
|
|
26580
26580
|
return ((_a = this.localFriends.get(className.toUpperCase())) === null || _a === void 0 ? void 0 : _a.includes(friendName.toUpperCase())) === true;
|
|
26581
26581
|
}
|
|
26582
|
+
getEnclosingMethodName() {
|
|
26583
|
+
let curr = this.current;
|
|
26584
|
+
while (curr !== undefined) {
|
|
26585
|
+
const stype = curr.getIdentifier().stype;
|
|
26586
|
+
if (stype === _scope_type_1.ScopeType.Method || stype === _scope_type_1.ScopeType.MethodInstance) {
|
|
26587
|
+
return curr.getIdentifier().sname;
|
|
26588
|
+
}
|
|
26589
|
+
curr = curr.getParent();
|
|
26590
|
+
}
|
|
26591
|
+
return undefined;
|
|
26592
|
+
}
|
|
26582
26593
|
getEnclosingClassName() {
|
|
26583
26594
|
let curr = this.current;
|
|
26584
26595
|
while (curr !== undefined) {
|
|
@@ -26842,6 +26853,42 @@ class ObjectOriented {
|
|
|
26842
26853
|
}
|
|
26843
26854
|
return "private";
|
|
26844
26855
|
}
|
|
26856
|
+
// the fixture methods of a test class are called by ABAP Unit only, returns the message otherwise
|
|
26857
|
+
checkSpecialTestMethodCall(method, foundDef) {
|
|
26858
|
+
if (method === undefined
|
|
26859
|
+
|| !(foundDef instanceof types_1.ClassDefinition)
|
|
26860
|
+
|| foundDef.isForTesting() === false) {
|
|
26861
|
+
return undefined;
|
|
26862
|
+
}
|
|
26863
|
+
const name = method.getName().toUpperCase();
|
|
26864
|
+
if (["SETUP", "TEARDOWN", "CLASS_SETUP", "CLASS_TEARDOWN"].includes(name) === false) {
|
|
26865
|
+
return undefined;
|
|
26866
|
+
}
|
|
26867
|
+
return `The special method "${name}" cannot be called directly`;
|
|
26868
|
+
}
|
|
26869
|
+
// SUPER-> can only call the previous implementation of the method it is used in, returns the message otherwise
|
|
26870
|
+
// both names are resolved in the super class, so an alias and the method it stands for are the same
|
|
26871
|
+
checkSuperCall(superDef, methodName) {
|
|
26872
|
+
const enclosing = this.scope.getEnclosingMethodName();
|
|
26873
|
+
if (methodName === undefined
|
|
26874
|
+
|| enclosing === undefined
|
|
26875
|
+
|| methodName.toUpperCase() === enclosing.toUpperCase()) {
|
|
26876
|
+
return undefined;
|
|
26877
|
+
}
|
|
26878
|
+
const message = "SUPER-> can only be used to call the previous implementation of the same method";
|
|
26879
|
+
// a method that is not a redefinition has no previous implementation
|
|
26880
|
+
const enclosingClass = this.scope.findClassDefinition(this.scope.getEnclosingClassName());
|
|
26881
|
+
const ownDefinition = enclosingClass === null || enclosingClass === void 0 ? void 0 : enclosingClass.getMethodDefinitions().getByName(enclosing);
|
|
26882
|
+
if (ownDefinition !== undefined && ownDefinition.isRedefinition() === false) {
|
|
26883
|
+
return message;
|
|
26884
|
+
}
|
|
26885
|
+
const called = this.searchMethodName(superDef, methodName).method;
|
|
26886
|
+
const own = this.searchMethodName(superDef, enclosing).method;
|
|
26887
|
+
if (called === undefined || own === undefined || called === own) {
|
|
26888
|
+
return undefined;
|
|
26889
|
+
}
|
|
26890
|
+
return message;
|
|
26891
|
+
}
|
|
26845
26892
|
// the class declaring the attribute or constant, searched from def up through the super classes
|
|
26846
26893
|
findAttributeOwner(def, found) {
|
|
26847
26894
|
const visited = [];
|
|
@@ -31889,6 +31936,9 @@ class FormParam {
|
|
|
31889
31936
|
else if (typeName === "P" && bfound instanceof basic_1.PackedType) {
|
|
31890
31937
|
bfound = basic_1.PGenericType.get();
|
|
31891
31938
|
}
|
|
31939
|
+
else if (typeName === "N" && bfound instanceof basic_1.NumericType) {
|
|
31940
|
+
bfound = basic_1.NGenericType.get();
|
|
31941
|
+
}
|
|
31892
31942
|
}
|
|
31893
31943
|
if (nameToken && bfound) {
|
|
31894
31944
|
return new _typed_identifier_1.TypedIdentifier(nameToken, input.filename, bfound, ["form_parameter" /* IdentifierMeta.FormParameter */]);
|
|
@@ -32840,6 +32890,14 @@ class MethodCallChain {
|
|
|
32840
32890
|
const methodToken = (_a = current.findDirectExpression(Expressions.MethodName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
32841
32891
|
const methodName = methodToken === null || methodToken === void 0 ? void 0 : methodToken.getStr();
|
|
32842
32892
|
const def = input.scope.findObjectDefinition(className);
|
|
32893
|
+
const isSuper = current === children[2]
|
|
32894
|
+
&& first.get() instanceof Expressions.FieldChain
|
|
32895
|
+
&& first.concatTokens().toUpperCase() === "SUPER";
|
|
32896
|
+
const superMessage = isSuper ? helper.checkSuperCall(def, methodName) : undefined;
|
|
32897
|
+
if (superMessage !== undefined) {
|
|
32898
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, superMessage));
|
|
32899
|
+
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
32900
|
+
}
|
|
32843
32901
|
// eslint-disable-next-line prefer-const
|
|
32844
32902
|
let { method, def: foundDef } = helper.searchMethodName(def, methodName);
|
|
32845
32903
|
if (method === undefined && current === first) {
|
|
@@ -32867,6 +32925,11 @@ class MethodCallChain {
|
|
|
32867
32925
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, message));
|
|
32868
32926
|
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
32869
32927
|
}
|
|
32928
|
+
const specialMessage = isSuper ? undefined : helper.checkSpecialTestMethodCall(method, foundDef);
|
|
32929
|
+
if (specialMessage !== undefined) {
|
|
32930
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, specialMessage));
|
|
32931
|
+
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
32932
|
+
}
|
|
32870
32933
|
const voidedName = context instanceof basic_1.VoidType ? context.getVoided() : undefined;
|
|
32871
32934
|
const extra = helper.methodReferenceExtras(foundDef, className || voidedName);
|
|
32872
32935
|
input.scope.addReference(methodToken, method, _reference_1.ReferenceType.MethodReference, input.filename, extra);
|
|
@@ -33262,6 +33325,9 @@ class MethodParam {
|
|
|
33262
33325
|
else if (concat === "TYPE P" || concat.startsWith("TYPE P ")) {
|
|
33263
33326
|
return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, basic_1.PGenericType.get(), meta);
|
|
33264
33327
|
}
|
|
33328
|
+
else if (concat === "TYPE N" || concat.startsWith("TYPE N ")) {
|
|
33329
|
+
return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, basic_1.NGenericType.get(), meta);
|
|
33330
|
+
}
|
|
33265
33331
|
const found = new basic_types_1.BasicTypes(input).parseType(type);
|
|
33266
33332
|
if (found) {
|
|
33267
33333
|
return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, found, meta);
|
|
@@ -33730,6 +33796,14 @@ class MethodSource {
|
|
|
33730
33796
|
const methodToken = current.getFirstToken();
|
|
33731
33797
|
const methodName = methodToken === null || methodToken === void 0 ? void 0 : methodToken.getStr();
|
|
33732
33798
|
const def = input.scope.findObjectDefinition(className);
|
|
33799
|
+
const isSuper = implicitMe === false
|
|
33800
|
+
&& first.get() instanceof Expressions.SourceField
|
|
33801
|
+
&& first.concatTokens().toUpperCase() === "SUPER";
|
|
33802
|
+
const superMessage = isSuper ? helper.checkSuperCall(def, methodName) : undefined;
|
|
33803
|
+
if (superMessage !== undefined) {
|
|
33804
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, superMessage));
|
|
33805
|
+
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
33806
|
+
}
|
|
33733
33807
|
// eslint-disable-next-line prefer-const
|
|
33734
33808
|
let { method, def: foundDef } = helper.searchMethodName(def, methodName);
|
|
33735
33809
|
if (implicitMe && current === first && (method === null || method === void 0 ? void 0 : method.isStatic()) === false && input.scope.isInStaticMethod() === true) {
|
|
@@ -33746,6 +33820,11 @@ class MethodSource {
|
|
|
33746
33820
|
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
33747
33821
|
}
|
|
33748
33822
|
else if (method) {
|
|
33823
|
+
const specialMessage = isSuper ? undefined : helper.checkSpecialTestMethodCall(method, foundDef);
|
|
33824
|
+
if (specialMessage !== undefined) {
|
|
33825
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, specialMessage));
|
|
33826
|
+
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
33827
|
+
}
|
|
33749
33828
|
const extra = helper.methodReferenceExtras(foundDef, className);
|
|
33750
33829
|
input.scope.addReference(methodToken, method, _reference_1.ReferenceType.MethodReference, input.filename, extra);
|
|
33751
33830
|
context = method;
|
|
@@ -34844,6 +34923,7 @@ const corresponding_body_1 = __webpack_require__(/*! ./corresponding_body */ "..
|
|
|
34844
34923
|
const _builtin_1 = __webpack_require__(/*! ../_builtin */ "../core/build/src/abap/5_syntax/_builtin.js");
|
|
34845
34924
|
const attribute_chain_1 = __webpack_require__(/*! ./attribute_chain */ "../core/build/src/abap/5_syntax/expressions/attribute_chain.js");
|
|
34846
34925
|
const dereference_1 = __webpack_require__(/*! ./dereference */ "../core/build/src/abap/5_syntax/expressions/dereference.js");
|
|
34926
|
+
const cast_1 = __webpack_require__(/*! ./cast */ "../core/build/src/abap/5_syntax/expressions/cast.js");
|
|
34847
34927
|
const _typed_identifier_1 = __webpack_require__(/*! ../../types/_typed_identifier */ "../core/build/src/abap/types/_typed_identifier.js");
|
|
34848
34928
|
const _type_utils_1 = __webpack_require__(/*! ../_type_utils */ "../core/build/src/abap/5_syntax/_type_utils.js");
|
|
34849
34929
|
const _syntax_input_1 = __webpack_require__(/*! ../_syntax_input */ "../core/build/src/abap/5_syntax/_syntax_input.js");
|
|
@@ -35067,6 +35147,10 @@ class Source {
|
|
|
35067
35147
|
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
35068
35148
|
}
|
|
35069
35149
|
}
|
|
35150
|
+
else if (get instanceof Expressions.Cast) {
|
|
35151
|
+
const found = cast_1.Cast.runSyntax(first, input, targetType);
|
|
35152
|
+
context = arithmetic === true ? this.infer(context, found, true) : found;
|
|
35153
|
+
}
|
|
35070
35154
|
else if (get instanceof Expressions.FieldChain) {
|
|
35071
35155
|
const found = field_chain_1.FieldChain.runSyntax(first, input, type, allowGenericDeference);
|
|
35072
35156
|
context = arithmetic === true ? this.infer(context, found, true) : found;
|
|
@@ -35083,6 +35167,11 @@ class Source {
|
|
|
35083
35167
|
context = this.infer(context, found, arithmetic);
|
|
35084
35168
|
}
|
|
35085
35169
|
else if (get instanceof Expressions.Dereference) {
|
|
35170
|
+
if (this.isNewObjectDereference(node, first)) {
|
|
35171
|
+
const message = "NEW cannot be dereferenced directly";
|
|
35172
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, first.getFirstToken(), message));
|
|
35173
|
+
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
35174
|
+
}
|
|
35086
35175
|
context = dereference_1.Dereference.runSyntax(first, context, input);
|
|
35087
35176
|
}
|
|
35088
35177
|
else if (get instanceof Expressions.ComponentChain) {
|
|
@@ -35270,6 +35359,16 @@ class Source {
|
|
|
35270
35359
|
}
|
|
35271
35360
|
return targetType;
|
|
35272
35361
|
}
|
|
35362
|
+
// "NEW ty( )->*" is a syntax error, also in releases where a method call can be dereferenced
|
|
35363
|
+
static isNewObjectDereference(node, deref) {
|
|
35364
|
+
var _a;
|
|
35365
|
+
const children = node.getChildren();
|
|
35366
|
+
const before = children[children.indexOf(deref) - 1];
|
|
35367
|
+
return before instanceof nodes_1.ExpressionNode
|
|
35368
|
+
&& before.get() instanceof Expressions.MethodCallChain
|
|
35369
|
+
&& before.getChildren().length === 1
|
|
35370
|
+
&& ((_a = before.getFirstChild()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.NewObject;
|
|
35371
|
+
}
|
|
35273
35372
|
}
|
|
35274
35373
|
exports.Source = Source;
|
|
35275
35374
|
//# sourceMappingURL=source.js.map
|
|
@@ -39931,9 +40030,9 @@ class CreateObject {
|
|
|
39931
40030
|
if (name === undefined) {
|
|
39932
40031
|
continue;
|
|
39933
40032
|
}
|
|
39934
|
-
const source = p.findDirectExpression(Expressions.Source);
|
|
39935
|
-
const sourceType = source_1.Source.runSyntax(source, input);
|
|
39936
40033
|
const found = allImporting === null || allImporting === void 0 ? void 0 : allImporting.find(p => p.getName().toUpperCase() === name);
|
|
40034
|
+
const source = p.findDirectExpression(Expressions.Source);
|
|
40035
|
+
const sourceType = source_1.Source.runSyntax(source, input, found === null || found === void 0 ? void 0 : found.getType());
|
|
39937
40036
|
if (found === undefined) {
|
|
39938
40037
|
const message = `constructor parameter "${name}" does not exist`;
|
|
39939
40038
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
@@ -51390,6 +51489,7 @@ __exportStar(__webpack_require__(/*! ./generic_object_reference_type */ "../core
|
|
|
51390
51489
|
__exportStar(__webpack_require__(/*! ./hex_type */ "../core/build/src/abap/types/basic/hex_type.js"), exports);
|
|
51391
51490
|
__exportStar(__webpack_require__(/*! ./integer_type */ "../core/build/src/abap/types/basic/integer_type.js"), exports);
|
|
51392
51491
|
__exportStar(__webpack_require__(/*! ./integer8_type */ "../core/build/src/abap/types/basic/integer8_type.js"), exports);
|
|
51492
|
+
__exportStar(__webpack_require__(/*! ./ngeneric_type */ "../core/build/src/abap/types/basic/ngeneric_type.js"), exports);
|
|
51393
51493
|
__exportStar(__webpack_require__(/*! ./numeric_generic_type */ "../core/build/src/abap/types/basic/numeric_generic_type.js"), exports);
|
|
51394
51494
|
__exportStar(__webpack_require__(/*! ./numeric_type */ "../core/build/src/abap/types/basic/numeric_type.js"), exports);
|
|
51395
51495
|
__exportStar(__webpack_require__(/*! ./object_reference_type */ "../core/build/src/abap/types/basic/object_reference_type.js"), exports);
|
|
@@ -51498,6 +51598,39 @@ IntegerType.singletons = new Map();
|
|
|
51498
51598
|
|
|
51499
51599
|
/***/ },
|
|
51500
51600
|
|
|
51601
|
+
/***/ "../core/build/src/abap/types/basic/ngeneric_type.js"
|
|
51602
|
+
/*!***********************************************************!*\
|
|
51603
|
+
!*** ../core/build/src/abap/types/basic/ngeneric_type.js ***!
|
|
51604
|
+
\***********************************************************/
|
|
51605
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
51606
|
+
|
|
51607
|
+
"use strict";
|
|
51608
|
+
|
|
51609
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
51610
|
+
exports.NGenericType = void 0;
|
|
51611
|
+
const numeric_type_1 = __webpack_require__(/*! ./numeric_type */ "../core/build/src/abap/types/basic/numeric_type.js");
|
|
51612
|
+
// "TYPE n" of a method or FORM parameter, where no length can be given.
|
|
51613
|
+
// It is a NumericType, so everything that handles n keeps treating it as such
|
|
51614
|
+
class NGenericType extends numeric_type_1.NumericType {
|
|
51615
|
+
static get() {
|
|
51616
|
+
return this.singleton;
|
|
51617
|
+
}
|
|
51618
|
+
constructor() {
|
|
51619
|
+
super(1);
|
|
51620
|
+
}
|
|
51621
|
+
toText() {
|
|
51622
|
+
return "```n```";
|
|
51623
|
+
}
|
|
51624
|
+
isGeneric() {
|
|
51625
|
+
return true;
|
|
51626
|
+
}
|
|
51627
|
+
}
|
|
51628
|
+
exports.NGenericType = NGenericType;
|
|
51629
|
+
NGenericType.singleton = new NGenericType();
|
|
51630
|
+
//# sourceMappingURL=ngeneric_type.js.map
|
|
51631
|
+
|
|
51632
|
+
/***/ },
|
|
51633
|
+
|
|
51501
51634
|
/***/ "../core/build/src/abap/types/basic/numeric_generic_type.js"
|
|
51502
51635
|
/*!******************************************************************!*\
|
|
51503
51636
|
!*** ../core/build/src/abap/types/basic/numeric_generic_type.js ***!
|
|
@@ -70392,7 +70525,7 @@ class Registry {
|
|
|
70392
70525
|
}
|
|
70393
70526
|
static abaplintVersion() {
|
|
70394
70527
|
// magic, see build script "version.js"
|
|
70395
|
-
return "2.120.
|
|
70528
|
+
return "2.120.70";
|
|
70396
70529
|
}
|
|
70397
70530
|
getDDICReferences() {
|
|
70398
70531
|
return this.ddicReferences;
|
|
@@ -79891,8 +80024,17 @@ ${indentation} output = ${uniqueName}.\n`;
|
|
|
79891
80024
|
const extra = (valueBody === null || valueBody === void 0 ? void 0 : valueBody.findDirectExpression(Expressions.For)) ? " " : "";
|
|
79892
80025
|
data = indentation + extra + `DATA ${structureName} LIKE LINE OF ${uniqueName}.\n`;
|
|
79893
80026
|
}
|
|
80027
|
+
// all rows are built in the same work area, a component a row leaves out must be initial,
|
|
80028
|
+
// not what an earlier row (or an earlier pass of a surrounding loop) put there
|
|
80029
|
+
const clearRows = valueBody !== undefined && this.valueRowsNeedClear(valueBody);
|
|
80030
|
+
const prefix = [];
|
|
79894
80031
|
for (const a of (valueBody === null || valueBody === void 0 ? void 0 : valueBody.getChildren()) || []) {
|
|
79895
80032
|
if (a.get() instanceof Expressions.FieldAssignment) {
|
|
80033
|
+
if (clearRows === true) {
|
|
80034
|
+
// the shared prefix applies to every following row, re-applied after each CLEAR
|
|
80035
|
+
prefix.push(a.concatTokens());
|
|
80036
|
+
continue;
|
|
80037
|
+
}
|
|
79896
80038
|
if (added === false) {
|
|
79897
80039
|
body += data;
|
|
79898
80040
|
added = true;
|
|
@@ -79916,6 +80058,16 @@ ${indentation} output = ${uniqueName}.\n`;
|
|
|
79916
80058
|
}
|
|
79917
80059
|
if (a instanceof nodes_1.ExpressionNode && a.get() instanceof Expressions.ValueBodyLine) {
|
|
79918
80060
|
let skip = false;
|
|
80061
|
+
if (clearRows === true && this.isStructuredValueRow(a)) {
|
|
80062
|
+
if (added === false) {
|
|
80063
|
+
body += data;
|
|
80064
|
+
added = true;
|
|
80065
|
+
}
|
|
80066
|
+
body += indentation + `CLEAR ${structureName}.\n`;
|
|
80067
|
+
for (const p of prefix) {
|
|
80068
|
+
body += indentation + structureName + "-" + p + ".\n";
|
|
80069
|
+
}
|
|
80070
|
+
}
|
|
79919
80071
|
for (const b of (a === null || a === void 0 ? void 0 : a.getChildren()) || []) {
|
|
79920
80072
|
if (b.get() instanceof Expressions.FieldAssignment) {
|
|
79921
80073
|
if (added === false) {
|
|
@@ -79994,6 +80146,39 @@ ${indentation} output = ${uniqueName}.\n`;
|
|
|
79994
80146
|
}
|
|
79995
80147
|
return undefined;
|
|
79996
80148
|
}
|
|
80149
|
+
/** a row that is built in the work area, ie. not "( source )" or "( LINES OF source )" */
|
|
80150
|
+
isStructuredValueRow(row) {
|
|
80151
|
+
return row.findDirectExpression(Expressions.Source) === undefined
|
|
80152
|
+
&& row.findDirectExpression(Expressions.ValueBodyLines) === undefined;
|
|
80153
|
+
}
|
|
80154
|
+
/** true if a row can observe a component that an earlier row, or an earlier pass of a surrounding loop,
|
|
80155
|
+
* left in the shared work area. Not the case if all rows assign the same components, and the shared
|
|
80156
|
+
* prefix is not changed between rows, eg. FOR rows or "( a = 1 b = 2 ) ( a = 3 b = 4 )" */
|
|
80157
|
+
valueRowsNeedClear(valueBody) {
|
|
80158
|
+
let shape = undefined;
|
|
80159
|
+
let rowSeen = false;
|
|
80160
|
+
for (const c of valueBody.getChildren()) {
|
|
80161
|
+
if (c.get() instanceof Expressions.FieldAssignment) {
|
|
80162
|
+
if (rowSeen === true) {
|
|
80163
|
+
return true;
|
|
80164
|
+
}
|
|
80165
|
+
}
|
|
80166
|
+
else if (c instanceof nodes_1.ExpressionNode
|
|
80167
|
+
&& c.get() instanceof Expressions.ValueBodyLine
|
|
80168
|
+
&& this.isStructuredValueRow(c)) {
|
|
80169
|
+
rowSeen = true;
|
|
80170
|
+
const current = c.findDirectExpressions(Expressions.FieldAssignment)
|
|
80171
|
+
.map(f => { var _a; return (_a = f.findDirectExpression(Expressions.FieldSub)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase().replace(/\s/g, ""); })
|
|
80172
|
+
.sort()
|
|
80173
|
+
.join(",");
|
|
80174
|
+
if (shape !== undefined && shape !== current) {
|
|
80175
|
+
return true;
|
|
80176
|
+
}
|
|
80177
|
+
shape = current;
|
|
80178
|
+
}
|
|
80179
|
+
}
|
|
80180
|
+
return false;
|
|
80181
|
+
}
|
|
79997
80182
|
outlineLet(node, indentation, highSyntax, lowFile) {
|
|
79998
80183
|
var _a;
|
|
79999
80184
|
let ret = "";
|
|
@@ -95269,7 +95454,9 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
|
|
|
95269
95454
|
title: "RFC error handling",
|
|
95270
95455
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
95271
95456
|
shortDescription: `Checks that exceptions 'system_failure' and 'communication_failure' are handled in RFC calls`,
|
|
95272
|
-
extendedInformation: `
|
|
95457
|
+
extendedInformation: `RESOURCE_FAILURE is also required for asynchronous calls with DESTINATION IN GROUP.
|
|
95458
|
+
|
|
95459
|
+
https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/abenrfc_exception.html`,
|
|
95273
95460
|
badExample: `CALL FUNCTION 'ZRFC'
|
|
95274
95461
|
DESTINATION lv_rfc.`,
|
|
95275
95462
|
goodExample: `CALL FUNCTION 'ZRFC'
|
|
@@ -95277,12 +95464,12 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
|
|
|
95277
95464
|
EXCEPTIONS
|
|
95278
95465
|
system_failure = 1 MESSAGE msg
|
|
95279
95466
|
communication_failure = 2 MESSAGE msg
|
|
95280
|
-
|
|
95281
|
-
OTHERS = 4.`,
|
|
95467
|
+
OTHERS = 3.`,
|
|
95282
95468
|
};
|
|
95283
95469
|
}
|
|
95284
|
-
getMessage() {
|
|
95285
|
-
return "RFC error handling: At least one unhandled exception from SYSTEM_FAILURE, COMMUNICATION_FAILURE
|
|
95470
|
+
getMessage(requireResourceFailure) {
|
|
95471
|
+
return "RFC error handling: At least one unhandled exception from SYSTEM_FAILURE, COMMUNICATION_FAILURE"
|
|
95472
|
+
+ (requireResourceFailure ? ", RESOURCE_FAILURE" : "");
|
|
95286
95473
|
}
|
|
95287
95474
|
getConfig() {
|
|
95288
95475
|
return this.conf;
|
|
@@ -95297,12 +95484,15 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
|
|
|
95297
95484
|
if (!(stat.get() instanceof Statements.CallFunction)) {
|
|
95298
95485
|
continue;
|
|
95299
95486
|
}
|
|
95300
|
-
|
|
95487
|
+
const destination = stat.findFirstExpression(Expressions.Destination);
|
|
95488
|
+
if (destination === undefined) {
|
|
95301
95489
|
continue;
|
|
95302
95490
|
}
|
|
95491
|
+
const requireResourceFailure = stat.findDirectTokenByText("STARTING") !== undefined
|
|
95492
|
+
&& destination.findDirectTokenByText("GROUP") !== undefined;
|
|
95303
95493
|
const list = stat.findFirstExpression(Expressions.ParameterListExceptions);
|
|
95304
95494
|
if (list === undefined) {
|
|
95305
|
-
const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
|
|
95495
|
+
const issue = issue_1.Issue.atToken(file, token, this.getMessage(requireResourceFailure), this.getMetadata().key, this.conf.severity);
|
|
95306
95496
|
output.push(issue);
|
|
95307
95497
|
continue;
|
|
95308
95498
|
}
|
|
@@ -95313,8 +95503,8 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
|
|
|
95313
95503
|
}
|
|
95314
95504
|
if (names.indexOf("SYSTEM_FAILURE") < 0
|
|
95315
95505
|
|| names.indexOf("COMMUNICATION_FAILURE") < 0
|
|
95316
|
-
|| names.indexOf("RESOURCE_FAILURE") < 0) {
|
|
95317
|
-
const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
|
|
95506
|
+
|| (requireResourceFailure && names.indexOf("RESOURCE_FAILURE") < 0)) {
|
|
95507
|
+
const issue = issue_1.Issue.atToken(file, token, this.getMessage(requireResourceFailure), this.getMetadata().key, this.conf.severity);
|
|
95318
95508
|
output.push(issue);
|
|
95319
95509
|
continue;
|
|
95320
95510
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
2
|
"name": "@abaplint/cli",
|
|
4
|
-
"version": "2.120.
|
|
3
|
+
"version": "2.120.70",
|
|
5
4
|
"description": "abaplint - Command Line Interface",
|
|
6
5
|
"funding": "https://github.com/sponsors/larshp",
|
|
7
6
|
"bin": {
|
|
@@ -40,7 +39,7 @@
|
|
|
40
39
|
},
|
|
41
40
|
"homepage": "https://abaplint.org",
|
|
42
41
|
"devDependencies": {
|
|
43
|
-
"@abaplint/core": "^2.120.
|
|
42
|
+
"@abaplint/core": "^2.120.70",
|
|
44
43
|
"@types/chai": "^4.3.20",
|
|
45
44
|
"@types/minimist": "^1.2.5",
|
|
46
45
|
"@types/mocha": "^10.0.10",
|