@abaplint/cli 2.120.56 → 2.120.58
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 +461 -7
- package/package.json +2 -2
package/build/cli.js
CHANGED
|
@@ -6484,7 +6484,8 @@ const Expressions = __importStar(__webpack_require__(/*! . */ "../core/build/src
|
|
|
6484
6484
|
const tokens_1 = __webpack_require__(/*! ../../1_lexer/tokens */ "../core/build/src/abap/1_lexer/tokens/index.js");
|
|
6485
6485
|
class MethodDefReturning extends combi_1.Expression {
|
|
6486
6486
|
getRunnable() {
|
|
6487
|
-
|
|
6487
|
+
// see MethodParam: the lexer gives "!VALUE" as one Identifier
|
|
6488
|
+
const value = (0, combi_1.seq)((0, combi_1.altPrio)("VALUE", "!VALUE"), (0, combi_1.tok)(tokens_1.ParenLeft), Expressions.MethodParamName, (0, combi_1.tok)(tokens_1.ParenRightW));
|
|
6488
6489
|
return (0, combi_1.seq)("RETURNING", value, Expressions.TypeParam);
|
|
6489
6490
|
}
|
|
6490
6491
|
}
|
|
@@ -6562,8 +6563,11 @@ const Expressions = __importStar(__webpack_require__(/*! . */ "../core/build/src
|
|
|
6562
6563
|
const tokens_1 = __webpack_require__(/*! ../../1_lexer/tokens */ "../core/build/src/abap/1_lexer/tokens/index.js");
|
|
6563
6564
|
class MethodParam extends combi_1.Expression {
|
|
6564
6565
|
getRunnable() {
|
|
6565
|
-
|
|
6566
|
-
|
|
6566
|
+
// The escape is part of the token: the lexer gives "!VALUE" as a single
|
|
6567
|
+
// Identifier, so a literal "VALUE" cannot match it and the whole METHODS
|
|
6568
|
+
// statement falls back to Unknown.
|
|
6569
|
+
const ref = (0, combi_1.seq)((0, combi_1.altPrio)("REFERENCE", "!REFERENCE"), (0, combi_1.tok)(tokens_1.ParenLeft), Expressions.MethodParamName, (0, combi_1.tok)(tokens_1.ParenRightW));
|
|
6570
|
+
const value = (0, combi_1.seq)((0, combi_1.altPrio)("VALUE", "!VALUE"), (0, combi_1.tok)(tokens_1.ParenLeft), Expressions.MethodParamName, (0, combi_1.tok)(tokens_1.ParenRightW));
|
|
6567
6571
|
const fieldsOrValue = (0, combi_1.seq)((0, combi_1.altPrio)(value, ref, Expressions.MethodParamName), Expressions.TypeParam);
|
|
6568
6572
|
return fieldsOrValue;
|
|
6569
6573
|
}
|
|
@@ -11547,6 +11551,10 @@ class StatementParser {
|
|
|
11547
11551
|
let add = [];
|
|
11548
11552
|
let pre = [];
|
|
11549
11553
|
let colon = undefined;
|
|
11554
|
+
// inside EXEC SQL and an AMDP body a colon reads a host variable, ":lv_a",
|
|
11555
|
+
// and is not the chaining marker; recognized here because nativeSQL() runs
|
|
11556
|
+
// afterwards and can only re-wrap what this has already cut
|
|
11557
|
+
let native = false;
|
|
11550
11558
|
for (const token of wa.tokens) {
|
|
11551
11559
|
if (token instanceof Tokens.Comment) {
|
|
11552
11560
|
wa.statements.push(new nodes_1.StatementNode(new _statement_1.Comment()).setChildren(this.tokensToNodes([token])));
|
|
@@ -11556,6 +11564,7 @@ class StatementParser {
|
|
|
11556
11564
|
const str = token.getStr();
|
|
11557
11565
|
if (str.length === 1) {
|
|
11558
11566
|
if (str === ".") {
|
|
11567
|
+
native = this.nativeAfter(native, add, colon);
|
|
11559
11568
|
wa.addUnknown(pre, add, colon);
|
|
11560
11569
|
add = [];
|
|
11561
11570
|
pre = [];
|
|
@@ -11565,13 +11574,13 @@ class StatementParser {
|
|
|
11565
11574
|
wa.addUnknown(pre, add, colon);
|
|
11566
11575
|
add = [];
|
|
11567
11576
|
}
|
|
11568
|
-
else if (str === ":" && colon === undefined) {
|
|
11577
|
+
else if (str === ":" && colon === undefined && native === false) {
|
|
11569
11578
|
colon = token;
|
|
11570
11579
|
add.pop(); // do not add colon token to statement
|
|
11571
11580
|
pre.push(...add);
|
|
11572
11581
|
add = [];
|
|
11573
11582
|
}
|
|
11574
|
-
else if (str === ":") {
|
|
11583
|
+
else if (str === ":" && native === false) {
|
|
11575
11584
|
add.pop(); // do not add colon token to statement
|
|
11576
11585
|
}
|
|
11577
11586
|
}
|
|
@@ -11580,6 +11589,36 @@ class StatementParser {
|
|
|
11580
11589
|
wa.addUnknown(pre, add, colon);
|
|
11581
11590
|
}
|
|
11582
11591
|
}
|
|
11592
|
+
/** whether the statement that just ended opens or closes a region where a
|
|
11593
|
+
* colon belongs to the statement rather than chaining it */
|
|
11594
|
+
nativeAfter(native, tokens, colon) {
|
|
11595
|
+
// a pragma sits between the closing keyword and the period, so it is left
|
|
11596
|
+
// out before the last word is read: "ENDEXEC ##NEEDED." closes the region
|
|
11597
|
+
const words = tokens.filter(t => !(t instanceof Tokens.Pragma)).map(t => t.getStr().toUpperCase());
|
|
11598
|
+
// a native body usually arrives as one blob terminated by its own closing
|
|
11599
|
+
// keyword, so the terminator is the word before the period
|
|
11600
|
+
if (words[words.length - 2] === "ENDEXEC" || words[words.length - 2] === "ENDMETHOD") {
|
|
11601
|
+
return false;
|
|
11602
|
+
}
|
|
11603
|
+
if (colon !== undefined) {
|
|
11604
|
+
// a fragment of a chain cannot OPEN a region: it is only part of a
|
|
11605
|
+
// statement, and taking "DATA: lv_a TYPE i, exec sql." for one would
|
|
11606
|
+
// turn chaining off for the rest of the file
|
|
11607
|
+
return native;
|
|
11608
|
+
}
|
|
11609
|
+
if (words[0] === "EXEC" && words[1] === "SQL") {
|
|
11610
|
+
return true;
|
|
11611
|
+
}
|
|
11612
|
+
// "BY DATABASE" as well as LANGUAGE, and not LANGUAGE alone: a method
|
|
11613
|
+
// may be NAMED language
|
|
11614
|
+
if (words[0] === "METHOD"
|
|
11615
|
+
&& words.includes("BY")
|
|
11616
|
+
&& words.includes("DATABASE")
|
|
11617
|
+
&& words.includes("LANGUAGE")) {
|
|
11618
|
+
return true;
|
|
11619
|
+
}
|
|
11620
|
+
return native;
|
|
11621
|
+
}
|
|
11583
11622
|
}
|
|
11584
11623
|
exports.StatementParser = StatementParser;
|
|
11585
11624
|
//# sourceMappingURL=statement_parser.js.map
|
|
@@ -53956,7 +53995,9 @@ class MethodParameters {
|
|
|
53956
53995
|
}
|
|
53957
53996
|
isPassByValue(param) {
|
|
53958
53997
|
var _a;
|
|
53959
|
-
|
|
53998
|
+
// "!" is the identifier escape, generated code has eg. "IMPORTING !VALUE(iv_foo)"
|
|
53999
|
+
const first = param.getFirstToken().getStr().toUpperCase();
|
|
54000
|
+
return (first === "VALUE" || first === "!VALUE")
|
|
53960
54001
|
&& ((_a = param.getChildren()[1]) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr()) === "(";
|
|
53961
54002
|
}
|
|
53962
54003
|
}
|
|
@@ -70644,7 +70685,7 @@ class Registry {
|
|
|
70644
70685
|
}
|
|
70645
70686
|
static abaplintVersion() {
|
|
70646
70687
|
// magic, see build script "version.js"
|
|
70647
|
-
return "2.120.
|
|
70688
|
+
return "2.120.58";
|
|
70648
70689
|
}
|
|
70649
70690
|
getDDICReferences() {
|
|
70650
70691
|
return this.ddicReferences;
|
|
@@ -85040,7 +85081,9 @@ __exportStar(__webpack_require__(/*! ./prefer_insert_into_table */ "../core/buil
|
|
|
85040
85081
|
__exportStar(__webpack_require__(/*! ./prefer_is_not */ "../core/build/src/rules/prefer_is_not.js"), exports);
|
|
85041
85082
|
__exportStar(__webpack_require__(/*! ./prefer_pragmas */ "../core/build/src/rules/prefer_pragmas.js"), exports);
|
|
85042
85083
|
__exportStar(__webpack_require__(/*! ./prefer_abap_bool */ "../core/build/src/rules/prefer_abap_bool.js"), exports);
|
|
85084
|
+
__exportStar(__webpack_require__(/*! ./prefer_abap_bool_values */ "../core/build/src/rules/prefer_abap_bool_values.js"), exports);
|
|
85043
85085
|
__exportStar(__webpack_require__(/*! ./prefer_raise_exception_new */ "../core/build/src/rules/prefer_raise_exception_new.js"), exports);
|
|
85086
|
+
__exportStar(__webpack_require__(/*! ./prefer_string_template */ "../core/build/src/rules/prefer_string_template.js"), exports);
|
|
85044
85087
|
__exportStar(__webpack_require__(/*! ./prefer_returning_to_exporting */ "../core/build/src/rules/prefer_returning_to_exporting.js"), exports);
|
|
85045
85088
|
__exportStar(__webpack_require__(/*! ./prefer_xsdbool */ "../core/build/src/rules/prefer_xsdbool.js"), exports);
|
|
85046
85089
|
__exportStar(__webpack_require__(/*! ./preferred_compare_operator */ "../core/build/src/rules/preferred_compare_operator.js"), exports);
|
|
@@ -92443,6 +92486,272 @@ exports.PreferAbapBool = PreferAbapBool;
|
|
|
92443
92486
|
|
|
92444
92487
|
/***/ },
|
|
92445
92488
|
|
|
92489
|
+
/***/ "../core/build/src/rules/prefer_abap_bool_values.js"
|
|
92490
|
+
/*!**********************************************************!*\
|
|
92491
|
+
!*** ../core/build/src/rules/prefer_abap_bool_values.js ***!
|
|
92492
|
+
\**********************************************************/
|
|
92493
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
92494
|
+
|
|
92495
|
+
"use strict";
|
|
92496
|
+
|
|
92497
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
92498
|
+
if (k2 === undefined) k2 = k;
|
|
92499
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
92500
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
92501
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
92502
|
+
}
|
|
92503
|
+
Object.defineProperty(o, k2, desc);
|
|
92504
|
+
}) : (function(o, m, k, k2) {
|
|
92505
|
+
if (k2 === undefined) k2 = k;
|
|
92506
|
+
o[k2] = m[k];
|
|
92507
|
+
}));
|
|
92508
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
92509
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
92510
|
+
}) : function(o, v) {
|
|
92511
|
+
o["default"] = v;
|
|
92512
|
+
});
|
|
92513
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
92514
|
+
var ownKeys = function(o) {
|
|
92515
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
92516
|
+
var ar = [];
|
|
92517
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
92518
|
+
return ar;
|
|
92519
|
+
};
|
|
92520
|
+
return ownKeys(o);
|
|
92521
|
+
};
|
|
92522
|
+
return function (mod) {
|
|
92523
|
+
if (mod && mod.__esModule) return mod;
|
|
92524
|
+
var result = {};
|
|
92525
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
92526
|
+
__setModuleDefault(result, mod);
|
|
92527
|
+
return result;
|
|
92528
|
+
};
|
|
92529
|
+
})();
|
|
92530
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
92531
|
+
exports.PreferAbapBoolValues = exports.PreferAbapBoolValuesConf = void 0;
|
|
92532
|
+
const issue_1 = __webpack_require__(/*! ../issue */ "../core/build/src/issue.js");
|
|
92533
|
+
const _abap_rule_1 = __webpack_require__(/*! ./_abap_rule */ "../core/build/src/rules/_abap_rule.js");
|
|
92534
|
+
const Expressions = __importStar(__webpack_require__(/*! ../abap/2_statements/expressions */ "../core/build/src/abap/2_statements/expressions/index.js"));
|
|
92535
|
+
const Statements = __importStar(__webpack_require__(/*! ../abap/2_statements/statements */ "../core/build/src/abap/2_statements/statements/index.js"));
|
|
92536
|
+
const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "../core/build/src/rules/_basic_rule_config.js");
|
|
92537
|
+
const _irule_1 = __webpack_require__(/*! ./_irule */ "../core/build/src/rules/_irule.js");
|
|
92538
|
+
const edit_helper_1 = __webpack_require__(/*! ../edit_helper */ "../core/build/src/edit_helper.js");
|
|
92539
|
+
const nodes_1 = __webpack_require__(/*! ../abap/nodes */ "../core/build/src/abap/nodes/index.js");
|
|
92540
|
+
const ABAP_BOOL = "ABAP_BOOL";
|
|
92541
|
+
const ABAP_TRUE = "abap_true";
|
|
92542
|
+
const ABAP_FALSE = "abap_false";
|
|
92543
|
+
const VALID_VALUES = new Set(["ABAP_TRUE", "ABAP_FALSE", "ABAP_UNDEFINED"]);
|
|
92544
|
+
class PreferAbapBoolValuesConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
92545
|
+
}
|
|
92546
|
+
exports.PreferAbapBoolValuesConf = PreferAbapBoolValuesConf;
|
|
92547
|
+
class PreferAbapBoolValues extends _abap_rule_1.ABAPRule {
|
|
92548
|
+
constructor() {
|
|
92549
|
+
super(...arguments);
|
|
92550
|
+
this.conf = new PreferAbapBoolValuesConf();
|
|
92551
|
+
}
|
|
92552
|
+
getMetadata() {
|
|
92553
|
+
return {
|
|
92554
|
+
key: "prefer_abap_bool_values",
|
|
92555
|
+
title: "Prefer abap_true and abap_false",
|
|
92556
|
+
shortDescription: `Use abap_true and abap_false instead of 'X' and ' ' for abap_bool variables`,
|
|
92557
|
+
// eslint-disable-next-line max-len
|
|
92558
|
+
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#use-abap_true-abap_false-and-abap_undefined-for-abap_bool-variables`,
|
|
92559
|
+
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Quickfix],
|
|
92560
|
+
badExample: `DATA lv_flag TYPE abap_bool.\nlv_flag = 'X'.`,
|
|
92561
|
+
goodExample: `DATA lv_flag TYPE abap_bool.\nlv_flag = abap_true.`,
|
|
92562
|
+
};
|
|
92563
|
+
}
|
|
92564
|
+
getConfig() {
|
|
92565
|
+
return this.conf;
|
|
92566
|
+
}
|
|
92567
|
+
setConfig(conf) {
|
|
92568
|
+
this.conf = conf;
|
|
92569
|
+
}
|
|
92570
|
+
runParsed(file) {
|
|
92571
|
+
const issues = [];
|
|
92572
|
+
const structure = file.getStructure();
|
|
92573
|
+
if (structure === undefined) {
|
|
92574
|
+
return [];
|
|
92575
|
+
}
|
|
92576
|
+
const boolVars = this.collectBoolVars(file);
|
|
92577
|
+
// Check Move statements: target = source
|
|
92578
|
+
for (const stat of structure.findAllStatements(Statements.Move)) {
|
|
92579
|
+
const target = stat.findFirstExpression(Expressions.Target);
|
|
92580
|
+
const source = stat.findFirstExpression(Expressions.Source);
|
|
92581
|
+
if (target === undefined || source === undefined) {
|
|
92582
|
+
continue;
|
|
92583
|
+
}
|
|
92584
|
+
const targetName = target.concatTokens().toUpperCase();
|
|
92585
|
+
if (!boolVars.has(targetName)) {
|
|
92586
|
+
continue;
|
|
92587
|
+
}
|
|
92588
|
+
this.checkSourceNode(source, file, issues);
|
|
92589
|
+
}
|
|
92590
|
+
// Check comparisons: IF/ELSEIF conditions
|
|
92591
|
+
const compareStatements = [
|
|
92592
|
+
...structure.findAllStatements(Statements.If),
|
|
92593
|
+
...structure.findAllStatements(Statements.ElseIf),
|
|
92594
|
+
];
|
|
92595
|
+
for (const stat of compareStatements) {
|
|
92596
|
+
const cond = stat.findFirstExpression(Expressions.Cond);
|
|
92597
|
+
if (cond === undefined) {
|
|
92598
|
+
continue;
|
|
92599
|
+
}
|
|
92600
|
+
for (const compare of cond.findAllExpressions(Expressions.Compare)) {
|
|
92601
|
+
this.checkCompareBoolLiteral(compare, boolVars, file, issues);
|
|
92602
|
+
}
|
|
92603
|
+
}
|
|
92604
|
+
return issues;
|
|
92605
|
+
}
|
|
92606
|
+
collectBoolVars(file) {
|
|
92607
|
+
var _a;
|
|
92608
|
+
const boolVars = new Set();
|
|
92609
|
+
const structure = file.getStructure();
|
|
92610
|
+
if (structure === undefined) {
|
|
92611
|
+
return boolVars;
|
|
92612
|
+
}
|
|
92613
|
+
const statements = [
|
|
92614
|
+
...structure.findAllStatements(Statements.Data),
|
|
92615
|
+
...structure.findAllStatements(Statements.ClassData),
|
|
92616
|
+
...structure.findAllStatements(Statements.FieldSymbol),
|
|
92617
|
+
];
|
|
92618
|
+
for (const stat of statements) {
|
|
92619
|
+
const typeNameExpr = stat.findFirstExpression(Expressions.TypeName);
|
|
92620
|
+
if (typeNameExpr === undefined) {
|
|
92621
|
+
continue;
|
|
92622
|
+
}
|
|
92623
|
+
if (typeNameExpr.concatTokens().toUpperCase() !== ABAP_BOOL) {
|
|
92624
|
+
continue;
|
|
92625
|
+
}
|
|
92626
|
+
const nameExpr = (_a = stat.findFirstExpression(Expressions.DefinitionName)) !== null && _a !== void 0 ? _a : stat.findFirstExpression(Expressions.FieldSymbol);
|
|
92627
|
+
if (nameExpr === undefined) {
|
|
92628
|
+
continue;
|
|
92629
|
+
}
|
|
92630
|
+
boolVars.add(nameExpr.concatTokens().toUpperCase());
|
|
92631
|
+
}
|
|
92632
|
+
return boolVars;
|
|
92633
|
+
}
|
|
92634
|
+
checkSourceNode(source, file, issues) {
|
|
92635
|
+
const firstToken = source.getFirstToken().getStr().toUpperCase();
|
|
92636
|
+
if (firstToken === "COND") {
|
|
92637
|
+
const condBody = source.findDirectExpression(Expressions.CondBody);
|
|
92638
|
+
if (condBody) {
|
|
92639
|
+
this.checkCondBodyBranches(condBody, file, issues);
|
|
92640
|
+
}
|
|
92641
|
+
return;
|
|
92642
|
+
}
|
|
92643
|
+
if (firstToken === "SWITCH") {
|
|
92644
|
+
const switchBody = source.findDirectExpression(Expressions.SwitchBody);
|
|
92645
|
+
if (switchBody) {
|
|
92646
|
+
this.checkSwitchBodyBranches(switchBody, file, issues);
|
|
92647
|
+
}
|
|
92648
|
+
return;
|
|
92649
|
+
}
|
|
92650
|
+
// Plain literal assignment
|
|
92651
|
+
const issue = this.checkLiteralSource(source, file);
|
|
92652
|
+
if (issue) {
|
|
92653
|
+
issues.push(issue);
|
|
92654
|
+
}
|
|
92655
|
+
}
|
|
92656
|
+
checkLiteralSource(source, file) {
|
|
92657
|
+
const constantStr = source.findFirstExpression(Expressions.ConstantString);
|
|
92658
|
+
if (constantStr === undefined) {
|
|
92659
|
+
return undefined;
|
|
92660
|
+
}
|
|
92661
|
+
const token = constantStr.getFirstToken();
|
|
92662
|
+
const val = token.getStr();
|
|
92663
|
+
if (val === "'X'") {
|
|
92664
|
+
const fix = edit_helper_1.EditHelper.replaceToken(file, token, ABAP_TRUE);
|
|
92665
|
+
return issue_1.Issue.atToken(file, token, `Use ${ABAP_TRUE} instead of 'X'`, this.getMetadata().key, this.conf.severity, fix);
|
|
92666
|
+
}
|
|
92667
|
+
if (val === "' '") {
|
|
92668
|
+
const fix = edit_helper_1.EditHelper.replaceToken(file, token, ABAP_FALSE);
|
|
92669
|
+
return issue_1.Issue.atToken(file, token, `Use ${ABAP_FALSE} instead of ' '`, this.getMetadata().key, this.conf.severity, fix);
|
|
92670
|
+
}
|
|
92671
|
+
return undefined;
|
|
92672
|
+
}
|
|
92673
|
+
checkCondBodyBranches(condBody, file, issues) {
|
|
92674
|
+
// CondBody: WHEN <cond> THEN <source> [WHEN <cond> THEN <source>]* [ELSE <source>]
|
|
92675
|
+
// Walk children; Source nodes after THEN/ELSE are the result values
|
|
92676
|
+
let afterThenOrElse = false;
|
|
92677
|
+
for (const child of condBody.getChildren()) {
|
|
92678
|
+
const tokenStr = child.getFirstToken().getStr().toUpperCase();
|
|
92679
|
+
if (tokenStr === "THEN" || tokenStr === "ELSE") {
|
|
92680
|
+
afterThenOrElse = true;
|
|
92681
|
+
continue;
|
|
92682
|
+
}
|
|
92683
|
+
if (tokenStr === "WHEN") {
|
|
92684
|
+
afterThenOrElse = false;
|
|
92685
|
+
continue;
|
|
92686
|
+
}
|
|
92687
|
+
if (afterThenOrElse && child instanceof nodes_1.ExpressionNode && child.get() instanceof Expressions.Source) {
|
|
92688
|
+
const issue = this.checkLiteralSource(child, file);
|
|
92689
|
+
if (issue) {
|
|
92690
|
+
issues.push(issue);
|
|
92691
|
+
}
|
|
92692
|
+
afterThenOrElse = false;
|
|
92693
|
+
}
|
|
92694
|
+
}
|
|
92695
|
+
}
|
|
92696
|
+
checkSwitchBodyBranches(switchBody, file, issues) {
|
|
92697
|
+
// SwitchBody: <source> WHEN <val> [OR <val>]* THEN <source> [ELSE <source>]
|
|
92698
|
+
// First Source is the operand; Source after THEN/ELSE are result values
|
|
92699
|
+
let firstSourceSeen = false;
|
|
92700
|
+
let afterThenOrElse = false;
|
|
92701
|
+
for (const child of switchBody.getChildren()) {
|
|
92702
|
+
const tokenStr = child.getFirstToken().getStr().toUpperCase();
|
|
92703
|
+
if (tokenStr === "THEN" || tokenStr === "ELSE") {
|
|
92704
|
+
afterThenOrElse = true;
|
|
92705
|
+
continue;
|
|
92706
|
+
}
|
|
92707
|
+
if (tokenStr === "WHEN" || tokenStr === "OR") {
|
|
92708
|
+
afterThenOrElse = false;
|
|
92709
|
+
continue;
|
|
92710
|
+
}
|
|
92711
|
+
if (child instanceof nodes_1.ExpressionNode && child.get() instanceof Expressions.Source) {
|
|
92712
|
+
if (!firstSourceSeen) {
|
|
92713
|
+
firstSourceSeen = true;
|
|
92714
|
+
continue;
|
|
92715
|
+
}
|
|
92716
|
+
if (afterThenOrElse) {
|
|
92717
|
+
const issue = this.checkLiteralSource(child, file);
|
|
92718
|
+
if (issue) {
|
|
92719
|
+
issues.push(issue);
|
|
92720
|
+
}
|
|
92721
|
+
afterThenOrElse = false;
|
|
92722
|
+
}
|
|
92723
|
+
}
|
|
92724
|
+
}
|
|
92725
|
+
}
|
|
92726
|
+
checkCompareBoolLiteral(compare, boolVars, file, issues) {
|
|
92727
|
+
// Compare: Source CompareOperator Source (or other forms)
|
|
92728
|
+
const sources = compare.findDirectExpressions(Expressions.Source);
|
|
92729
|
+
if (sources.length < 2) {
|
|
92730
|
+
return;
|
|
92731
|
+
}
|
|
92732
|
+
const [left, right] = sources;
|
|
92733
|
+
const leftStr = left.concatTokens().toUpperCase();
|
|
92734
|
+
const rightStr = right.concatTokens().toUpperCase();
|
|
92735
|
+
let literalSource;
|
|
92736
|
+
if (boolVars.has(leftStr) && !VALID_VALUES.has(rightStr)) {
|
|
92737
|
+
literalSource = right;
|
|
92738
|
+
}
|
|
92739
|
+
else if (boolVars.has(rightStr) && !VALID_VALUES.has(leftStr)) {
|
|
92740
|
+
literalSource = left;
|
|
92741
|
+
}
|
|
92742
|
+
if (literalSource) {
|
|
92743
|
+
const issue = this.checkLiteralSource(literalSource, file);
|
|
92744
|
+
if (issue) {
|
|
92745
|
+
issues.push(issue);
|
|
92746
|
+
}
|
|
92747
|
+
}
|
|
92748
|
+
}
|
|
92749
|
+
}
|
|
92750
|
+
exports.PreferAbapBoolValues = PreferAbapBoolValues;
|
|
92751
|
+
//# sourceMappingURL=prefer_abap_bool_values.js.map
|
|
92752
|
+
|
|
92753
|
+
/***/ },
|
|
92754
|
+
|
|
92446
92755
|
/***/ "../core/build/src/rules/prefer_corresponding.js"
|
|
92447
92756
|
/*!*******************************************************!*\
|
|
92448
92757
|
!*** ../core/build/src/rules/prefer_corresponding.js ***!
|
|
@@ -93432,6 +93741,151 @@ exports.PreferReturningToExporting = PreferReturningToExporting;
|
|
|
93432
93741
|
|
|
93433
93742
|
/***/ },
|
|
93434
93743
|
|
|
93744
|
+
/***/ "../core/build/src/rules/prefer_string_template.js"
|
|
93745
|
+
/*!*********************************************************!*\
|
|
93746
|
+
!*** ../core/build/src/rules/prefer_string_template.js ***!
|
|
93747
|
+
\*********************************************************/
|
|
93748
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
93749
|
+
|
|
93750
|
+
"use strict";
|
|
93751
|
+
|
|
93752
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
93753
|
+
if (k2 === undefined) k2 = k;
|
|
93754
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
93755
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
93756
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
93757
|
+
}
|
|
93758
|
+
Object.defineProperty(o, k2, desc);
|
|
93759
|
+
}) : (function(o, m, k, k2) {
|
|
93760
|
+
if (k2 === undefined) k2 = k;
|
|
93761
|
+
o[k2] = m[k];
|
|
93762
|
+
}));
|
|
93763
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
93764
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
93765
|
+
}) : function(o, v) {
|
|
93766
|
+
o["default"] = v;
|
|
93767
|
+
});
|
|
93768
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
93769
|
+
var ownKeys = function(o) {
|
|
93770
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
93771
|
+
var ar = [];
|
|
93772
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
93773
|
+
return ar;
|
|
93774
|
+
};
|
|
93775
|
+
return ownKeys(o);
|
|
93776
|
+
};
|
|
93777
|
+
return function (mod) {
|
|
93778
|
+
if (mod && mod.__esModule) return mod;
|
|
93779
|
+
var result = {};
|
|
93780
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
93781
|
+
__setModuleDefault(result, mod);
|
|
93782
|
+
return result;
|
|
93783
|
+
};
|
|
93784
|
+
})();
|
|
93785
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
93786
|
+
exports.PreferStringTemplate = exports.PreferStringTemplateConf = void 0;
|
|
93787
|
+
const issue_1 = __webpack_require__(/*! ../issue */ "../core/build/src/issue.js");
|
|
93788
|
+
const _abap_rule_1 = __webpack_require__(/*! ./_abap_rule */ "../core/build/src/rules/_abap_rule.js");
|
|
93789
|
+
const Expressions = __importStar(__webpack_require__(/*! ../abap/2_statements/expressions */ "../core/build/src/abap/2_statements/expressions/index.js"));
|
|
93790
|
+
const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "../core/build/src/rules/_basic_rule_config.js");
|
|
93791
|
+
const _irule_1 = __webpack_require__(/*! ./_irule */ "../core/build/src/rules/_irule.js");
|
|
93792
|
+
const nodes_1 = __webpack_require__(/*! ../abap/nodes */ "../core/build/src/abap/nodes/index.js");
|
|
93793
|
+
const edit_helper_1 = __webpack_require__(/*! ../edit_helper */ "../core/build/src/edit_helper.js");
|
|
93794
|
+
class PreferStringTemplateConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
93795
|
+
}
|
|
93796
|
+
exports.PreferStringTemplateConf = PreferStringTemplateConf;
|
|
93797
|
+
class PreferStringTemplate extends _abap_rule_1.ABAPRule {
|
|
93798
|
+
constructor() {
|
|
93799
|
+
super(...arguments);
|
|
93800
|
+
this.conf = new PreferStringTemplateConf();
|
|
93801
|
+
}
|
|
93802
|
+
getMetadata() {
|
|
93803
|
+
return {
|
|
93804
|
+
key: "prefer_string_template",
|
|
93805
|
+
title: "Prefer string template over &&",
|
|
93806
|
+
shortDescription: `Use string templates instead of && to assemble text`,
|
|
93807
|
+
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#use--to-assemble-text`,
|
|
93808
|
+
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Quickfix],
|
|
93809
|
+
badExample: `DATA(msg) = \`Hello \` && name && \`!\`.`,
|
|
93810
|
+
goodExample: `DATA(msg) = |Hello { name }!|.`,
|
|
93811
|
+
};
|
|
93812
|
+
}
|
|
93813
|
+
getConfig() {
|
|
93814
|
+
return this.conf;
|
|
93815
|
+
}
|
|
93816
|
+
setConfig(conf) {
|
|
93817
|
+
this.conf = conf;
|
|
93818
|
+
}
|
|
93819
|
+
runParsed(file) {
|
|
93820
|
+
const issues = [];
|
|
93821
|
+
const structure = file.getStructure();
|
|
93822
|
+
if (structure === undefined) {
|
|
93823
|
+
return [];
|
|
93824
|
+
}
|
|
93825
|
+
const allSources = structure.findAllExpressions(Expressions.Source);
|
|
93826
|
+
// collect all Source nodes that appear as the RHS (children[2]) of a && expression
|
|
93827
|
+
const rhsChildren = new Set();
|
|
93828
|
+
for (const source of allSources) {
|
|
93829
|
+
const children = source.getChildren();
|
|
93830
|
+
if (children.length === 3 && children[1].getFirstToken().getStr() === "&&") {
|
|
93831
|
+
rhsChildren.add(children[2]);
|
|
93832
|
+
}
|
|
93833
|
+
}
|
|
93834
|
+
for (const source of allSources) {
|
|
93835
|
+
const children = source.getChildren();
|
|
93836
|
+
if (children.length !== 3) {
|
|
93837
|
+
continue;
|
|
93838
|
+
}
|
|
93839
|
+
if (children[1].getFirstToken().getStr() !== "&&") {
|
|
93840
|
+
continue;
|
|
93841
|
+
}
|
|
93842
|
+
// only process top-level && roots (not nested RHS children)
|
|
93843
|
+
if (rhsChildren.has(source)) {
|
|
93844
|
+
continue;
|
|
93845
|
+
}
|
|
93846
|
+
const operands = this.flattenChain(source);
|
|
93847
|
+
if (!operands.some(op => { const c = op.getFirstToken().getStr()[0]; return c === "'" || c === "`"; })) {
|
|
93848
|
+
continue;
|
|
93849
|
+
}
|
|
93850
|
+
const template = this.buildTemplate(operands);
|
|
93851
|
+
const start = source.getFirstToken().getStart();
|
|
93852
|
+
const end = source.getLastToken().getEnd();
|
|
93853
|
+
const fix = edit_helper_1.EditHelper.replaceRange(file, start, end, template);
|
|
93854
|
+
const token = children[1].getFirstToken();
|
|
93855
|
+
issues.push(issue_1.Issue.atToken(file, token, "Use string template instead of &&", this.getMetadata().key, this.conf.severity, fix));
|
|
93856
|
+
}
|
|
93857
|
+
return issues;
|
|
93858
|
+
}
|
|
93859
|
+
flattenChain(node) {
|
|
93860
|
+
const children = node.getChildren();
|
|
93861
|
+
if (children.length === 3 && children[1].getFirstToken().getStr() === "&&") {
|
|
93862
|
+
return [...this.flattenChain(children[0]), ...this.flattenChain(children[2])];
|
|
93863
|
+
}
|
|
93864
|
+
if (children.length === 1 && children[0] instanceof nodes_1.ExpressionNode) {
|
|
93865
|
+
return this.flattenChain(children[0]);
|
|
93866
|
+
}
|
|
93867
|
+
return [node];
|
|
93868
|
+
}
|
|
93869
|
+
buildTemplate(operands) {
|
|
93870
|
+
let inner = "";
|
|
93871
|
+
for (const op of operands) {
|
|
93872
|
+
const raw = op.getFirstToken().getStr();
|
|
93873
|
+
const firstChar = raw[0];
|
|
93874
|
+
if (firstChar === "'" || firstChar === "`") {
|
|
93875
|
+
inner += raw.slice(1, -1);
|
|
93876
|
+
}
|
|
93877
|
+
else {
|
|
93878
|
+
inner += `{ ${op.concatTokens()} }`;
|
|
93879
|
+
}
|
|
93880
|
+
}
|
|
93881
|
+
return `|${inner}|`;
|
|
93882
|
+
}
|
|
93883
|
+
}
|
|
93884
|
+
exports.PreferStringTemplate = PreferStringTemplate;
|
|
93885
|
+
//# sourceMappingURL=prefer_string_template.js.map
|
|
93886
|
+
|
|
93887
|
+
/***/ },
|
|
93888
|
+
|
|
93435
93889
|
/***/ "../core/build/src/rules/prefer_xsdbool.js"
|
|
93436
93890
|
/*!*************************************************!*\
|
|
93437
93891
|
!*** ../core/build/src/rules/prefer_xsdbool.js ***!
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abaplint/cli",
|
|
3
|
-
"version": "2.120.
|
|
3
|
+
"version": "2.120.58",
|
|
4
4
|
"description": "abaplint - Command Line Interface",
|
|
5
5
|
"funding": "https://github.com/sponsors/larshp",
|
|
6
6
|
"bin": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"homepage": "https://abaplint.org",
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@abaplint/core": "^2.120.
|
|
42
|
+
"@abaplint/core": "^2.120.58",
|
|
43
43
|
"@types/chai": "^4.3.20",
|
|
44
44
|
"@types/minimist": "^1.2.5",
|
|
45
45
|
"@types/mocha": "^10.0.10",
|