Skip to content

add new check for 'Prefer INSERT INTO TABLE to APPEND TO' #623

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/check_documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
- [Prefer CASE to ELSEIF](checks/prefer-case-to-elseif.md)
- [Prefer RETURNING to EXPORTING](checks/prefer-returning-to-exporting.md)
- [Prefer IS NOT to NOT IS](checks/prefer-is-not-to-not-is.md)
- [Prefer INSERT INTO TABLE to APPEND TO](checks/prefer-insert-into-to-append.md)
- [Prefer LINE_EXISTS or LINE_INDEX to READ TABLE or LOOP AT](checks/prefer-line-exists.md)
- [Prefer NEW to CREATE OBJECT](checks/prefer-new-to-create-object.md)
- [Prefer Pragmas to Pseudo Comments](checks/prefer-pragmas-to-pseudo-comments.md)
Expand Down
40 changes: 40 additions & 0 deletions docs/checks/prefer-insert-into-to-append.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[code pal for ABAP](../../README.md) > [Documentation](../check_documentation.md) > [Prefer INSERT INTO TABLE to APPEND TO](prefer-insert-into-to-append.md)

## Prefer INSERT INTO TABLE to APPEND TO

### What is the intent of the check?

This check searches for `APPEND` statements and reports a finding. `INSERT INTO TABLE` works with all table and key types, thus making it easier for you to refactor the table's type and key definitions if your performance requirements change.

### How to solve the issue?

Use `INSERT INTO` instead of `APPEND TO`.

### What to do in case of exception?

In exceptional cases, you can suppress this finding by using the pseudo comment `"#EC PREF_INSERT_INT`:

```abap
DATA prefer_insert_into_table TYPE TABLE OF string.
APPEND `example` TO prefer_insert_into_table. "#EC PREF_INSERT_INT
```

### Example

Before the check:

```abap
DATA prefer_insert_into_table TYPE TABLE OF string.
APPEND `example` TO prefer_insert_into_table.
```

After the check:

```abap
DATA prefer_insert_into_table TYPE TABLE OF string.
INSERT `example` INTO TABLE prefer_insert_into_table.
```

### Further Readings & Knowledge

* [Clean ABAP - Prefer INSERT INTO TABLE to APPEND TO](https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-insert-into-table-to-append-to)
50 changes: 50 additions & 0 deletions src/y_check_prefer_insert_into.clas.abap
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
CLASS y_check_prefer_insert_into DEFINITION
PUBLIC
INHERITING FROM y_check_base
FINAL
CREATE PUBLIC .

PUBLIC SECTION.
METHODS constructor.
PROTECTED SECTION.
METHODS: inspect_tokens REDEFINITION.
PRIVATE SECTION.
ENDCLASS.



CLASS y_check_prefer_insert_into IMPLEMENTATION.

METHOD constructor.
super->constructor( ).

settings-pseudo_comment = '"#EC PREF_INSERT_INT' ##NO_TEXT.
settings-disable_threshold_selection = abap_true.
settings-threshold = 0.
settings-documentation = |{ c_docs_path-checks }prefer-insert-into-to-append.md|.

set_check_message( 'Prefer INSERT INTO TABLE to APPEND TO.' ).

ENDMETHOD.

METHOD inspect_tokens.

IF get_token_abs( statement-from ) <> 'APPEND'.
RETURN.
ENDIF.

IF next2( p_word1 = 'SORTED'
p_word2 = 'BY' ) IS NOT INITIAL.
RETURN.
ENDIF.

DATA(check_configuration) = detect_check_configuration( statement ).

raise_error( statement_level = statement-level
statement_index = index
statement_from = statement-from
check_configuration = check_configuration ).

ENDMETHOD.

ENDCLASS.
182 changes: 182 additions & 0 deletions src/y_check_prefer_insert_into.clas.testclasses.abap
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
CLASS ltc_append_to DEFINITION INHERITING FROM y_unit_test_base FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PROTECTED SECTION.
METHODS: get_cut REDEFINITION,
get_code_with_issue REDEFINITION,
get_code_without_issue REDEFINITION,
get_code_with_exemption REDEFINITION.

ENDCLASS.


CLASS ltc_append_to IMPLEMENTATION.

METHOD get_code_without_issue.

result = VALUE #(
( ' REPORT y_example.' )

( ' CLASS y_example DEFINITION.' )
( ' PUBLIC SECTION.' )
( ' METHODS example.' )
( ' ENDCLASS.' )

( ' CLASS y_example IMPLEMENTATION.' )
( ' METHOD example.' )
( ' DATA prefer_insert_into_table TYPE TABLE OF string.' )
( ' INSERT `example` INTO TABLE prefer_insert_into_table.' )
( ' ENDMETHOD.' )
( ' ENDCLASS.' )
).

ENDMETHOD.

METHOD get_code_with_exemption.

result = VALUE #(
( ' REPORT y_example.' )

