@abaplint/core 2.79.19 → 2.79.23
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/README.md +6 -6
- package/build/abaplint.d.ts +5 -0
- package/build/src/abap/2_statements/expressions/index.js +1 -0
- package/build/src/abap/2_statements/expressions/reduce_body.js +2 -2
- package/build/src/abap/2_statements/expressions/reduce_next.js +13 -0
- package/build/src/abap/5_syntax/_builtin.js +50 -50
- package/build/src/abap/5_syntax/basic_types.js +7 -1
- package/build/src/abap/5_syntax/expressions/method_source.js +8 -2
- package/build/src/abap/5_syntax/expressions/reduce_body.js +4 -0
- package/build/src/abap/5_syntax/expressions/reduce_next.js +17 -0
- package/build/src/abap/5_syntax/statements/tables.js +1 -1
- package/build/src/ddic.js +6 -6
- package/build/src/lsp/_lookup.js +13 -11
- package/build/src/lsp/help.js +7 -7
- package/build/src/objects/assignment_service_to_authorization_group.js +1 -1
- package/build/src/registry.js +1 -1
- package/build/src/rules/abapdoc.js +1 -1
- package/build/src/rules/ambiguous_statement.js +5 -5
- package/build/src/rules/avoid_use.js +6 -6
- package/build/src/rules/begin_end_names.js +4 -4
- package/build/src/rules/begin_single_include.js +12 -12
- package/build/src/rules/chain_mainly_declarations.js +4 -4
- package/build/src/rules/check_abstract.js +2 -2
- package/build/src/rules/check_comments.js +3 -3
- package/build/src/rules/check_include.js +3 -3
- package/build/src/rules/check_no_handler_pragma.js +8 -8
- package/build/src/rules/check_subrc.js +8 -8
- package/build/src/rules/commented_code.js +1 -1
- package/build/src/rules/constructor_visibility_public.js +4 -4
- package/build/src/rules/contains_tab.js +2 -2
- package/build/src/rules/downport.js +200 -45
- package/build/src/rules/exit_or_check.js +3 -3
- package/build/src/rules/exporting.js +1 -1
- package/build/src/rules/forbidden_identifier.js +1 -1
- package/build/src/rules/forbidden_void_type.js +2 -2
- package/build/src/rules/functional_writing.js +17 -17
- package/build/src/rules/global_class.js +4 -4
- package/build/src/rules/identical_conditions.js +2 -2
- package/build/src/rules/identical_contents.js +15 -15
- package/build/src/rules/identical_descriptions.js +4 -4
- package/build/src/rules/if_in_if.js +7 -7
- package/build/src/rules/implement_methods.js +3 -3
- package/build/src/rules/in_statement_indentation.js +11 -11
- package/build/src/rules/intf_referencing_clas.js +3 -3
- package/build/src/rules/line_break_style.js +2 -2
- package/build/src/rules/line_length.js +1 -1
- package/build/src/rules/line_only_punc.js +1 -1
- package/build/src/rules/local_variable_names.js +2 -2
- package/build/src/rules/many_parentheses.js +10 -10
- package/build/src/rules/max_one_method_parameter_per_line.js +7 -7
- package/build/src/rules/max_one_statement.js +3 -3
- package/build/src/rules/nesting.js +1 -1
- package/build/src/rules/no_public_attributes.js +1 -1
- package/build/src/rules/no_yoda_conditions.js +4 -4
- package/build/src/rules/obsolete_statement.js +36 -36
- package/build/src/rules/omit_parameter_name.js +3 -3
- package/build/src/rules/omit_receiving.js +13 -13
- package/build/src/rules/parser_702_chaining.js +2 -2
- package/build/src/rules/parser_error.js +2 -2
- package/build/src/rules/parser_missing_space.js +1 -1
- package/build/src/rules/prefer_inline.js +16 -16
- package/build/src/rules/prefer_is_not.js +7 -7
- package/build/src/rules/prefer_raise_exception_new.js +3 -3
- package/build/src/rules/prefer_returning_to_exporting.js +1 -1
- package/build/src/rules/prefer_xsdbool.js +2 -2
- package/build/src/rules/remove_descriptions.js +4 -4
- package/build/src/rules/rfc_error_handling.js +9 -9
- package/build/src/rules/select_add_order_by.js +5 -5
- package/build/src/rules/select_performance.js +2 -2
- package/build/src/rules/sicf_consistency.js +4 -4
- package/build/src/rules/space_before_dot.js +2 -2
- package/build/src/rules/start_at_tab.js +1 -1
- package/build/src/rules/sy_modification.js +2 -2
- package/build/src/rules/tabl_enhancement_category.js +2 -2
- package/build/src/rules/unused_methods.js +9 -9
- package/build/src/rules/unused_variables.js +6 -6
- package/build/src/rules/use_bool_expression.js +8 -8
- package/build/src/rules/use_line_exists.js +6 -6
- package/build/src/rules/use_new.js +2 -2
- package/build/src/rules/when_others_last.js +6 -6
- package/package.json +76 -76
|
@@ -34,14 +34,14 @@ class CheckSubrc extends _abap_rule_1.ABAPRule {
|
|
|
34
34
|
key: "check_subrc",
|
|
35
35
|
title: "Check sy-subrc",
|
|
36
36
|
shortDescription: `Check sy-subrc`,
|
|
37
|
-
extendedInformation: `Pseudo comment "#EC CI_SUBRC can be added to suppress findings
|
|
38
|
-
|
|
39
|
-
If sy-dbcnt is checked after database statements, it is considered okay.
|
|
40
|
-
|
|
41
|
-
"SELECT SINGLE @abap_true FROM " is considered as an existence check
|
|
42
|
-
|
|
43
|
-
If IS ASSIGNED is checked after assigning, it is considered okay.
|
|
44
|
-
|
|
37
|
+
extendedInformation: `Pseudo comment "#EC CI_SUBRC can be added to suppress findings
|
|
38
|
+
|
|
39
|
+
If sy-dbcnt is checked after database statements, it is considered okay.
|
|
40
|
+
|
|
41
|
+
"SELECT SINGLE @abap_true FROM " is considered as an existence check
|
|
42
|
+
|
|
43
|
+
If IS ASSIGNED is checked after assigning, it is considered okay.
|
|
44
|
+
|
|
45
45
|
FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
|
|
46
46
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
47
47
|
pseudoComment: "EC CI_SUBRC",
|
|
@@ -30,7 +30,7 @@ class CommentedCode extends _abap_rule_1.ABAPRule {
|
|
|
30
30
|
key: "commented_code",
|
|
31
31
|
title: "Find commented code",
|
|
32
32
|
shortDescription: `Detects usage of commented out code.`,
|
|
33
|
-
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#delete-code-instead-of-commenting-it
|
|
33
|
+
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#delete-code-instead-of-commenting-it
|
|
34
34
|
https://docs.abapopenchecks.org/checks/14/`,
|
|
35
35
|
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
|
|
36
36
|
};
|
|
@@ -18,10 +18,10 @@ class ConstructorVisibilityPublic {
|
|
|
18
18
|
key: "constructor_visibility_public",
|
|
19
19
|
title: "Check constructor visibility is public",
|
|
20
20
|
shortDescription: `Constructor must be placed in the public section, even if the class is not CREATE PUBLIC.`,
|
|
21
|
-
extendedInformation: `
|
|
22
|
-
This only applies to global classes.
|
|
23
|
-
|
|
24
|
-
https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#if-your-global-class-is-create-private-leave-the-constructor-public
|
|
21
|
+
extendedInformation: `
|
|
22
|
+
This only applies to global classes.
|
|
23
|
+
|
|
24
|
+
https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#if-your-global-class-is-create-private-leave-the-constructor-public
|
|
25
25
|
https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abeninstance_constructor_guidl.htm`,
|
|
26
26
|
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
|
|
27
27
|
};
|
|
@@ -25,8 +25,8 @@ class ContainsTab extends _abap_rule_1.ABAPRule {
|
|
|
25
25
|
key: "contains_tab",
|
|
26
26
|
title: "Code contains tab",
|
|
27
27
|
shortDescription: `Checks for usage of tabs (enable to enforce spaces)`,
|
|
28
|
-
extendedInformation: `
|
|
29
|
-
https://docs.abapopenchecks.org/checks/09/
|
|
28
|
+
extendedInformation: `
|
|
29
|
+
https://docs.abapopenchecks.org/checks/09/
|
|
30
30
|
https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#indent-and-snap-to-tab`,
|
|
31
31
|
tags: [_irule_1.RuleTag.Whitespace, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
|
|
32
32
|
};
|
|
@@ -5,6 +5,7 @@ const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
|
5
5
|
const issue_1 = require("../issue");
|
|
6
6
|
const _irule_1 = require("./_irule");
|
|
7
7
|
const _statement_1 = require("../abap/2_statements/statements/_statement");
|
|
8
|
+
const nodes_1 = require("../abap/nodes");
|
|
8
9
|
const Statements = require("../abap/2_statements/statements");
|
|
9
10
|
const Expressions = require("../abap/2_statements/expressions");
|
|
10
11
|
const edit_helper_1 = require("../edit_helper");
|
|
@@ -18,6 +19,7 @@ const _typed_identifier_1 = require("../abap/types/_typed_identifier");
|
|
|
18
19
|
const basic_1 = require("../abap/types/basic");
|
|
19
20
|
const config_1 = require("../config");
|
|
20
21
|
const tokens_1 = require("../abap/1_lexer/tokens");
|
|
22
|
+
// todo: refactor each sub-rule to new classes
|
|
21
23
|
class DownportConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
22
24
|
}
|
|
23
25
|
exports.DownportConf = DownportConf;
|
|
@@ -30,25 +32,27 @@ class Downport {
|
|
|
30
32
|
key: "downport",
|
|
31
33
|
title: "Downport statement",
|
|
32
34
|
shortDescription: `Experimental downport functionality`,
|
|
33
|
-
extendedInformation: `Much like the 'commented_code' rule this rule loops through unknown statements and tries parsing with
|
|
34
|
-
a higher level language version. If successful, various rules are applied to downport the statement.
|
|
35
|
-
Target downport version is always v702, thus rule is only enabled if target version is v702.
|
|
36
|
-
|
|
37
|
-
Current rules:
|
|
38
|
-
* NEW transformed to CREATE OBJECT, opposite of https://rules.abaplint.org/use_new/
|
|
39
|
-
* DATA() definitions are outlined, opposite of https://rules.abaplint.org/prefer_inline/
|
|
40
|
-
* FIELD-SYMBOL() definitions are outlined
|
|
41
|
-
* CONV is outlined
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* SELECT
|
|
51
|
-
|
|
35
|
+
extendedInformation: `Much like the 'commented_code' rule this rule loops through unknown statements and tries parsing with
|
|
36
|
+
a higher level language version. If successful, various rules are applied to downport the statement.
|
|
37
|
+
Target downport version is always v702, thus rule is only enabled if target version is v702.
|
|
38
|
+
|
|
39
|
+
Current rules:
|
|
40
|
+
* NEW transformed to CREATE OBJECT, opposite of https://rules.abaplint.org/use_new/
|
|
41
|
+
* DATA() definitions are outlined, opposite of https://rules.abaplint.org/prefer_inline/
|
|
42
|
+
* FIELD-SYMBOL() definitions are outlined
|
|
43
|
+
* CONV is outlined
|
|
44
|
+
* COND is outlined
|
|
45
|
+
* REDUCE is outlined
|
|
46
|
+
* EMPTY KEY is changed to DEFAULT KEY, opposite of DEFAULT KEY in https://rules.abaplint.org/avoid_use/
|
|
47
|
+
* CAST changed to ?=
|
|
48
|
+
* LOOP AT method_call( ) is outlined
|
|
49
|
+
* VALUE # with structure fields
|
|
50
|
+
* VALUE # with internal table lines
|
|
51
|
+
* Table Expressions[ index ] are outlined
|
|
52
|
+
* SELECT INTO @DATA definitions are outlined
|
|
53
|
+
* Some occurrences of string template formatting option ALPHA changed to function module call
|
|
54
|
+
* SELECT/INSERT/MODIFY/DELETE/UPDATE "," in field list removed, "@" in source/targets removed
|
|
55
|
+
|
|
52
56
|
Only one transformation is applied to a statement at a time, so multiple steps might be required to do the full downport.`,
|
|
53
57
|
tags: [_irule_1.RuleTag.Experimental, _irule_1.RuleTag.Downport, _irule_1.RuleTag.Quickfix],
|
|
54
58
|
};
|
|
@@ -167,6 +171,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
|
|
|
167
171
|
if (found) {
|
|
168
172
|
return found;
|
|
169
173
|
}
|
|
174
|
+
found = this.outlineReduce(high, lowFile, highSyntax);
|
|
175
|
+
if (found) {
|
|
176
|
+
return found;
|
|
177
|
+
}
|
|
170
178
|
found = this.outlineCast(high, lowFile, highSyntax);
|
|
171
179
|
if (found) {
|
|
172
180
|
return found;
|
|
@@ -175,6 +183,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
|
|
|
175
183
|
if (found) {
|
|
176
184
|
return found;
|
|
177
185
|
}
|
|
186
|
+
found = this.outlineCond(high, lowFile, highSyntax);
|
|
187
|
+
if (found) {
|
|
188
|
+
return found;
|
|
189
|
+
}
|
|
178
190
|
found = this.outlineDataSimple(high, lowFile);
|
|
179
191
|
if (found) {
|
|
180
192
|
return found;
|
|
@@ -294,10 +306,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
|
|
|
294
306
|
const fieldName = f.concatTokens();
|
|
295
307
|
fieldDefinition += indentation + " " + fieldName + " TYPE " + tableName + "-" + fieldName + ",\n";
|
|
296
308
|
}
|
|
297
|
-
fieldDefinition = `DATA: BEGIN OF ${name},
|
|
309
|
+
fieldDefinition = `DATA: BEGIN OF ${name},
|
|
298
310
|
${fieldDefinition}${indentation} END OF ${name}.`;
|
|
299
311
|
}
|
|
300
|
-
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getStart(), `${fieldDefinition}
|
|
312
|
+
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getStart(), `${fieldDefinition}
|
|
301
313
|
${indentation}`);
|
|
302
314
|
const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, inlineData.getFirstToken().getStart(), inlineData.getLastToken().getEnd(), name);
|
|
303
315
|
const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
|
|
@@ -333,9 +345,9 @@ ${indentation}`);
|
|
|
333
345
|
}
|
|
334
346
|
const uniqueName = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
|
|
335
347
|
const name = ((_c = inlineData.findFirstExpression(Expressions.TargetField)) === null || _c === void 0 ? void 0 : _c.concatTokens()) || "error";
|
|
336
|
-
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getStart(), `TYPES: BEGIN OF ${uniqueName},
|
|
337
|
-
${fieldDefinitions}${indentation} END OF ${uniqueName}.
|
|
338
|
-
${indentation}DATA ${name} TYPE STANDARD TABLE OF ${uniqueName} WITH DEFAULT KEY.
|
|
348
|
+
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getStart(), `TYPES: BEGIN OF ${uniqueName},
|
|
349
|
+
${fieldDefinitions}${indentation} END OF ${uniqueName}.
|
|
350
|
+
${indentation}DATA ${name} TYPE STANDARD TABLE OF ${uniqueName} WITH DEFAULT KEY.
|
|
339
351
|
${indentation}`);
|
|
340
352
|
const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, inlineData.getFirstToken().getStart(), inlineData.getLastToken().getEnd(), name);
|
|
341
353
|
const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
|
|
@@ -369,11 +381,11 @@ ${indentation}`);
|
|
|
369
381
|
const uniqueName = this.uniqueName(node.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
|
|
370
382
|
const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
|
|
371
383
|
const firstToken = node.getFirstToken();
|
|
372
|
-
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, firstToken.getStart(), `DATA ${uniqueName} LIKE LINE OF ${pre}.
|
|
373
|
-
${indentation}READ TABLE ${pre} INDEX ${(_a = tableExpression.findFirstExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.concatTokens()} INTO ${uniqueName}.
|
|
374
|
-
${indentation}IF sy-subrc <> 0.
|
|
375
|
-
${indentation} RAISE EXCEPTION TYPE cx_sy_itab_line_not_found.
|
|
376
|
-
${indentation}ENDIF.
|
|
384
|
+
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, firstToken.getStart(), `DATA ${uniqueName} LIKE LINE OF ${pre}.
|
|
385
|
+
${indentation}READ TABLE ${pre} INDEX ${(_a = tableExpression.findFirstExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.concatTokens()} INTO ${uniqueName}.
|
|
386
|
+
${indentation}IF sy-subrc <> 0.
|
|
387
|
+
${indentation} RAISE EXCEPTION TYPE cx_sy_itab_line_not_found.
|
|
388
|
+
${indentation}ENDIF.
|
|
377
389
|
${indentation}`);
|
|
378
390
|
const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, startToken.getStart(), tableExpression.getLastToken().getEnd(), uniqueName);
|
|
379
391
|
const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
|
|
@@ -424,7 +436,7 @@ ${indentation}`);
|
|
|
424
436
|
}
|
|
425
437
|
i = key;
|
|
426
438
|
const concat = i.concatTokens();
|
|
427
|
-
if (concat.includes("WITH EMPTY KEY") === false) {
|
|
439
|
+
if (concat.toUpperCase().includes("WITH EMPTY KEY") === false) {
|
|
428
440
|
continue;
|
|
429
441
|
}
|
|
430
442
|
const token = i.findDirectTokenByText("EMPTY");
|
|
@@ -472,10 +484,10 @@ ${indentation}`);
|
|
|
472
484
|
const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
|
|
473
485
|
const source = (_b = templateSource === null || templateSource === void 0 ? void 0 : templateSource.findDirectExpression(Expressions.Source)) === null || _b === void 0 ? void 0 : _b.concatTokens();
|
|
474
486
|
const topTarget = (_c = node.findDirectExpression(Expressions.Target)) === null || _c === void 0 ? void 0 : _c.concatTokens();
|
|
475
|
-
const code = `CALL FUNCTION '${functionName}'
|
|
476
|
-
${indentation} EXPORTING
|
|
477
|
-
${indentation} input = ${source}
|
|
478
|
-
${indentation} IMPORTING
|
|
487
|
+
const code = `CALL FUNCTION '${functionName}'
|
|
488
|
+
${indentation} EXPORTING
|
|
489
|
+
${indentation} input = ${source}
|
|
490
|
+
${indentation} IMPORTING
|
|
479
491
|
${indentation} output = ${topTarget}.`;
|
|
480
492
|
const fix = edit_helper_1.EditHelper.replaceRange(lowFile, node.getFirstToken().getStart(), node.getLastToken().getEnd(), code);
|
|
481
493
|
return issue_1.Issue.atToken(lowFile, node.getFirstToken(), "Downport ALPHA", this.getMetadata().key, this.conf.severity, fix);
|
|
@@ -535,6 +547,66 @@ ${indentation} output = ${topTarget}.`;
|
|
|
535
547
|
}
|
|
536
548
|
return undefined;
|
|
537
549
|
}
|
|
550
|
+
outlineReduce(node, lowFile, highSyntax) {
|
|
551
|
+
var _a, _b, _c;
|
|
552
|
+
for (const i of node.findAllExpressionsRecursive(Expressions.Source)) {
|
|
553
|
+
const firstToken = i.getFirstToken();
|
|
554
|
+
if (firstToken.getStr().toUpperCase() !== "REDUCE") {
|
|
555
|
+
continue;
|
|
556
|
+
}
|
|
557
|
+
const type = this.findType(i, lowFile, highSyntax);
|
|
558
|
+
if (type === undefined) {
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
const uniqueName = this.uniqueName(firstToken.getStart(), lowFile.getFilename(), highSyntax);
|
|
562
|
+
const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
|
|
563
|
+
let body = "";
|
|
564
|
+
let name = "";
|
|
565
|
+
const reduceBody = i.findDirectExpression(Expressions.ReduceBody);
|
|
566
|
+
if (reduceBody === undefined) {
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
for (const init of reduceBody.findDirectExpressions(Expressions.InlineFieldDefinition)) {
|
|
570
|
+
name = init.getFirstToken().getStr();
|
|
571
|
+
body += indentation + `DATA(${name}) = ${(_a = reduceBody.findFirstExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.concatTokens()}.\n`;
|
|
572
|
+
}
|
|
573
|
+
const loop = reduceBody.findFirstExpression(Expressions.InlineLoopDefinition);
|
|
574
|
+
if (loop === undefined) {
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
577
|
+
const loopSource = (_b = loop.findFirstExpression(Expressions.Source)) === null || _b === void 0 ? void 0 : _b.concatTokens();
|
|
578
|
+
const loopTarget = (_c = loop.findFirstExpression(Expressions.TargetField)) === null || _c === void 0 ? void 0 : _c.concatTokens();
|
|
579
|
+
body += indentation + `LOOP AT ${loopSource} INTO DATA(${loopTarget}).\n`;
|
|
580
|
+
const next = reduceBody.findDirectExpression(Expressions.ReduceNext);
|
|
581
|
+
if (next === undefined) {
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
for (const n of next.getChildren()) {
|
|
585
|
+
if (n.concatTokens().toUpperCase() === "NEXT") {
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
else if (n.concatTokens() === "=") {
|
|
589
|
+
body += " = ";
|
|
590
|
+
}
|
|
591
|
+
else if (n.get() instanceof Expressions.Field) {
|
|
592
|
+
body += indentation + " " + n.concatTokens();
|
|
593
|
+
}
|
|
594
|
+
else if (n.get() instanceof Expressions.Source) {
|
|
595
|
+
body += n.concatTokens() + ".\n";
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
body += indentation + `ENDLOOP.\n`;
|
|
599
|
+
body += indentation + `${uniqueName} = ${name}.\n`;
|
|
600
|
+
const abap = `DATA ${uniqueName} TYPE ${type}.\n` +
|
|
601
|
+
body +
|
|
602
|
+
indentation;
|
|
603
|
+
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), abap);
|
|
604
|
+
const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, firstToken.getStart(), i.getLastToken().getEnd(), uniqueName);
|
|
605
|
+
const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
|
|
606
|
+
return issue_1.Issue.atToken(lowFile, firstToken, "Downport REDUCE", this.getMetadata().key, this.conf.severity, fix);
|
|
607
|
+
}
|
|
608
|
+
return undefined;
|
|
609
|
+
}
|
|
538
610
|
outlineValue(node, lowFile, highSyntax) {
|
|
539
611
|
var _a;
|
|
540
612
|
for (const i of node.findAllExpressionsRecursive(Expressions.Source)) {
|
|
@@ -564,10 +636,13 @@ ${indentation} output = ${topTarget}.`;
|
|
|
564
636
|
}
|
|
565
637
|
body += indentation + structureName + "-" + b.concatTokens() + ".\n";
|
|
566
638
|
}
|
|
567
|
-
if (b.get() instanceof Expressions.Source) {
|
|
639
|
+
else if (b.get() instanceof Expressions.Source) {
|
|
568
640
|
structureName = b.concatTokens();
|
|
569
641
|
}
|
|
570
|
-
if (b.
|
|
642
|
+
else if (b instanceof nodes_1.ExpressionNode && b.get() instanceof Expressions.Let) {
|
|
643
|
+
body += this.outlineLet(b, indentation, highSyntax, lowFile);
|
|
644
|
+
}
|
|
645
|
+
else if (b.concatTokens() === ")") {
|
|
571
646
|
body += indentation + `APPEND ${structureName} TO ${uniqueName}.\n`;
|
|
572
647
|
}
|
|
573
648
|
}
|
|
@@ -581,13 +656,40 @@ ${indentation} output = ${topTarget}.`;
|
|
|
581
656
|
}
|
|
582
657
|
return undefined;
|
|
583
658
|
}
|
|
659
|
+
outlineLet(node, indentation, highSyntax, lowFile) {
|
|
660
|
+
var _a;
|
|
661
|
+
let ret = "";
|
|
662
|
+
for (const f of node.findDirectExpressions(Expressions.InlineFieldDefinition)) {
|
|
663
|
+
const c = f.getFirstChild();
|
|
664
|
+
if (c === undefined) {
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
const name = c.concatTokens().toLowerCase();
|
|
668
|
+
const spag = highSyntax.spaghetti.lookupPosition(c.getFirstToken().getStart(), lowFile.getFilename());
|
|
669
|
+
if (spag === undefined) {
|
|
670
|
+
continue;
|
|
671
|
+
}
|
|
672
|
+
const found = spag.findVariable(name);
|
|
673
|
+
if (found === undefined) {
|
|
674
|
+
continue;
|
|
675
|
+
}
|
|
676
|
+
const type = found.getType().getQualifiedName() ? (_a = found.getType().getQualifiedName()) === null || _a === void 0 ? void 0 : _a.toLowerCase() : found.getType().toABAP();
|
|
677
|
+
ret += indentation + "DATA " + name + ` TYPE ${type}.\n`;
|
|
678
|
+
const source = node.findFirstExpression(Expressions.Source);
|
|
679
|
+
if (source) {
|
|
680
|
+
ret += indentation + name + ` = ${source.concatTokens()}.\n`;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
return ret;
|
|
684
|
+
}
|
|
584
685
|
findType(i, lowFile, highSyntax) {
|
|
686
|
+
var _a;
|
|
585
687
|
const expr = i.findDirectExpression(Expressions.TypeNameOrInfer);
|
|
586
688
|
if (expr === undefined) {
|
|
587
689
|
return undefined;
|
|
588
690
|
}
|
|
589
691
|
const firstToken = expr.getFirstToken();
|
|
590
|
-
const concat = expr.concatTokens();
|
|
692
|
+
const concat = expr.concatTokens().toLowerCase();
|
|
591
693
|
if (concat !== "#") {
|
|
592
694
|
return concat;
|
|
593
695
|
}
|
|
@@ -608,10 +710,10 @@ ${indentation} output = ${topTarget}.`;
|
|
|
608
710
|
if (inferred === undefined) {
|
|
609
711
|
return undefined;
|
|
610
712
|
}
|
|
611
|
-
return inferred.getType().getQualifiedName();
|
|
713
|
+
return (_a = inferred.getType().getQualifiedName()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
612
714
|
}
|
|
613
715
|
outlineFS(node, lowFile, highSyntax) {
|
|
614
|
-
var _a;
|
|
716
|
+
var _a, _b;
|
|
615
717
|
for (const i of node.findAllExpressionsRecursive(Expressions.InlineFS)) {
|
|
616
718
|
const nameToken = (_a = i.findDirectExpression(Expressions.TargetFieldSymbol)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
617
719
|
if (nameToken === undefined) {
|
|
@@ -629,7 +731,7 @@ ${indentation} output = ${topTarget}.`;
|
|
|
629
731
|
else if (found.getType() instanceof basic_1.VoidType) {
|
|
630
732
|
return issue_1.Issue.atToken(lowFile, i.getFirstToken(), "Error outlining voided type", this.getMetadata().key, this.conf.severity);
|
|
631
733
|
}
|
|
632
|
-
const type = found.getType().getQualifiedName() ? found.getType().getQualifiedName() : found.getType().toABAP();
|
|
734
|
+
const type = found.getType().getQualifiedName() ? (_b = found.getType().getQualifiedName()) === null || _b === void 0 ? void 0 : _b.toLowerCase() : found.getType().toABAP();
|
|
633
735
|
const code = `FIELD-SYMBOLS ${name} TYPE ${type}.\n` +
|
|
634
736
|
" ".repeat(node.getFirstToken().getStart().getCol() - 1);
|
|
635
737
|
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), code);
|
|
@@ -640,7 +742,7 @@ ${indentation} output = ${topTarget}.`;
|
|
|
640
742
|
return undefined;
|
|
641
743
|
}
|
|
642
744
|
outlineData(node, lowFile, highSyntax) {
|
|
643
|
-
var _a;
|
|
745
|
+
var _a, _b;
|
|
644
746
|
for (const i of node.findAllExpressionsRecursive(Expressions.InlineData)) {
|
|
645
747
|
const nameToken = (_a = i.findDirectExpression(Expressions.TargetField)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
646
748
|
if (nameToken === undefined) {
|
|
@@ -658,7 +760,7 @@ ${indentation} output = ${topTarget}.`;
|
|
|
658
760
|
else if (found.getType() instanceof basic_1.VoidType) {
|
|
659
761
|
return issue_1.Issue.atToken(lowFile, i.getFirstToken(), "Error outlining voided type", this.getMetadata().key, this.conf.severity);
|
|
660
762
|
}
|
|
661
|
-
const type = found.getType().getQualifiedName() ? found.getType().getQualifiedName() : found.getType().toABAP();
|
|
763
|
+
const type = found.getType().getQualifiedName() ? (_b = found.getType().getQualifiedName()) === null || _b === void 0 ? void 0 : _b.toLowerCase() : found.getType().toABAP();
|
|
662
764
|
const code = `DATA ${name} TYPE ${type}.\n` +
|
|
663
765
|
" ".repeat(node.getFirstToken().getStart().getCol() - 1);
|
|
664
766
|
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), code);
|
|
@@ -668,6 +770,59 @@ ${indentation} output = ${topTarget}.`;
|
|
|
668
770
|
}
|
|
669
771
|
return undefined;
|
|
670
772
|
}
|
|
773
|
+
outlineCond(node, lowFile, highSyntax) {
|
|
774
|
+
for (const i of node.findAllExpressionsRecursive(Expressions.Source)) {
|
|
775
|
+
if (i.getFirstToken().getStr().toUpperCase() !== "COND") {
|
|
776
|
+
continue;
|
|
777
|
+
}
|
|
778
|
+
const body = i.findDirectExpression(Expressions.CondBody);
|
|
779
|
+
if (body === undefined) {
|
|
780
|
+
continue;
|
|
781
|
+
}
|
|
782
|
+
const uniqueName = this.uniqueName(i.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
|
|
783
|
+
const type = this.findType(i, lowFile, highSyntax);
|
|
784
|
+
const indent = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
|
|
785
|
+
const bodyCode = this.buildCondBody(body, uniqueName, indent);
|
|
786
|
+
const abap = `DATA ${uniqueName} TYPE ${type}.\n` + bodyCode;
|
|
787
|
+
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), abap);
|
|
788
|
+
const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, i.getFirstToken().getStart(), i.getLastToken().getEnd(), uniqueName);
|
|
789
|
+
const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
|
|
790
|
+
return issue_1.Issue.atToken(lowFile, i.getFirstToken(), "Downport COND", this.getMetadata().key, this.conf.severity, fix);
|
|
791
|
+
}
|
|
792
|
+
return undefined;
|
|
793
|
+
}
|
|
794
|
+
buildCondBody(body, uniqueName, indent) {
|
|
795
|
+
let code = indent;
|
|
796
|
+
for (const c of body.getChildren()) {
|
|
797
|
+
if (c instanceof nodes_1.TokenNode) {
|
|
798
|
+
switch (c.getFirstToken().getStr().toUpperCase()) {
|
|
799
|
+
case "WHEN":
|
|
800
|
+
code += "IF ";
|
|
801
|
+
break;
|
|
802
|
+
case "THEN":
|
|
803
|
+
code += ".\n";
|
|
804
|
+
break;
|
|
805
|
+
case "ELSE":
|
|
806
|
+
code += indent + "ELSE.\n";
|
|
807
|
+
break;
|
|
808
|
+
default:
|
|
809
|
+
throw "buildCondBody, unexpected token";
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
else if (c.get() instanceof Expressions.Cond) {
|
|
813
|
+
code += c.concatTokens();
|
|
814
|
+
}
|
|
815
|
+
else if (c.get() instanceof Expressions.Source) {
|
|
816
|
+
code += indent + " " + uniqueName + " = " + c.concatTokens() + ".\n";
|
|
817
|
+
}
|
|
818
|
+
else {
|
|
819
|
+
throw "buildCondBody, unexpected expression";
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
code += indent + "ENDIF.\n";
|
|
823
|
+
code += indent;
|
|
824
|
+
return code;
|
|
825
|
+
}
|
|
671
826
|
outlineConv(node, lowFile, highSyntax) {
|
|
672
827
|
var _a;
|
|
673
828
|
for (const i of node.findAllExpressionsRecursive(Expressions.Source)) {
|
|
@@ -680,10 +835,10 @@ ${indentation} output = ${topTarget}.`;
|
|
|
680
835
|
}
|
|
681
836
|
const uniqueName = this.uniqueName(i.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
|
|
682
837
|
const type = this.findType(i, lowFile, highSyntax);
|
|
838
|
+
const indent = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
|
|
683
839
|
const abap = `DATA ${uniqueName} TYPE ${type}.\n` +
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
" ".repeat(node.getFirstToken().getStart().getCol() - 1);
|
|
840
|
+
indent + `${uniqueName} = ${body}.\n` +
|
|
841
|
+
indent;
|
|
687
842
|
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), abap);
|
|
688
843
|
const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, i.getFirstToken().getStart(), i.getLastToken().getEnd(), uniqueName);
|
|
689
844
|
const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
|
|
@@ -24,10 +24,10 @@ class ExitOrCheck extends _abap_rule_1.ABAPRule {
|
|
|
24
24
|
return {
|
|
25
25
|
key: "exit_or_check",
|
|
26
26
|
title: "Find EXIT or CHECK outside loops",
|
|
27
|
-
shortDescription: `Detects usages of EXIT or CHECK statements outside of loops.
|
|
27
|
+
shortDescription: `Detects usages of EXIT or CHECK statements outside of loops.
|
|
28
28
|
Use RETURN to leave procesing blocks instead.`,
|
|
29
|
-
extendedInformation: `https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abenleave_processing_blocks.htm
|
|
30
|
-
https://help.sap.com/doc/abapdocu_750_index_htm/7.50/en-US/abapcheck_processing_blocks.htm
|
|
29
|
+
extendedInformation: `https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abenleave_processing_blocks.htm
|
|
30
|
+
https://help.sap.com/doc/abapdocu_750_index_htm/7.50/en-US/abapcheck_processing_blocks.htm
|
|
31
31
|
https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#check-vs-return`,
|
|
32
32
|
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Quickfix],
|
|
33
33
|
};
|
|
@@ -22,7 +22,7 @@ class Exporting extends _abap_rule_1.ABAPRule {
|
|
|
22
22
|
shortDescription: `Detects EXPORTING statements which can be omitted.`,
|
|
23
23
|
badExample: `call_method( EXPORTING foo = bar ).`,
|
|
24
24
|
goodExample: `call_method( foo = bar ).`,
|
|
25
|
-
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#omit-the-optional-keyword-exporting
|
|
25
|
+
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#omit-the-optional-keyword-exporting
|
|
26
26
|
https://docs.abapopenchecks.org/checks/30/`,
|
|
27
27
|
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
|
|
28
28
|
};
|
|
@@ -26,7 +26,7 @@ class ForbiddenIdentifier extends _abap_rule_1.ABAPRule {
|
|
|
26
26
|
key: "forbidden_identifier",
|
|
27
27
|
title: "Forbidden Identifier",
|
|
28
28
|
shortDescription: `Forbid use of specified identifiers, list of regex.`,
|
|
29
|
-
extendedInformation: `Used in the transpiler to find javascript keywords in ABAP identifiers,
|
|
29
|
+
extendedInformation: `Used in the transpiler to find javascript keywords in ABAP identifiers,
|
|
30
30
|
https://github.com/abaplint/transpiler/blob/bda94b8b56e2b7f2f87be2168f12361aa530220e/packages/transpiler/src/validation.ts#L44`,
|
|
31
31
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
32
32
|
};
|
|
@@ -28,8 +28,8 @@ class ForbiddenVoidType {
|
|
|
28
28
|
key: "forbidden_void_type",
|
|
29
29
|
title: "Forbidden Void Types",
|
|
30
30
|
shortDescription: `Avoid usage of specified void types.`,
|
|
31
|
-
extendedInformation: `Inspiration:
|
|
32
|
-
BOOLEAN, BOOLE_D, CHAR01, CHAR1, CHAR10, CHAR12, CHAR128, CHAR2, CHAR20, CHAR4, CHAR70,
|
|
31
|
+
extendedInformation: `Inspiration:
|
|
32
|
+
BOOLEAN, BOOLE_D, CHAR01, CHAR1, CHAR10, CHAR12, CHAR128, CHAR2, CHAR20, CHAR4, CHAR70,
|
|
33
33
|
DATS, TIMS, DATUM, FLAG, INT4, NUMC3, NUMC4, SAP_BOOL, TEXT25, TEXT80, X255, XFELD`,
|
|
34
34
|
};
|
|
35
35
|
}
|
|
@@ -28,26 +28,26 @@ class FunctionalWriting extends _abap_rule_1.ABAPRule {
|
|
|
28
28
|
key: "functional_writing",
|
|
29
29
|
title: "Use functional writing",
|
|
30
30
|
shortDescription: `Detects usage of call method when functional style calls can be used.`,
|
|
31
|
-
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-functional-to-procedural-calls
|
|
31
|
+
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-functional-to-procedural-calls
|
|
32
32
|
https://docs.abapopenchecks.org/checks/07/`,
|
|
33
33
|
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
|
|
34
|
-
badExample: `CALL METHOD zcl_class=>method( ).
|
|
35
|
-
CALL METHOD cl_abap_typedescr=>describe_by_name
|
|
36
|
-
EXPORTING
|
|
37
|
-
p_name = 'NAME'
|
|
38
|
-
RECEIVING
|
|
39
|
-
p_descr_ref = lr_typedescr
|
|
40
|
-
EXCEPTIONS
|
|
41
|
-
type_not_found = 1
|
|
34
|
+
badExample: `CALL METHOD zcl_class=>method( ).
|
|
35
|
+
CALL METHOD cl_abap_typedescr=>describe_by_name
|
|
36
|
+
EXPORTING
|
|
37
|
+
p_name = 'NAME'
|
|
38
|
+
RECEIVING
|
|
39
|
+
p_descr_ref = lr_typedescr
|
|
40
|
+
EXCEPTIONS
|
|
41
|
+
type_not_found = 1
|
|
42
42
|
OTHERS = 2.`,
|
|
43
|
-
goodExample: `zcl_class=>method( ).
|
|
44
|
-
cl_abap_typedescr=>describe_by_name(
|
|
45
|
-
EXPORTING
|
|
46
|
-
p_name = 'NAME'
|
|
47
|
-
RECEIVING
|
|
48
|
-
p_descr_ref = lr_typedescr
|
|
49
|
-
EXCEPTIONS
|
|
50
|
-
type_not_found = 1
|
|
43
|
+
goodExample: `zcl_class=>method( ).
|
|
44
|
+
cl_abap_typedescr=>describe_by_name(
|
|
45
|
+
EXPORTING
|
|
46
|
+
p_name = 'NAME'
|
|
47
|
+
RECEIVING
|
|
48
|
+
p_descr_ref = lr_typedescr
|
|
49
|
+
EXCEPTIONS
|
|
50
|
+
type_not_found = 1
|
|
51
51
|
OTHERS = 2 ).`,
|
|
52
52
|
};
|
|
53
53
|
}
|
|
@@ -18,10 +18,10 @@ class GlobalClass extends _abap_rule_1.ABAPRule {
|
|
|
18
18
|
return {
|
|
19
19
|
key: "global_class",
|
|
20
20
|
title: "Global class checks",
|
|
21
|
-
shortDescription: `Checks related to global classes.
|
|
22
|
-
* global classes must be in own files
|
|
23
|
-
* file names must match class name
|
|
24
|
-
* global classes must be global definitions
|
|
21
|
+
shortDescription: `Checks related to global classes.
|
|
22
|
+
* global classes must be in own files
|
|
23
|
+
* file names must match class name
|
|
24
|
+
* global classes must be global definitions
|
|
25
25
|
* global interfaces must be global definitions`,
|
|
26
26
|
tags: [_irule_1.RuleTag.Syntax],
|
|
27
27
|
};
|
|
@@ -33,8 +33,8 @@ class IdenticalConditions extends _abap_rule_1.ABAPRule {
|
|
|
33
33
|
return {
|
|
34
34
|
key: "identical_conditions",
|
|
35
35
|
title: "Identical conditions",
|
|
36
|
-
shortDescription: `Find identical conditions in IF + CASE + WHILE etc
|
|
37
|
-
|
|
36
|
+
shortDescription: `Find identical conditions in IF + CASE + WHILE etc
|
|
37
|
+
|
|
38
38
|
Prerequsites: code is pretty printed with identical cAsE`,
|
|
39
39
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
40
40
|
};
|
|
@@ -19,24 +19,24 @@ class IdenticalContents extends _abap_rule_1.ABAPRule {
|
|
|
19
19
|
return {
|
|
20
20
|
key: "identical_contents",
|
|
21
21
|
title: "Identical contents",
|
|
22
|
-
shortDescription: `Find identical contents in blocks inside IFs, both in the beginning and in the end.
|
|
23
|
-
|
|
24
|
-
Prerequsites: code is pretty printed with identical cAsE
|
|
25
|
-
|
|
22
|
+
shortDescription: `Find identical contents in blocks inside IFs, both in the beginning and in the end.
|
|
23
|
+
|
|
24
|
+
Prerequsites: code is pretty printed with identical cAsE
|
|
25
|
+
|
|
26
26
|
Chained statments are ignored`,
|
|
27
27
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
28
|
-
badExample: `IF foo = bar.
|
|
29
|
-
WRITE 'bar'.
|
|
30
|
-
WRITE 'world'.
|
|
31
|
-
ELSE.
|
|
32
|
-
WRITE 'foo'.
|
|
33
|
-
WRITE 'world'.
|
|
28
|
+
badExample: `IF foo = bar.
|
|
29
|
+
WRITE 'bar'.
|
|
30
|
+
WRITE 'world'.
|
|
31
|
+
ELSE.
|
|
32
|
+
WRITE 'foo'.
|
|
33
|
+
WRITE 'world'.
|
|
34
34
|
ENDIF.`,
|
|
35
|
-
goodExample: `IF foo = bar.
|
|
36
|
-
WRITE 'bar'.
|
|
37
|
-
ELSE.
|
|
38
|
-
WRITE 'foo'.
|
|
39
|
-
ENDIF.
|
|
35
|
+
goodExample: `IF foo = bar.
|
|
36
|
+
WRITE 'bar'.
|
|
37
|
+
ELSE.
|
|
38
|
+
WRITE 'foo'.
|
|
39
|
+
ENDIF.
|
|
40
40
|
WRITE 'world'.`,
|
|
41
41
|
};
|
|
42
42
|
}
|
|
@@ -16,10 +16,10 @@ class IdenticalDescriptions {
|
|
|
16
16
|
key: "identical_descriptions",
|
|
17
17
|
title: "Identical descriptions",
|
|
18
18
|
shortDescription: `Searches for objects with the same type and same description`,
|
|
19
|
-
extendedInformation: `Case insensitive
|
|
20
|
-
|
|
21
|
-
Only checks the master language descriptions
|
|
22
|
-
|
|
19
|
+
extendedInformation: `Case insensitive
|
|
20
|
+
|
|
21
|
+
Only checks the master language descriptions
|
|
22
|
+
|
|
23
23
|
Works for: INTF, CLAS, DOMA, DTEL, FUNC in same FUGR`,
|
|
24
24
|
tags: [],
|
|
25
25
|
};
|
|
@@ -19,15 +19,15 @@ class IfInIf extends _abap_rule_1.ABAPRule {
|
|
|
19
19
|
key: "if_in_if",
|
|
20
20
|
title: "IF in IF",
|
|
21
21
|
shortDescription: `Detects nested ifs which can be refactored to a single condition using AND.`,
|
|
22
|
-
extendedInformation: `https://docs.abapopenchecks.org/checks/01/
|
|
22
|
+
extendedInformation: `https://docs.abapopenchecks.org/checks/01/
|
|
23
23
|
https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#keep-the-nesting-depth-low`,
|
|
24
|
-
badExample: `IF condition1.
|
|
25
|
-
IF condition2.
|
|
26
|
-
...
|
|
27
|
-
ENDIF.
|
|
24
|
+
badExample: `IF condition1.
|
|
25
|
+
IF condition2.
|
|
26
|
+
...
|
|
27
|
+
ENDIF.
|
|
28
28
|
ENDIF.`,
|
|
29
|
-
goodExample: `IF ( condition1 ) AND ( condition2 ).
|
|
30
|
-
...
|
|
29
|
+
goodExample: `IF ( condition1 ) AND ( condition2 ).
|
|
30
|
+
...
|
|
31
31
|
ENDIF.`,
|
|
32
32
|
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
|
|
33
33
|
};
|