@abaplint/core 2.79.22 → 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/expressions/reduce_body.js +4 -0
- package/build/src/abap/5_syntax/expressions/reduce_next.js +17 -0
- package/build/src/lsp/help.js +7 -7
- 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 +131 -36
- 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
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# @abaplint/core
|
|
2
|
-
|
|
3
|
-
[abaplint](https://abaplint.org/) core library
|
|
4
|
-
|
|
5
|
-
Exposes functionallity like the parser and rules, which can be used in other projects.
|
|
6
|
-
|
|
1
|
+
# @abaplint/core
|
|
2
|
+
|
|
3
|
+
[abaplint](https://abaplint.org/) core library
|
|
4
|
+
|
|
5
|
+
Exposes functionallity like the parser and rules, which can be used in other projects.
|
|
6
|
+
|
|
7
7
|
For more information see https://github.com/abaplint/abaplint
|
package/build/abaplint.d.ts
CHANGED
|
@@ -1764,6 +1764,7 @@ declare namespace Expressions {
|
|
|
1764
1764
|
ReceiveParameters,
|
|
1765
1765
|
Redefinition,
|
|
1766
1766
|
ReduceBody,
|
|
1767
|
+
ReduceNext,
|
|
1767
1768
|
ReportName,
|
|
1768
1769
|
SelectLoop_2 as SelectLoop,
|
|
1769
1770
|
Select_3 as Select,
|
|
@@ -4086,6 +4087,10 @@ declare class ReduceBody extends Expression {
|
|
|
4086
4087
|
getRunnable(): IStatementRunnable;
|
|
4087
4088
|
}
|
|
4088
4089
|
|
|
4090
|
+
declare class ReduceNext extends Expression {
|
|
4091
|
+
getRunnable(): IStatementRunnable;
|
|
4092
|
+
}
|
|
4093
|
+
|
|
4089
4094
|
export declare enum ReferenceType {
|
|
4090
4095
|
/** for classes and interface references */
|
|
4091
4096
|
ObjectOrientedReference = "ObjectOrientedReference",
|
|
@@ -137,6 +137,7 @@ __exportStar(require("./read_table_target"), exports);
|
|
|
137
137
|
__exportStar(require("./receive_parameters"), exports);
|
|
138
138
|
__exportStar(require("./redefinition"), exports);
|
|
139
139
|
__exportStar(require("./reduce_body"), exports);
|
|
140
|
+
__exportStar(require("./reduce_next"), exports);
|
|
140
141
|
__exportStar(require("./report_name"), exports);
|
|
141
142
|
__exportStar(require("./select_loop"), exports);
|
|
142
143
|
__exportStar(require("./select"), exports);
|
|
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ReduceBody = void 0;
|
|
4
4
|
const combi_1 = require("../combi");
|
|
5
5
|
const _1 = require(".");
|
|
6
|
+
const reduce_next_1 = require("./reduce_next");
|
|
6
7
|
class ReduceBody extends combi_1.Expression {
|
|
7
8
|
getRunnable() {
|
|
8
|
-
const fields = (0, combi_1.seq)(_1.Field, "=", _1.Source);
|
|
9
9
|
const init = (0, combi_1.seq)("INIT", (0, combi_1.plus)(_1.InlineFieldDefinition));
|
|
10
|
-
return (0, combi_1.seq)((0, combi_1.opt)(_1.Let), init, _1.For,
|
|
10
|
+
return (0, combi_1.seq)((0, combi_1.opt)(_1.Let), init, _1.For, reduce_next_1.ReduceNext);
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
exports.ReduceBody = ReduceBody;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReduceNext = void 0;
|
|
4
|
+
const combi_1 = require("../combi");
|
|
5
|
+
const _1 = require(".");
|
|
6
|
+
class ReduceNext extends combi_1.Expression {
|
|
7
|
+
getRunnable() {
|
|
8
|
+
const fields = (0, combi_1.seq)(_1.Field, "=", _1.Source);
|
|
9
|
+
return (0, combi_1.seq)("NEXT", (0, combi_1.plus)(fields));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.ReduceNext = ReduceNext;
|
|
13
|
+
//# sourceMappingURL=reduce_next.js.map
|
|
@@ -7,6 +7,7 @@ const source_1 = require("./source");
|
|
|
7
7
|
const inline_field_definition_1 = require("./inline_field_definition");
|
|
8
8
|
const unknown_type_1 = require("../../types/basic/unknown_type");
|
|
9
9
|
const _scope_type_1 = require("../_scope_type");
|
|
10
|
+
const reduce_next_1 = require("./reduce_next");
|
|
10
11
|
class ReduceBody {
|
|
11
12
|
runSyntax(node, scope, filename) {
|
|
12
13
|
if (node === undefined) {
|
|
@@ -22,6 +23,9 @@ class ReduceBody {
|
|
|
22
23
|
for (const s of node.findDirectExpressions(Expressions.Source)) {
|
|
23
24
|
new source_1.Source().runSyntax(s, scope, filename);
|
|
24
25
|
}
|
|
26
|
+
for (const s of node.findDirectExpressions(Expressions.ReduceNext)) {
|
|
27
|
+
new reduce_next_1.ReduceNext().runSyntax(s, scope, filename);
|
|
28
|
+
}
|
|
25
29
|
if (scope.getType() === _scope_type_1.ScopeType.For) {
|
|
26
30
|
scope.pop(node.getLastToken().getEnd());
|
|
27
31
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReduceNext = void 0;
|
|
4
|
+
const Expressions = require("../../2_statements/expressions");
|
|
5
|
+
const source_1 = require("./source");
|
|
6
|
+
class ReduceNext {
|
|
7
|
+
runSyntax(node, scope, filename) {
|
|
8
|
+
if (node === undefined) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
for (const s of node.findDirectExpressions(Expressions.Source)) {
|
|
12
|
+
new source_1.Source().runSyntax(s, scope, filename);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.ReduceNext = ReduceNext;
|
|
17
|
+
//# sourceMappingURL=reduce_next.js.map
|
package/build/src/lsp/help.js
CHANGED
|
@@ -9,13 +9,13 @@ const dump_scope_1 = require("./dump_scope");
|
|
|
9
9
|
class Help {
|
|
10
10
|
static find(reg, textDocument, position) {
|
|
11
11
|
let content = "";
|
|
12
|
-
content = `
|
|
13
|
-
<a href="#_tokens" rel="no-refresh">Tokens</a> |
|
|
14
|
-
<a href="#_statements" rel="no-refresh">Statements</a> |
|
|
15
|
-
<a href="#_structure" rel="no-refresh">Structure</a> |
|
|
16
|
-
<a href="#_files" rel="no-refresh">Files</a> |
|
|
17
|
-
<a href="#_info" rel="no-refresh">Info Dump</a>
|
|
18
|
-
<hr>
|
|
12
|
+
content = `
|
|
13
|
+
<a href="#_tokens" rel="no-refresh">Tokens</a> |
|
|
14
|
+
<a href="#_statements" rel="no-refresh">Statements</a> |
|
|
15
|
+
<a href="#_structure" rel="no-refresh">Structure</a> |
|
|
16
|
+
<a href="#_files" rel="no-refresh">Files</a> |
|
|
17
|
+
<a href="#_info" rel="no-refresh">Info Dump</a>
|
|
18
|
+
<hr>
|
|
19
19
|
` +
|
|
20
20
|
"<tt>" + textDocument.uri + " (" +
|
|
21
21
|
(position.line + 1) + ", " +
|
package/build/src/registry.js
CHANGED
|
@@ -23,7 +23,7 @@ class Abapdoc extends _abap_rule_1.ABAPRule {
|
|
|
23
23
|
return {
|
|
24
24
|
key: "abapdoc",
|
|
25
25
|
title: "Check abapdoc",
|
|
26
|
-
shortDescription: `Various checks regarding abapdoc.
|
|
26
|
+
shortDescription: `Various checks regarding abapdoc.
|
|
27
27
|
Base rule checks for existence of abapdoc for public class methods and all interface methods.`,
|
|
28
28
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
29
29
|
};
|
|
@@ -20,14 +20,14 @@ class AmbiguousStatement extends _abap_rule_1.ABAPRule {
|
|
|
20
20
|
return {
|
|
21
21
|
key: "ambiguous_statement",
|
|
22
22
|
title: "Check for ambigious statements",
|
|
23
|
-
shortDescription: `Checks for ambiguity between deleting or modifying from internal and database table
|
|
24
|
-
Add "TABLE" keyword or "@" for escaping SQL variables
|
|
25
|
-
|
|
23
|
+
shortDescription: `Checks for ambiguity between deleting or modifying from internal and database table
|
|
24
|
+
Add "TABLE" keyword or "@" for escaping SQL variables
|
|
25
|
+
|
|
26
26
|
Only works if the target version is 740sp05 or above`,
|
|
27
27
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
28
|
-
badExample: `DELETE foo FROM bar.
|
|
28
|
+
badExample: `DELETE foo FROM bar.
|
|
29
29
|
MODIFY foo FROM bar.`,
|
|
30
|
-
goodExample: `DELETE foo FROM @bar.
|
|
30
|
+
goodExample: `DELETE foo FROM @bar.
|
|
31
31
|
MODIFY TABLE foo FROM bar.`,
|
|
32
32
|
};
|
|
33
33
|
}
|
|
@@ -35,12 +35,12 @@ class AvoidUse extends _abap_rule_1.ABAPRule {
|
|
|
35
35
|
key: "avoid_use",
|
|
36
36
|
title: "Avoid use of certain statements",
|
|
37
37
|
shortDescription: `Detects usage of certain statements.`,
|
|
38
|
-
extendedInformation: `DEFAULT KEY: https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#avoid-default-key
|
|
39
|
-
|
|
40
|
-
Macros: https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abenmacros_guidl.htm
|
|
41
|
-
|
|
42
|
-
STATICS: use CLASS-DATA instead
|
|
43
|
-
|
|
38
|
+
extendedInformation: `DEFAULT KEY: https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#avoid-default-key
|
|
39
|
+
|
|
40
|
+
Macros: https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abenmacros_guidl.htm
|
|
41
|
+
|
|
42
|
+
STATICS: use CLASS-DATA instead
|
|
43
|
+
|
|
44
44
|
DESCRIBE TABLE LINES: use lines() instead (quickfix exists)`,
|
|
45
45
|
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
|
|
46
46
|
};
|
|
@@ -23,11 +23,11 @@ class BeginEndNames extends _abap_rule_1.ABAPRule {
|
|
|
23
23
|
title: "Check BEGIN END names",
|
|
24
24
|
shortDescription: `Check BEGIN OF and END OF names match, plus there must be statements between BEGIN and END`,
|
|
25
25
|
tags: [_irule_1.RuleTag.Syntax, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
|
|
26
|
-
badExample: `DATA: BEGIN OF stru,
|
|
27
|
-
field TYPE i,
|
|
26
|
+
badExample: `DATA: BEGIN OF stru,
|
|
27
|
+
field TYPE i,
|
|
28
28
|
END OF structure_not_the_same.`,
|
|
29
|
-
goodExample: `DATA: BEGIN OF stru,
|
|
30
|
-
field TYPE i,
|
|
29
|
+
goodExample: `DATA: BEGIN OF stru,
|
|
30
|
+
field TYPE i,
|
|
31
31
|
END OF stru.`,
|
|
32
32
|
};
|
|
33
33
|
}
|
|
@@ -21,19 +21,19 @@ class BeginSingleInclude extends _abap_rule_1.ABAPRule {
|
|
|
21
21
|
title: "BEGIN contains single INCLUDE",
|
|
22
22
|
shortDescription: `Finds TYPE BEGIN with just one INCLUDE TYPE, and DATA with single INCLUDE STRUCTURE`,
|
|
23
23
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
24
|
-
badExample: `TYPES: BEGIN OF dummy1.
|
|
25
|
-
INCLUDE TYPE dselc.
|
|
26
|
-
TYPES: END OF dummy1.
|
|
27
|
-
|
|
28
|
-
DATA BEGIN OF foo.
|
|
29
|
-
INCLUDE STRUCTURE syst.
|
|
30
|
-
DATA END OF foo.
|
|
31
|
-
|
|
32
|
-
STATICS BEGIN OF bar.
|
|
33
|
-
INCLUDE STRUCTURE syst.
|
|
24
|
+
badExample: `TYPES: BEGIN OF dummy1.
|
|
25
|
+
INCLUDE TYPE dselc.
|
|
26
|
+
TYPES: END OF dummy1.
|
|
27
|
+
|
|
28
|
+
DATA BEGIN OF foo.
|
|
29
|
+
INCLUDE STRUCTURE syst.
|
|
30
|
+
DATA END OF foo.
|
|
31
|
+
|
|
32
|
+
STATICS BEGIN OF bar.
|
|
33
|
+
INCLUDE STRUCTURE syst.
|
|
34
34
|
STATICS END OF bar.`,
|
|
35
|
-
goodExample: `DATA BEGIN OF foo.
|
|
36
|
-
INCLUDE STRUCTURE dselc.
|
|
35
|
+
goodExample: `DATA BEGIN OF foo.
|
|
36
|
+
INCLUDE STRUCTURE dselc.
|
|
37
37
|
DATA END OF foo.`,
|
|
38
38
|
};
|
|
39
39
|
}
|
|
@@ -45,10 +45,10 @@ class ChainMainlyDeclarations extends _abap_rule_1.ABAPRule {
|
|
|
45
45
|
key: "chain_mainly_declarations",
|
|
46
46
|
title: "Chain mainly declarations",
|
|
47
47
|
shortDescription: `Chain mainly declarations, allows chaining for the configured statements, reports errors for other statements.`,
|
|
48
|
-
extendedInformation: `
|
|
49
|
-
https://docs.abapopenchecks.org/checks/23/
|
|
50
|
-
|
|
51
|
-
https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abenchained_statements_guidl.htm
|
|
48
|
+
extendedInformation: `
|
|
49
|
+
https://docs.abapopenchecks.org/checks/23/
|
|
50
|
+
|
|
51
|
+
https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abenchained_statements_guidl.htm
|
|
52
52
|
`,
|
|
53
53
|
tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Quickfix],
|
|
54
54
|
badExample: `CALL METHOD: bar.`,
|
|
@@ -23,8 +23,8 @@ class CheckAbstract extends _abap_rule_1.ABAPRule {
|
|
|
23
23
|
return {
|
|
24
24
|
key: "check_abstract",
|
|
25
25
|
title: "Check abstract methods and classes",
|
|
26
|
-
shortDescription: `Checks abstract methods and classes:
|
|
27
|
-
- class defined as abstract and final,
|
|
26
|
+
shortDescription: `Checks abstract methods and classes:
|
|
27
|
+
- class defined as abstract and final,
|
|
28
28
|
- non-abstract class contains abstract methods`,
|
|
29
29
|
extendedInformation: `If a class defines only constants, use an interface instead`,
|
|
30
30
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
@@ -27,9 +27,9 @@ class CheckComments extends _abap_rule_1.ABAPRule {
|
|
|
27
27
|
return {
|
|
28
28
|
key: "check_comments",
|
|
29
29
|
title: "Check Comments",
|
|
30
|
-
shortDescription: `
|
|
31
|
-
Various checks for comment usage.
|
|
32
|
-
|
|
30
|
+
shortDescription: `
|
|
31
|
+
Various checks for comment usage.
|
|
32
|
+
|
|
33
33
|
* End of line comments. Comments starting with "#EC" or "##" are ignored`,
|
|
34
34
|
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#put-comments-before-the-statement-they-relate-to`,
|
|
35
35
|
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
|
|
@@ -17,9 +17,9 @@ class CheckInclude {
|
|
|
17
17
|
key: "check_include",
|
|
18
18
|
title: "Check INCLUDEs",
|
|
19
19
|
shortDescription: `Checks INCLUDE statements`,
|
|
20
|
-
extendedInformation: `
|
|
21
|
-
* Reports unused includes
|
|
22
|
-
* Errors if the includes are not found
|
|
20
|
+
extendedInformation: `
|
|
21
|
+
* Reports unused includes
|
|
22
|
+
* Errors if the includes are not found
|
|
23
23
|
* Error if including a main program`,
|
|
24
24
|
tags: [_irule_1.RuleTag.Syntax],
|
|
25
25
|
};
|
|
@@ -21,15 +21,15 @@ class CheckNoHandlerPragma extends _abap_rule_1.ABAPRule {
|
|
|
21
21
|
title: "Check if NO_HANDLER can be removed",
|
|
22
22
|
shortDescription: `Checks NO_HANDLER pragmas that can be removed`,
|
|
23
23
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
24
|
-
badExample: `TRY.
|
|
25
|
-
...
|
|
26
|
-
CATCH zcx_abapgit_exception ##NO_HANDLER.
|
|
27
|
-
RETURN. " it has a handler
|
|
24
|
+
badExample: `TRY.
|
|
25
|
+
...
|
|
26
|
+
CATCH zcx_abapgit_exception ##NO_HANDLER.
|
|
27
|
+
RETURN. " it has a handler
|
|
28
28
|
ENDTRY.`,
|
|
29
|
-
goodExample: `TRY.
|
|
30
|
-
...
|
|
31
|
-
CATCH zcx_abapgit_exception.
|
|
32
|
-
RETURN.
|
|
29
|
+
goodExample: `TRY.
|
|
30
|
+
...
|
|
31
|
+
CATCH zcx_abapgit_exception.
|
|
32
|
+
RETURN.
|
|
33
33
|
ENDTRY.`,
|
|
34
34
|
};
|
|
35
35
|
}
|
|
@@ -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
|
};
|
|
@@ -19,6 +19,7 @@ const _typed_identifier_1 = require("../abap/types/_typed_identifier");
|
|
|
19
19
|
const basic_1 = require("../abap/types/basic");
|
|
20
20
|
const config_1 = require("../config");
|
|
21
21
|
const tokens_1 = require("../abap/1_lexer/tokens");
|
|
22
|
+
// todo: refactor each sub-rule to new classes
|
|
22
23
|
class DownportConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
23
24
|
}
|
|
24
25
|
exports.DownportConf = DownportConf;
|
|
@@ -31,26 +32,27 @@ class Downport {
|
|
|
31
32
|
key: "downport",
|
|
32
33
|
title: "Downport statement",
|
|
33
34
|
shortDescription: `Experimental downport functionality`,
|
|
34
|
-
extendedInformation: `Much like the 'commented_code' rule this rule loops through unknown statements and tries parsing with
|
|
35
|
-
a higher level language version. If successful, various rules are applied to downport the statement.
|
|
36
|
-
Target downport version is always v702, thus rule is only enabled if target version is v702.
|
|
37
|
-
|
|
38
|
-
Current rules:
|
|
39
|
-
* NEW transformed to CREATE OBJECT, opposite of https://rules.abaplint.org/use_new/
|
|
40
|
-
* DATA() definitions are outlined, opposite of https://rules.abaplint.org/prefer_inline/
|
|
41
|
-
* FIELD-SYMBOL() definitions are outlined
|
|
42
|
-
* CONV is outlined
|
|
43
|
-
* COND is outlined
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* VALUE # with
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
|
|
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
|
+
|
|
54
56
|
Only one transformation is applied to a statement at a time, so multiple steps might be required to do the full downport.`,
|
|
55
57
|
tags: [_irule_1.RuleTag.Experimental, _irule_1.RuleTag.Downport, _irule_1.RuleTag.Quickfix],
|
|
56
58
|
};
|
|
@@ -169,6 +171,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
|
|
|
169
171
|
if (found) {
|
|
170
172
|
return found;
|
|
171
173
|
}
|
|
174
|
+
found = this.outlineReduce(high, lowFile, highSyntax);
|
|
175
|
+
if (found) {
|
|
176
|
+
return found;
|
|
177
|
+
}
|
|
172
178
|
found = this.outlineCast(high, lowFile, highSyntax);
|
|
173
179
|
if (found) {
|
|
174
180
|
return found;
|
|
@@ -300,10 +306,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
|
|
|
300
306
|
const fieldName = f.concatTokens();
|
|
301
307
|
fieldDefinition += indentation + " " + fieldName + " TYPE " + tableName + "-" + fieldName + ",\n";
|
|
302
308
|
}
|
|
303
|
-
fieldDefinition = `DATA: BEGIN OF ${name},
|
|
309
|
+
fieldDefinition = `DATA: BEGIN OF ${name},
|
|
304
310
|
${fieldDefinition}${indentation} END OF ${name}.`;
|
|
305
311
|
}
|
|
306
|
-
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getStart(), `${fieldDefinition}
|
|
312
|
+
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getStart(), `${fieldDefinition}
|
|
307
313
|
${indentation}`);
|
|
308
314
|
const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, inlineData.getFirstToken().getStart(), inlineData.getLastToken().getEnd(), name);
|
|
309
315
|
const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
|
|
@@ -339,9 +345,9 @@ ${indentation}`);
|
|
|
339
345
|
}
|
|
340
346
|
const uniqueName = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
|
|
341
347
|
const name = ((_c = inlineData.findFirstExpression(Expressions.TargetField)) === null || _c === void 0 ? void 0 : _c.concatTokens()) || "error";
|
|
342
|
-
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getStart(), `TYPES: BEGIN OF ${uniqueName},
|
|
343
|
-
${fieldDefinitions}${indentation} END OF ${uniqueName}.
|
|
344
|
-
${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.
|
|
345
351
|
${indentation}`);
|
|
346
352
|
const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, inlineData.getFirstToken().getStart(), inlineData.getLastToken().getEnd(), name);
|
|
347
353
|
const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
|
|
@@ -375,11 +381,11 @@ ${indentation}`);
|
|
|
375
381
|
const uniqueName = this.uniqueName(node.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
|
|
376
382
|
const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
|
|
377
383
|
const firstToken = node.getFirstToken();
|
|
378
|
-
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, firstToken.getStart(), `DATA ${uniqueName} LIKE LINE OF ${pre}.
|
|
379
|
-
${indentation}READ TABLE ${pre} INDEX ${(_a = tableExpression.findFirstExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.concatTokens()} INTO ${uniqueName}.
|
|
380
|
-
${indentation}IF sy-subrc <> 0.
|
|
381
|
-
${indentation} RAISE EXCEPTION TYPE cx_sy_itab_line_not_found.
|
|
382
|
-
${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.
|
|
383
389
|
${indentation}`);
|
|
384
390
|
const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, startToken.getStart(), tableExpression.getLastToken().getEnd(), uniqueName);
|
|
385
391
|
const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
|
|
@@ -478,10 +484,10 @@ ${indentation}`);
|
|
|
478
484
|
const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
|
|
479
485
|
const source = (_b = templateSource === null || templateSource === void 0 ? void 0 : templateSource.findDirectExpression(Expressions.Source)) === null || _b === void 0 ? void 0 : _b.concatTokens();
|
|
480
486
|
const topTarget = (_c = node.findDirectExpression(Expressions.Target)) === null || _c === void 0 ? void 0 : _c.concatTokens();
|
|
481
|
-
const code = `CALL FUNCTION '${functionName}'
|
|
482
|
-
${indentation} EXPORTING
|
|
483
|
-
${indentation} input = ${source}
|
|
484
|
-
${indentation} IMPORTING
|
|
487
|
+
const code = `CALL FUNCTION '${functionName}'
|
|
488
|
+
${indentation} EXPORTING
|
|
489
|
+
${indentation} input = ${source}
|
|
490
|
+
${indentation} IMPORTING
|
|
485
491
|
${indentation} output = ${topTarget}.`;
|
|
486
492
|
const fix = edit_helper_1.EditHelper.replaceRange(lowFile, node.getFirstToken().getStart(), node.getLastToken().getEnd(), code);
|
|
487
493
|
return issue_1.Issue.atToken(lowFile, node.getFirstToken(), "Downport ALPHA", this.getMetadata().key, this.conf.severity, fix);
|
|
@@ -541,6 +547,66 @@ ${indentation} output = ${topTarget}.`;
|
|
|
541
547
|
}
|
|
542
548
|
return undefined;
|
|
543
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
|
+
}
|
|
544
610
|
outlineValue(node, lowFile, highSyntax) {
|
|
545
611
|
var _a;
|
|
546
612
|
for (const i of node.findAllExpressionsRecursive(Expressions.Source)) {
|
|
@@ -570,10 +636,13 @@ ${indentation} output = ${topTarget}.`;
|
|
|
570
636
|
}
|
|
571
637
|
body += indentation + structureName + "-" + b.concatTokens() + ".\n";
|
|
572
638
|
}
|
|
573
|
-
if (b.get() instanceof Expressions.Source) {
|
|
639
|
+
else if (b.get() instanceof Expressions.Source) {
|
|
574
640
|
structureName = b.concatTokens();
|
|
575
641
|
}
|
|
576
|
-
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() === ")") {
|
|
577
646
|
body += indentation + `APPEND ${structureName} TO ${uniqueName}.\n`;
|
|
578
647
|
}
|
|
579
648
|
}
|
|
@@ -587,6 +656,32 @@ ${indentation} output = ${topTarget}.`;
|
|
|
587
656
|
}
|
|
588
657
|
return undefined;
|
|
589
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
|
+
}
|
|
590
685
|
findType(i, lowFile, highSyntax) {
|
|
591
686
|
var _a;
|
|
592
687
|
const expr = i.findDirectExpression(Expressions.TypeNameOrInfer);
|
|
@@ -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
|
};
|