( ' CLASS y_example DEFINITION.' )
( ' PUBLIC SECTION.' )
( ' METHODS example.' )
( ' ENDCLASS.' )

( ' CLASS y_example IMPLEMENTATION.' )
( ' METHOD example.' )
( ' DATA prefer_insert_into_table TYPE TABLE OF string.' )
( ' APPEND `example` TO prefer_insert_into_table. "#EC PREF_INSERT_INT' )
( ' ENDMETHOD.' )
( ' ENDCLASS.' )
).

ENDMETHOD.

METHOD get_code_with_issue.

result = VALUE #(
( ' REPORT y_example.' )

( ' CLASS y_example DEFINITION.' )
( ' PUBLIC SECTION.' )
( ' METHODS example.' )
( ' ENDCLASS.' )

( ' CLASS y_example IMPLEMENTATION.' )
( ' METHOD example.' )
( ' DATA prefer_insert_into_table TYPE TABLE OF string.' )
( ' APPEND `example` TO prefer_insert_into_table.' )
( ' ENDMETHOD.' )
( ' ENDCLASS.' )
).

ENDMETHOD.

METHOD get_cut.
result ?= NEW y_check_prefer_insert_into( ).
ENDMETHOD.

ENDCLASS.

CLASS ltc_append_initial_line DEFINITION INHERITING FROM ltc_append_to FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PROTECTED SECTION.
METHODS get_code_with_issue REDEFINITION.
ENDCLASS.

CLASS ltc_append_initial_line IMPLEMENTATION.

METHOD get_code_with_issue.
result = VALUE #(
( ' REPORT y_example.' )

( ' CLASS y_example DEFINITION.' )
( ' PUBLIC SECTION.' )
( ' METHODS example.' )
( ' ENDCLASS.' )

( ' CLASS y_example IMPLEMENTATION.' )
( ' METHOD example.' )
( ' DATA prefer_insert_into_table TYPE TABLE OF string.' )
( ' FIELD-SYMBOLS <example> TYPE string.' )
( ' APPEND INITIAL LINE TO prefer_insert_into_table ASSIGNING <example>.' )
( ' ENDMETHOD.' )
( ' ENDCLASS.' )
).
ENDMETHOD.

ENDCLASS.

CLASS ltc_append_lines_of DEFINITION INHERITING FROM ltc_append_to FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PROTECTED SECTION.
METHODS get_code_with_issue REDEFINITION.
ENDCLASS.

CLASS ltc_append_lines_of IMPLEMENTATION.

METHOD get_code_with_issue.
result = VALUE #(
( ' REPORT y_example.' )

( ' CLASS y_example DEFINITION.' )
( ' PUBLIC SECTION.' )
( ' METHODS example.' )
( ' ENDCLASS.' )

( ' CLASS y_example IMPLEMENTATION.' )
( ' METHOD example.' )
( ' DATA prefer_insert_into_table TYPE TABLE OF string.' )
( ' DATA example_table TYPE TABLE OF string.' )
( ' APPEND LINES OF example_table TO prefer_insert_into_table.' )
( ' ENDMETHOD.' )
( ' ENDCLASS.' )
).
ENDMETHOD.

ENDCLASS.

CLASS ltc_append_sorted_by DEFINITION INHERITING FROM ltc_append_to FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PROTECTED SECTION.
METHODS get_code_without_issue REDEFINITION.
ENDCLASS.

CLASS ltc_append_sorted_by IMPLEMENTATION.

METHOD get_code_without_issue.
result = VALUE #(
( ' REPORT y_example.' )

( ' CLASS y_example DEFINITION.' )
( ' PUBLIC SECTION.' )
( ' METHODS example.' )
( ' ENDCLASS.' )

( ' CLASS y_example IMPLEMENTATION.' )
( ' METHOD example.' )
( ' DATA prefer_insert_into_table TYPE TABLE OF sflight.' )
( ' DATA example_line TYPE sflight.' )
( ' APPEND example_line TO prefer_insert_into_table SORTED BY fldate.' )
( ' ENDMETHOD.' )
( ' ENDCLASS.' )
).
ENDMETHOD.

ENDCLASS.


CLASS ltc_select DEFINITION INHERITING FROM ltc_append_to FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PROTECTED SECTION.
METHODS get_code_without_issue REDEFINITION.
ENDCLASS.

CLASS ltc_select IMPLEMENTATION.

METHOD get_code_without_issue.
result = VALUE #(
( ' REPORT ut_test.' )
( ' START-OF-SELECTION.' )
( ' DATA example_table TYPE TABLE OF sflight.' )
( ' SELECT * FROM sflight APPENDING TABLE example_table.' )
).
ENDMETHOD.

ENDCLASS.
17 changes: 17 additions & 0 deletions src/y_check_prefer_insert_into.clas.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>Y_CHECK_PREFER_INSERT_INTO</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>Prefer INSERT INTO TABLE to APPEND TO</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>