├── .github ├── CODEOWNERS ├── workflows │ └── on_pull_request.yml └── ISSUE_TEMPLATE │ ├── bug.md │ └── new-check.md ├── src ├── test_objects │ ├── #cc4a#test_prefer_is_not.clas.locals_def.abap │ ├── #cc4a#test_method_signature_if.intf.abap │ ├── #cc4a#if_test_avoid_self_ref.intf.abap │ ├── #cc4a#test_prefer_methods.fugr.#cc4a#ltest_prefer_methodstop.abap │ ├── #cc4a#bp_test_rap_unamanaged.clas.abap │ ├── #cc4a#test_check_constant_if2.intf.abap │ ├── #cc4a#test_rap_unamanaged.ddls.baseinfo │ ├── #cc4a#test_check_constant_if1.clas.abap │ ├── #cc4a#test_db_access_in_ut.clas.abap │ ├── #cc4a#test_prefer_methods.fugr.#cc4a#rfc_disabled_module.abap │ ├── #cc4a#test_prefer_methods.fugr.#cc4a#rfc_enabled_module.abap │ ├── #cc4a#test_prefer_is_not.clas.locals_imp.abap │ ├── #cc4a#test_rap_unamanaged.bdef.asbdef │ ├── package.devc.xml │ ├── #cc4a#test_avoid_self_ref_sup.clas.abap │ ├── #cc4a#test_rap_unamanaged.ddls.asddls │ ├── #cc4a#test_prefer_is_not_2.clas.abap │ ├── #cc4a#test_rap_unamanaged.ddls.xml │ ├── #cc4a#test_prefer_methods.fugr.#cc4a#ltest_prefer_methodstop.xml │ ├── #cc4a#test_modern_language.clas.xml │ ├── #cc4a#test_prefer_methods.fugr.#cc4a#sapltest_prefer_methods.xml │ ├── #cc4a#test_proper_bool_expr.clas.xml │ ├── #cc4a#test_scope_of_variable.clas.xml │ ├── #cc4a#if_test_avoid_self_ref.intf.xml │ ├── #cc4a#test_method_signature_if.intf.xml │ ├── #cc4a#test_for_db_statements.clas.xml │ ├── #cc4a#test_check_constant_if2.intf.xml │ ├── #cc4a#test_avoid_test_seam.clas.xml │ ├── #cc4a#test_prefer_is_not_2.clas.xml │ ├── #cc4a#test_chain_declaration.clas.xml │ ├── #cc4a#test_method_signature.clas.xml │ ├── #cc4a#test_prefer_is_not.clas.xml │ ├── #cc4a#test_avoid_default_key.clas.xml │ ├── #cc4a#test_avoid_self_ref_sup.clas.xml │ ├── #cc4a#test_method_signature_1.clas.xml │ ├── #cc4a#test_method_signature_2.clas.xml │ ├── #cc4a#test_check_constant_if1.clas.xml │ ├── #cc4a#test_equal_sign_chaining.clas.xml │ ├── #cc4a#test_check_in_iteration.clas.xml │ ├── #cc4a#test_avoid_self_ref.clas.xml │ ├── #cc4a#test_db_access_in_ut.clas.xml │ ├── #cc4a#bp_test_rap_unamanaged.clas.xml │ ├── #cc4a#test_method_signature_3.clas.xml │ ├── #cc4a#test_method_signature_3.clas.abap │ ├── #cc4a#rfc_enabled_module_rfc.sco2.xml │ ├── #cc4a#test_prefer_methods.fugr.xml │ ├── #cc4a#test_method_signature_2.clas.abap │ ├── #cc4a#rfc_enabled_module_rfc_ibs.sia6.xml │ ├── #cc4a#test_prefer_methods.fugr.#cc4a#sapltest_prefer_methods.abap │ ├── #cc4a#rfc_enabled_module rf.sush.xml │ ├── #cc4a#test_method_signature_1.clas.abap │ ├── #cc4a#test_equal_sign_chaining.clas.abap │ ├── #cc4a#test_avoid_self_ref.clas.testclasses.abap │ ├── #cc4a#test_check_constant_if1.clas.locals_imp.abap │ ├── #cc4a#test_avoid_test_seam.clas.abap │ ├── #cc4a#test_rap_unamanaged.bdef.xml │ ├── #cc4a#test_db.tabl.xml │ ├── #cc4a#test_avoid_default_key.clas.abap │ ├── #cc4a#bp_test_rap_unamanaged.clas.locals_imp.abap │ ├── #cc4a#test_avoid_self_ref.clas.locals_imp.abap │ ├── #cc4a#test_rap.tabl.xml │ ├── #cc4a#test_check_in_iteration.clas.abap │ ├── #cc4a#test_modern_language.clas.locals_imp.abap │ ├── #cc4a#test_avoid_self_ref.clas.abap │ ├── #cc4a#test_prefer_is_not.clas.abap │ ├── #cc4a#test_proper_bool_expr.clas.abap │ ├── #cc4a#tstflight1.tabl.xml │ ├── #cc4a#test_method_signature.clas.abap │ ├── #cc4a#test_for_db_statements.clas.abap │ ├── #cc4a#test_scope_of_variable.clas.abap │ └── #cc4a#test_chain_declaration.clas.abap ├── core │ ├── (cc4a)code_pal.chkc.json │ ├── package.devc.xml │ ├── #cc4a#if_check_meta_data.intf.abap │ ├── #cc4a#cx_clause_is_initial.clas.abap │ ├── #cc4a#cx_line_break_impossible.clas.abap │ ├── #cc4a#cx_token_is_no_bracket.clas.abap │ ├── #cc4a#cx_token_is_no_operator.clas.abap │ ├── #cc4a#if_abap_analyzer.intf.xml │ ├── #cc4a#if_check_meta_data.intf.xml │ ├── #cc4a#check_meta_data.clas.xml │ ├── #cc4a#abap_analyzer.clas.xml │ ├── #cc4a#cx_clause_is_initial.clas.xml │ ├── #cc4a#cx_line_break_impossible.clas.xml │ ├── #cc4a#cx_token_is_no_bracket.clas.xml │ ├── #cc4a#cx_token_is_no_operator.clas.xml │ ├── (cc4a)code_pal_remote.chkv.json │ ├── (cc4a)code_pal_full.chkv.json │ ├── #cc4a#check_meta_data.clas.abap │ └── #cc4a#if_abap_analyzer.intf.abap ├── checks │ ├── #cc4a#modern_language.clas.locals_imp.abap │ ├── (cc4a)modern.chko.json │ ├── #cc4a#modern_language.clas.locals_def.abap │ ├── (cc4a)variable_scope.chko.json │ ├── (cc4a)prefer_methods.chko.json │ ├── (cc4a)avoid_test_seam.chko.json │ ├── (cc4a)assignment_chaining.chko.json │ ├── (cc4a)chain_declarations.chko.json │ ├── (cc4a)check_in_iteration.chko.json │ ├── package.devc.xml │ ├── (cc4a)prefer_is_not.chko.json │ ├── (cc4a)avoid_db_access_in_aunit.chko.json │ ├── (cc4a)constants_interface.chko.json │ ├── (cc4a)proper_bool_usage.chko.json │ ├── (cc4a)avoid_self_reference.chko.json │ ├── (cc4a)avoid_default_key.chko.json │ ├── #cc4a#avoid_test_seam.clas.xml │ ├── #cc4a#db_access_in_ut.clas.xml │ ├── #cc4a#check_constant_interface.clas.xml │ ├── #cc4a#prefer_is_not.clas.xml │ ├── #cc4a#avoid_self_reference.clas.xml │ ├── #cc4a#avoid_default_key.clas.xml │ ├── #cc4a#scope_of_variable.clas.xml │ ├── #cc4a#chain_declaration.clas.xml │ ├── #cc4a#prefer_methods.clas.xml │ ├── #cc4a#equals_sign_chaining.clas.xml │ ├── #cc4a#scope_of_variable.clas.locals_def.abap │ ├── #cc4a#check_in_iteration.clas.xml │ ├── (cc4a)method_signature.chko.json │ ├── #cc4a#proper_bool_expression.clas.xml │ ├── #cc4a#method_signature.clas.xml │ ├── #cc4a#prefer_methods.clas.testclasses.abap │ ├── #cc4a#scope_of_variable.clas.locals_imp.abap │ ├── #cc4a#avoid_test_seam.clas.abap │ ├── #cc4a#check_constant_interface.clas.testclasses.abap │ ├── #cc4a#avoid_test_seam.clas.testclasses.abap │ ├── #cc4a#modern_language.clas.xml │ ├── #cc4a#prefer_methods.clas.abap │ ├── #cc4a#check_constant_interface.clas.abap │ ├── #cc4a#equals_sign_chaining.clas.testclasses.abap │ ├── #cc4a#avoid_default_key.clas.abap │ ├── #cc4a#avoid_default_key.clas.testclasses.abap │ └── #cc4a#equals_sign_chaining.clas.abap ├── package.devc.xml └── #cc4a#.nspc.xml ├── .abapgit.xml ├── REUSE.toml ├── docs └── contributing-code.md ├── CONTRIBUTING.md ├── README.md └── CODE_OF_CONDUCT.md /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | @SAP/code-pal-for-abap-cloud-admin -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_is_not.clas.locals_def.abap: -------------------------------------------------------------------------------- 1 | class tester definition deferred. 2 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_method_signature_if.intf.abap: -------------------------------------------------------------------------------- 1 | INTERFACE /cc4a/test_method_signature_if 2 | PUBLIC . 3 | METHODS public_inst_interface_meth. 4 | 5 | ENDINTERFACE. 6 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#if_test_avoid_self_ref.intf.abap: -------------------------------------------------------------------------------- 1 | interface /cc4a/if_test_avoid_self_ref 2 | public. 3 | 4 | methods meth_1 5 | importing var_1 type i. 6 | 7 | endinterface. 8 | -------------------------------------------------------------------------------- /src/core/(cc4a)code_pal.chkc.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Code Pal", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_methods.fugr.#cc4a#ltest_prefer_methodstop.abap: -------------------------------------------------------------------------------- 1 | FUNCTION-POOL /CC4A/TEST_PREFER_METHODS. "MESSAGE-ID .. 2 | 3 | * INCLUDE /CC4A/LTEST_PREFER_METHODSD... " Local class definition 4 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#bp_test_rap_unamanaged.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/bp_test_rap_unamanaged definition public abstract final for behavior of /cc4a/test_rap_unamanaged. 2 | endclass. 3 | 4 | class /cc4a/bp_test_rap_unamanaged implementation. 5 | endclass. 6 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_check_constant_if2.intf.abap: -------------------------------------------------------------------------------- 1 | INTERFACE /cc4a/test_check_constant_if2 PUBLIC. 2 | CONSTANTS: 3 | co_1 TYPE symsgty VALUE 'E', 4 | co_2 TYPE symsgty VALUE 'W', 5 | co_3 TYPE symsgty VALUE 'N'. 6 | ENDINTERFACE. 7 | -------------------------------------------------------------------------------- /src/checks/#cc4a#modern_language.clas.locals_imp.abap: -------------------------------------------------------------------------------- 1 | *"* use this source file for the definition and implementation of 2 | *"* local helper classes, interface definitions and type 3 | *"* declarations 4 | 5 | class lcx_error implementation. 6 | endclass. 7 | -------------------------------------------------------------------------------- /src/checks/(cc4a)modern.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Modern Language", 5 | "originalLanguage": "en" 6 | }, 7 | "category": "/CC4A/CODE_PAL", 8 | "implementingClass": "/CC4A/MODERN_LANGUAGE", 9 | "checkType": "remoteEnabled" 10 | } -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_rap_unamanaged.ddls.baseinfo: -------------------------------------------------------------------------------- 1 | { 2 | "BASEINFO": 3 | { 4 | "FROM": 5 | [ 6 | "/CC4A/TEST_RAP" 7 | ], 8 | "ASSOCIATED": 9 | [], 10 | "BASE": 11 | [], 12 | "ANNO_REF": 13 | [], 14 | "SCALAR_FUNCTION": 15 | [], 16 | "VERSION":0, 17 | "ANNOREF_EVALUATION_ERROR":"" 18 | } 19 | } -------------------------------------------------------------------------------- /src/checks/#cc4a#modern_language.clas.locals_def.abap: -------------------------------------------------------------------------------- 1 | *"* use this source file for any type of declarations (class 2 | *"* definitions, interfaces or type declarations) you need for 3 | *"* components in the private section 4 | class lcx_error definition final 5 | inheriting from cx_static_check. 6 | endclass. 7 | -------------------------------------------------------------------------------- /src/checks/(cc4a)variable_scope.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Scope of Variable", 5 | "originalLanguage": "en" 6 | }, 7 | "category": "/CC4A/CODE_PAL", 8 | "implementingClass": "/CC4A/SCOPE_OF_VARIABLE", 9 | "checkType": "remoteEnabled" 10 | } 11 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_check_constant_if1.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS /cc4a/test_check_constant_if1 DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. 7 | PROTECTED SECTION. 8 | PRIVATE SECTION. 9 | ENDCLASS. 10 | 11 | 12 | 13 | CLASS /CC4A/TEST_CHECK_CONSTANT_IF1 IMPLEMENTATION. 14 | ENDCLASS. 15 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_db_access_in_ut.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/test_db_access_in_ut definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | protected section. 8 | private section. 9 | endclass. 10 | 11 | 12 | 13 | class /cc4a/test_db_access_in_ut implementation. 14 | endclass. 15 | 16 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_methods.fugr.#cc4a#rfc_disabled_module.abap: -------------------------------------------------------------------------------- 1 | FUNCTION /CC4A/RFC_DISABLED_MODULE. 2 | *"-------------------------------------------------------------------- 3 | *"*"Local Interface: 4 | *"-------------------------------------------------------------------- 5 | 6 | 7 | 8 | 9 | 10 | ENDFUNCTION. 11 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_methods.fugr.#cc4a#rfc_enabled_module.abap: -------------------------------------------------------------------------------- 1 | FUNCTION /CC4A/RFC_ENABLED_MODULE. 2 | *"-------------------------------------------------------------------- 3 | *"*"Local Interface: 4 | *"-------------------------------------------------------------------- 5 | 6 | 7 | 8 | 9 | 10 | ENDFUNCTION. 11 | -------------------------------------------------------------------------------- /.abapgit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | E 6 | /src/ 7 | PREFIX 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/checks/(cc4a)prefer_methods.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Prefer methods over other procedures", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "category": "/CC4A/CODE_PAL", 9 | "implementingClass": "/CC4A/PREFER_METHODS" 10 | } 11 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_is_not.clas.locals_imp.abap: -------------------------------------------------------------------------------- 1 | class tester definition final. 2 | public section. 3 | methods check 4 | importing val type i 5 | returning value(bool) type abap_bool. 6 | endclass. 7 | 8 | CLASS tester IMPLEMENTATION. 9 | 10 | METHOD check. 11 | 12 | ENDMETHOD. 13 | 14 | ENDCLASS. 15 | -------------------------------------------------------------------------------- /src/checks/(cc4a)avoid_test_seam.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Usage of TEST-SEAM", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "category": "/CC4A/CODE_PAL", 9 | "implementingClass": "/CC4A/AVOID_TEST_SEAM", 10 | "checkType": "remoteEnabled" 11 | } 12 | -------------------------------------------------------------------------------- /src/package.devc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code Pal for Cloud 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/checks/(cc4a)assignment_chaining.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Assignment Chaining", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "category": "/CC4A/CODE_PAL", 9 | "implementingClass": "/CC4A/EQUALS_SIGN_CHAINING", 10 | "checkType": "remoteEnabled" 11 | } 12 | -------------------------------------------------------------------------------- /src/checks/(cc4a)chain_declarations.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Chained declarations", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "category": "/CC4A/CODE_PAL", 9 | "implementingClass": "/CC4A/CHAIN_DECLARATION", 10 | "checkType": "remoteEnabled" 11 | } 12 | -------------------------------------------------------------------------------- /src/checks/(cc4a)check_in_iteration.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Check in iteration", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "category": "/CC4A/CODE_PAL", 9 | "implementingClass": "/CC4A/CHECK_IN_ITERATION", 10 | "checkType": "remoteEnabled" 11 | } 12 | -------------------------------------------------------------------------------- /src/checks/package.devc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Check implementations 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/checks/(cc4a)prefer_is_not.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "\"NOT IS\" in logical expressions", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "category": "/CC4A/CODE_PAL", 9 | "implementingClass": "/CC4A/PREFER_IS_NOT", 10 | "checkType": "remoteEnabled" 11 | } 12 | -------------------------------------------------------------------------------- /src/checks/(cc4a)avoid_db_access_in_aunit.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Database access in unit-tests", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "category": "/CC4A/CODE_PAL", 9 | "implementingClass": "/CC4A/DB_ACCESS_IN_UT", 10 | "checkType": "remoteEnabled" 11 | } 12 | -------------------------------------------------------------------------------- /src/checks/(cc4a)constants_interface.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Constants in Interfaces", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "category": "/CC4A/CODE_PAL", 9 | "implementingClass": "/CC4A/CHECK_CONSTANT_INTERFACE", 10 | "checkType": "remoteEnabled" 11 | } 12 | -------------------------------------------------------------------------------- /src/checks/(cc4a)proper_bool_usage.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Standard Boolean Expressions", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "category": "/CC4A/CODE_PAL", 9 | "implementingClass": "/CC4A/PROPER_BOOL_EXPRESSION", 10 | "checkType": "remoteEnabled" 11 | } 12 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_rap_unamanaged.bdef.asbdef: -------------------------------------------------------------------------------- 1 | unmanaged implementation in class /cc4a/bp_test_rap_unamanaged unique; 2 | strict ( 2 ); 3 | 4 | define behavior for /CC4A/TEST_RAP_UNAMANAGED //alias 5 | //late numbering 6 | lock master 7 | authorization master ( instance ) 8 | //etag master 9 | { 10 | create; 11 | update; 12 | delete; 13 | } -------------------------------------------------------------------------------- /src/test_objects/package.devc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Test objects for Code Pal 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/checks/(cc4a)avoid_self_reference.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Find unnecessary self-references", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "category": "/CC4A/CODE_PAL", 9 | "implementingClass": "/CC4A/AVOID_SELF_REFERENCE", 10 | "checkType": "remoteEnabled" 11 | } 12 | -------------------------------------------------------------------------------- /src/core/package.devc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code Pal for Cloud core functionality 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/checks/(cc4a)avoid_default_key.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Internal table definitions with default key", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "category": "/CC4A/CODE_PAL", 9 | "implementingClass": "/CC4A/AVOID_DEFAULT_KEY", 10 | "checkType": "remoteEnabled" 11 | } 12 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_avoid_self_ref_sup.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/test_avoid_self_ref_sup definition 2 | public 3 | create public . 4 | 5 | public section. 6 | methods super_meth 7 | importing imp type i. 8 | protected section. 9 | private section. 10 | endclass. 11 | 12 | 13 | 14 | class /cc4a/test_avoid_self_ref_sup implementation. 15 | 16 | method super_meth. 17 | 18 | endmethod. 19 | 20 | endclass. 21 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_rap_unamanaged.ddls.asddls: -------------------------------------------------------------------------------- 1 | @AccessControl.authorizationCheck: #NOT_REQUIRED 2 | define root view entity /CC4A/TEST_RAP_UNAMANAGED 3 | as select from /cc4a/test_rap 4 | { 5 | key key_field as KeyFieldRoot, 6 | data_field as DataFieldRoot, 7 | char_field as CharFieldRoot, 8 | crea_date_time as Timestamp, 9 | lchg_date_time as LastChangedAt 10 | } 11 | -------------------------------------------------------------------------------- /src/core/#cc4a#if_check_meta_data.intf.abap: -------------------------------------------------------------------------------- 1 | interface /cc4a/if_check_meta_data 2 | public. 3 | 4 | interfaces if_ci_atc_check_meta_data. 5 | 6 | methods has_valid_pseudo_comment 7 | importing 8 | statement type if_ci_atc_source_code_provider=>ty_statement 9 | finding_code type if_ci_atc_check_meta_data=>ty_finding_code_info-code 10 | returning value(has_valid_pseudo_comment) type abap_bool. 11 | 12 | endinterface. 13 | -------------------------------------------------------------------------------- /REUSE.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | SPDX-PackageName = "code pal for ABAP cloud" 3 | SPDX-PackageSupplier = "code pal for ABAP cloud team (@SAP/code-pal-for-abap-cloud-team)" 4 | SPDX-PackageDownloadLocation = "https://github.com/SAP/code-pal-for-abap-cloud" 5 | 6 | [[annotations]] 7 | path = "**" 8 | precedence = "aggregate" 9 | SPDX-FileCopyrightText = "2021 SAP SE or an SAP affiliate company and code pal for ABAP contributors" 10 | SPDX-License-Identifier = "Apache-2.0" 11 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_is_not_2.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/test_prefer_is_not_2 definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | protected section. 8 | private section. 9 | methods meth. 10 | endclass. 11 | 12 | 13 | 14 | class /cc4a/test_prefer_is_not_2 implementation. 15 | 16 | method meth. 17 | data(var_1) = 1. 18 | data(var_2) = 2. 19 | if var_1 is not initial and var_2 <> 2. 20 | endif. 21 | endmethod. 22 | 23 | endclass. 24 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_rap_unamanaged.ddls.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_RAP_UNAMANAGED 7 | E 8 | Test RAP unmanaged 9 | W 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.github/workflows/on_pull_request.yml: -------------------------------------------------------------------------------- 1 | name: CI (on pull request) 2 | 3 | on: pull_request_target 4 | 5 | permissions: 6 | checks: write 7 | contents: read 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 15 | - uses: actions/checkout@v3 16 | 17 | - name: abaplint 18 | uses: abaplint/actions-abaplint@main 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | -------------------------------------------------------------------------------- /src/core/#cc4a#cx_clause_is_initial.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/cx_clause_is_initial definition 2 | public 3 | inheriting from cx_dynamic_check 4 | final 5 | create public . 6 | 7 | public section. 8 | 9 | methods constructor. 10 | protected section. 11 | private section. 12 | endclass. 13 | 14 | 15 | 16 | class /cc4a/cx_clause_is_initial implementation. 17 | method constructor ##ADT_SUPPRESS_GENERATION. 18 | 19 | super->constructor( textid = textid previous = previous ). 20 | 21 | endmethod. 22 | 23 | endclass. 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name : Bug 3 | about : Use this template to report a bug, in particular false positive or negative findings from the Code Pal checks 4 | labels : bug 5 | 6 | --- 7 | 8 | **Affected Checks** 9 | > Which of the Code Pal checks is this about? 10 | 11 | **Expectation** 12 | > Describe the expected behavior of the check(s). 13 | 14 | **Actual Behavior** 15 | > Describe the actual behavior of the check(s). 16 | 17 | **Code** 18 | > If applicable, post an ABAP code example with which the behavior can be reproduced. -------------------------------------------------------------------------------- /src/core/#cc4a#cx_line_break_impossible.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/cx_line_break_impossible definition 2 | public 3 | inheriting from cx_dynamic_check 4 | final 5 | create public . 6 | 7 | public section. 8 | 9 | methods constructor. 10 | protected section. 11 | private section. 12 | endclass. 13 | 14 | 15 | 16 | class /cc4a/cx_line_break_impossible implementation. 17 | method constructor ##ADT_SUPPRESS_GENERATION. 18 | 19 | super->constructor( textid = textid previous = previous ). 20 | 21 | endmethod. 22 | 23 | endclass. 24 | -------------------------------------------------------------------------------- /src/core/#cc4a#cx_token_is_no_bracket.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/cx_token_is_no_bracket definition 2 | public 3 | inheriting from cx_dynamic_check 4 | final 5 | create public . 6 | 7 | public section. 8 | 9 | methods constructor. 10 | protected section. 11 | private section. 12 | ENDCLASS. 13 | 14 | 15 | 16 | CLASS /CC4A/CX_TOKEN_IS_NO_BRACKET IMPLEMENTATION. 17 | 18 | 19 | method constructor ##ADT_SUPPRESS_GENERATION. 20 | 21 | super->constructor( textid = textid previous = previous ). 22 | 23 | endmethod. 24 | ENDCLASS. 25 | -------------------------------------------------------------------------------- /src/#cc4a#.nspc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/ 7 | 22229904900326563203 8 | 9 | 10 | E 11 | Clean Code for ABAP 12 | FIEDLERT 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/core/#cc4a#cx_token_is_no_operator.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/cx_token_is_no_operator definition 2 | public 3 | inheriting from cx_dynamic_check 4 | final 5 | create public . 6 | 7 | public section. 8 | 9 | methods constructor. 10 | protected section. 11 | private section. 12 | ENDCLASS. 13 | 14 | 15 | 16 | CLASS /CC4A/CX_TOKEN_IS_NO_OPERATOR IMPLEMENTATION. 17 | 18 | 19 | method constructor ##ADT_SUPPRESS_GENERATION. 20 | 21 | super->constructor( textid = textid previous = previous ). 22 | 23 | endmethod. 24 | ENDCLASS. 25 | -------------------------------------------------------------------------------- /src/core/#cc4a#if_abap_analyzer.intf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/IF_ABAP_ANALYZER 7 | E 8 | ABAP code analysis 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_methods.fugr.#cc4a#ltest_prefer_methodstop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/LTEST_PREFER_METHODSTOP 7 | S 8 | D$ 9 | I 10 | S 11 | X 12 | D$S 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/core/#cc4a#if_check_meta_data.intf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/IF_CHECK_META_DATA 7 | E 8 | Shared meta data for checks 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_modern_language.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_MODERN_LANGUAGE 7 | E 8 | test 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_methods.fugr.#cc4a#sapltest_prefer_methods.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/SAPLTEST_PREFER_METHODS 7 | S 8 | D$ 9 | F 10 | S 11 | E 12 | X 13 | D$S 14 | 5 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_proper_bool_expr.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_PROPER_BOOL_EXPR 7 | E 8 | Test 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_scope_of_variable.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_SCOPE_OF_VARIABLE 7 | E 8 | Test 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new-check.md: -------------------------------------------------------------------------------- 1 | --- 2 | name : New check 3 | about : Use this template to propose a new Code Pal check 4 | labels : feature-request 5 | 6 | --- 7 | 8 | **Relevant style guide recommendations** 9 | > Explain which sections of the [Clean ABAP style guide](https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md) the new check is supposed to implement. 10 | 11 | **Feasibility** 12 | > Explain how this part of the style guide could be checked automatically 13 | 14 | **Prior Work** 15 | > Are there already other ATC checks (outside of Code Pal) that implement similar features? -------------------------------------------------------------------------------- /src/test_objects/#cc4a#if_test_avoid_self_ref.intf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/IF_TEST_AVOID_SELF_REF 7 | E 8 | Test object for /CC4A/AVOID_SELF_REFERENCE 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_method_signature_if.intf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_METHOD_SIGNATURE_IF 7 | E 8 | Test Interface for check Method Signature 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/core/#cc4a#check_meta_data.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/CHECK_META_DATA 7 | E 8 | Shared meta data implementation for all checks 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_for_db_statements.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_FOR_DB_STATEMENTS 7 | E 8 | test for db statements 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_check_constant_if2.intf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_CHECK_CONSTANT_IF2 7 | E 8 | Test Interface for check Constants Interface Check 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_avoid_test_seam.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_AVOID_TEST_SEAM 7 | E 8 | Test class for check Avoid TEST-SEAM 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_is_not_2.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_PREFER_IS_NOT_2 7 | E 8 | Test object for /CC4A/PREFER_IS_NOT 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/core/#cc4a#abap_analyzer.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/ABAP_ANALYZER 7 | E 8 | ABAP code analysis 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/core/#cc4a#cx_clause_is_initial.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/CX_CLAUSE_IS_INITIAL 7 | E 8 | clause is initial 9 | 40 10 | 1 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_chain_declaration.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_CHAIN_DECLARATION 7 | E 8 | Test class for check Chain Declaration 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_method_signature.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_METHOD_SIGNATURE 7 | E 8 | Test class for check Message Easy to Find 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_is_not.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_PREFER_IS_NOT 7 | E 8 | Test class for check Prefer IS NOT to NOT IS 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_avoid_default_key.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_AVOID_DEFAULT_KEY 7 | E 8 | Test class for check Avoid Default Table Key 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_avoid_self_ref_sup.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_AVOID_SELF_REF_SUP 7 | E 8 | Test object for /CC4A/AVOID_SELF_REFERENCE 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_method_signature_1.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_METHOD_SIGNATURE_1 7 | E 8 | Test class for check Message Easy to Find 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_method_signature_2.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_METHOD_SIGNATURE_2 7 | E 8 | Test class for check Message Easy to Find 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_check_constant_if1.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_CHECK_CONSTANT_IF1 7 | E 8 | Test Class for check Constants Interface Check 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_equal_sign_chaining.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_EQUAL_SIGN_CHAINING 7 | E 8 | Test class for check Equals Sign Chaining 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/core/#cc4a#cx_line_break_impossible.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/CX_LINE_BREAK_IMPOSSIBLE 7 | E 8 | line break impossible 9 | 40 10 | 1 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_check_in_iteration.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_CHECK_IN_ITERATION 7 | E 8 | Test class for check statements within iterations 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/core/#cc4a#cx_token_is_no_bracket.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/CX_TOKEN_IS_NO_BRACKET 7 | E 8 | Exception if given token is not a bracket 9 | 40 10 | 1 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/core/#cc4a#cx_token_is_no_operator.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/CX_TOKEN_IS_NO_OPERATOR 7 | E 8 | Exception if given token is not an operator 9 | 40 10 | 1 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_avoid_self_ref.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_AVOID_SELF_REF 7 | E 8 | Test class for check Avoid Self Reference 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_db_access_in_ut.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_DB_ACCESS_IN_UT 7 | E 8 | Test class for check Avoid database access in unit-tests 9 | 1 10 | X 11 | X 12 | 5 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#bp_test_rap_unamanaged.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/BP_TEST_RAP_UNAMANAGED 7 | E 8 | Behavior Implementation for /CC4A/TEST_RAP_UNAMANAGED 9 | 06 10 | 1 11 | X 12 | X 13 | X 14 | /CC4A/TEST_RAP_UNAMANAGED 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_method_signature_3.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_METHOD_SIGNATURE_3 7 | E 8 | Test class for check Message Easy to Find 9 | 05 10 | 1 11 | X 12 | X 13 | X 14 | 12 15 | 11 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_method_signature_3.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS /cc4a/test_method_signature_3 DEFINITION 2 | PUBLIC ABSTRACT CREATE PUBLIC 3 | FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. 4 | 5 | PUBLIC SECTION. 6 | METHODS public_inst_no_interface_meth1 FOR TESTING. 7 | METHODS public_inst_no_interface_meth2. 8 | 9 | PROTECTED SECTION. 10 | 11 | PRIVATE SECTION. 12 | 13 | ENDCLASS. 14 | 15 | 16 | 17 | CLASS /CC4A/TEST_METHOD_SIGNATURE_3 IMPLEMENTATION. 18 | 19 | 20 | METHOD public_inst_no_interface_meth1. 21 | "only signature is relevant for this test 22 | ENDMETHOD. 23 | 24 | 25 | METHOD public_inst_no_interface_meth2. 26 | "only signature is relevant for this test 27 | ENDMETHOD. 28 | ENDCLASS. 29 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#rfc_enabled_module_rfc.sco2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/RFC_ENABLED_MODULE_RFC 7 | SRFC 8 | /CC4A/RFC_ENABLED_MODULE 9 | X 10 | 5 11 | /CC4A/RFC_ENABLED_MODULE_RFC 12 | RFC Service /CC4A/RFC_ENABLED_MODULE 13 | 5 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_methods.fugr.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test class for prefer methods check 6 | 7 | /CC4A/LTEST_PREFER_METHODSTOP 8 | /CC4A/SAPLTEST_PREFER_METHODS 9 | 10 | 11 | 12 | /CC4A/RFC_DISABLED_MODULE 13 | Test module where rfc is disabled 14 | 15 | 16 | /CC4A/RFC_ENABLED_MODULE 17 | R 18 | Test module where rfc is enabled 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_method_signature_2.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS /cc4a/test_method_signature_2 DEFINITION 2 | INHERITING FROM /cc4a/test_method_signature_1 3 | PUBLIC 4 | FINAL 5 | CREATE PUBLIC . 6 | 7 | PUBLIC SECTION. 8 | METHODS public_inst_no_interface_meth1 REDEFINITION. 9 | METHODS public_inst_no_interface_meth3. 10 | 11 | PROTECTED SECTION. 12 | 13 | PRIVATE SECTION. 14 | METHODS priv_inst_not_interface_meth. 15 | 16 | ENDCLASS. 17 | 18 | 19 | 20 | CLASS /CC4A/TEST_METHOD_SIGNATURE_2 IMPLEMENTATION. 21 | 22 | 23 | METHOD priv_inst_not_interface_meth. 24 | "only signature is relevant for this test 25 | ENDMETHOD. 26 | 27 | 28 | METHOD public_inst_no_interface_meth1. 29 | "only signature is relevant for this test 30 | ENDMETHOD. 31 | 32 | 33 | METHOD public_inst_no_interface_meth3. 34 | "only signature is relevant for this test 35 | ENDMETHOD. 36 | ENDCLASS. 37 | -------------------------------------------------------------------------------- /src/checks/#cc4a#avoid_test_seam.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/AVOID_TEST_SEAM 7 | E 8 | Avoid using TEST-SEAM 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | DES 19 | Usage of TEST-SEAM 20 | 88 21 | 22 | 23 | I 24 | UOT 25 | Usage of TEST-SEAM 26 | 88 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/checks/#cc4a#db_access_in_ut.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/DB_ACCESS_IN_UT 7 | E 8 | Avoid database access in unit tests 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | DAU 19 | Database access in unit test 20 | 88 21 | 22 | 23 | I 24 | DES 25 | Database access in unit tests 26 | 88 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/checks/#cc4a#check_constant_interface.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/CHECK_CONSTANT_INTERFACE 7 | E 8 | Constants Interface Check 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | DES 19 | Constants in Interfaces 20 | 132 21 | 22 | 23 | I 24 | MC1 25 | Interface contains only constants 26 | 132 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#rfc_enabled_module_rfc_ibs.sia6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | /CC4A/RFC_ENABLED_MODULE_RFC_IBS 8 | SIA6 9 | RFC Service /CC4A/RFC_ENABLED_MODULE 10 | CB9980000871 11 | EN 12 | X11 13 | 14 | /CC4A/CODE_PAL_TEST_OBJECTS 15 | 16 | 5 17 | 18 | /CC4A/RFC_ENABLED_MODULE_RFC_IBS 19 | IBS 20 | 5 21 | /CC4A/RFC_ENABLED_MODULE_RFC 22 | p 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /docs/contributing-code.md: -------------------------------------------------------------------------------- 1 | All objects belonging to Code Pal for Cloud should lie in the `/CC4A/` namespace. The basic package structure is: 2 | - `core` for functionality shared by more than one check 3 | - `check` for the actual check implementation and their "ATC Check" objects 4 | - `test_objects` for test objects, i.e. everything that only exists for the automated (unit) tests 5 | 6 | All our code should conform to the recommendations of the [Clean ABAP style guide](https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md). In particular this means that there should be no findings from Code Pal checks on Code Pal code. 7 | 8 | SAP's new check implementation framework via the interface `IF_CI_ATC_CHECK` is no longer based on inheritance, so we also prefer composition over inheritance: Instead of having check classes share logic by subclassing, they should delegate shared logic to other global classes. `/CC4A/CHECK_META_DATA` does this for the checks' meta data and `/CC4A/ABAP_ANALYZER` should contain all logic that analyzes ABAP code. Do not hesitate to add methods to these classes or introduce new classes for more shared functionality. -------------------------------------------------------------------------------- /src/checks/#cc4a#prefer_is_not.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/PREFER_IS_NOT 7 | E 8 | Prefer IS NOT to NOT IS 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | DES 19 | Prefer IS NOT to NOT IS 20 | 88 21 | 22 | 23 | I 24 | NIC 25 | Usage of NOT IS condition 26 | 88 27 | 28 | 29 | I 30 | QIN 31 | Replace NOT IS condition with IS NOT 32 | 88 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/checks/#cc4a#avoid_self_reference.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/AVOID_SELF_REFERENCE 7 | E 8 | Avoid self-reference 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | DES 19 | Find unnecessary self-references 20 | 88 21 | 22 | 23 | I 24 | DUS 25 | Unnecessary self-reference 26 | 88 27 | 28 | 29 | I 30 | QRS 31 | Remove self-reference 32 | 88 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/checks/#cc4a#avoid_default_key.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/AVOID_DEFAULT_KEY 7 | E 8 | Avoid Default Table Keys 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | DES 19 | Avoid default keys 20 | 88 21 | 22 | 23 | I 24 | DTK 25 | Usage of default table key 26 | 88 27 | 28 | 29 | I 30 | QEK 31 | Replace WITH DEFAULT KEY with WITH EMPTY KEY 32 | 88 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/checks/#cc4a#scope_of_variable.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/SCOPE_OF_VARIABLE 7 | E 8 | Scope of Variable 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | 001 19 | Variable &1 declared inside block and used outside 20 | 94 21 | 22 | 23 | I 24 | DES 25 | Scope of Variable 26 | 27 27 | 28 | 29 | I 30 | QF1 31 | Change scope of variable 32 | 48 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/checks/#cc4a#chain_declaration.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/CHAIN_DECLARATION 7 | E 8 | Avoid chain declaration 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | DES 19 | Avoid Chain Declaration 20 | 88 21 | 22 | 23 | I 24 | QSD 25 | Replace Chain Declaration with Single Declaration 26 | 88 27 | 28 | 29 | I 30 | UCD 31 | Usage of Chain Declaration 32 | 88 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/checks/#cc4a#prefer_methods.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/PREFER_METHODS 7 | E 8 | Prefer methods over other procedures 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | DES 19 | Prefer methods over other procedures 20 | 88 21 | 22 | 23 | I 24 | PRM 25 | Definition of function module &1 26 | 88 27 | 28 | 29 | I 30 | UFR 31 | Definition of FORM routine &1 32 | 88 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/checks/#cc4a#equals_sign_chaining.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/EQUALS_SIGN_CHAINING 7 | E 8 | Equals Sign Chaining 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | DES 19 | Assignment Chaining 20 | 132 21 | 22 | 23 | I 24 | MC1 25 | Values are allocated more than once within one statement 26 | 132 27 | 28 | 29 | I 30 | Q1S 31 | Break assignment chain into multiple rows 32 | 132 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_methods.fugr.#cc4a#sapltest_prefer_methods.abap: -------------------------------------------------------------------------------- 1 | ******************************************************************* 2 | * System-defined Include-files. * 3 | ******************************************************************* 4 | INCLUDE /CC4A/LTEST_PREFER_METHODSTOP. " Global Declarations 5 | INCLUDE /CC4A/LTEST_PREFER_METHODSUXX. " Function Modules 6 | 7 | ******************************************************************* 8 | * User-defined Include-files (if necessary). * 9 | ******************************************************************* 10 | * INCLUDE /CC4A/LTEST_PREFER_METHODSF... " Subroutines 11 | * INCLUDE /CC4A/LTEST_PREFER_METHODSO... " PBO-Modules 12 | * INCLUDE /CC4A/LTEST_PREFER_METHODSI... " PAI-Modules 13 | * INCLUDE /CC4A/LTEST_PREFER_METHODSE... " Events 14 | * INCLUDE /CC4A/LTEST_PREFER_METHODSP... " Local class implement. 15 | * INCLUDE /CC4A/LTEST_PREFER_METHODST99. " ABAP Unit tests 16 | 17 | form test_form. 18 | 19 | 20 | endform. 21 | 22 | form pseudo_comment. "#EC CI_FROM 23 | 24 | 25 | endform. 26 | -------------------------------------------------------------------------------- /src/checks/#cc4a#scope_of_variable.clas.locals_def.abap: -------------------------------------------------------------------------------- 1 | types ty_block_list type sorted table of i with unique key table_line. 2 | 3 | class block_finder definition final. 4 | public section. 5 | types: 6 | begin of ty_block_info, 7 | block type i, 8 | inside_injection type abap_bool, 9 | end of ty_block_info. 10 | 11 | methods constructor 12 | importing 13 | blocks type if_ci_atc_source_code_provider=>ty_blocks 14 | first_valid_block type i. 15 | methods find_parent_branch 16 | importing block type i 17 | returning value(result) type ty_block_info. 18 | methods find_outer_block 19 | importing blocks type ty_block_list 20 | returning value(result) type i. 21 | private section. 22 | data first_valid_block type i. 23 | data blocks type if_ci_Atc_source_code_provider=>ty_blocks. 24 | 25 | methods least_common_parent 26 | importing 27 | block_1 type i 28 | block_2 type i 29 | returning 30 | value(result) type i. 31 | methods is_parent 32 | importing 33 | parent type i 34 | child type i 35 | returning 36 | value(result) type abap_bool. 37 | endclass. 38 | -------------------------------------------------------------------------------- /src/checks/#cc4a#check_in_iteration.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/CHECK_IN_ITERATION 7 | E 8 | Avoid using of CHECK-statement 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | DES 19 | Avoid using of CHECK-statement 20 | 88 21 | 22 | 23 | I 24 | ICC 25 | Replace CHECK condition with IF condition 26 | 88 27 | 28 | 29 | I 30 | USG 31 | Usage of CHECK-statement 32 | 88 33 | 34 | 35 | I 36 | WLD 37 | Replace CHECK condition with a WHERE condition in loop 38 | 88 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#rfc_enabled_module rf.sush.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/RFC_ENABLED_MODULE 7 | RF 8 | /CC4A/RFC_ENABLED_MODULE 9 | Test module where rfc is enabled 10 | /CC4A/CODE_PAL_TEST_OBJECTS 11 | 5 12 | 13 | 14 | 15 | /CC4A/RFC_ENABLED_MODULE 16 | RF 17 | S_RFC 18 | X 19 | 20 | 21 | 22 | 23 | S_RFC 24 | Authorization Check for RFC Access 25 | AAAB 26 | X 27 | SRCX 28 | BC-MID-RFC 29 | Check 30 | Check 31 | No 32 | 3 33 | Okay 34 | @08@ 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/checks/(cc4a)method_signature.chko.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Method Signature", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "category": "/CC4A/CODE_PAL", 9 | "implementingClass": "/CC4A/METHOD_SIGNATURE", 10 | "checkType": "remoteEnabled", 11 | "parameters": [ 12 | { 13 | "name": "CheckPubMethodNoInterface", 14 | "description": "Check for public methods which are not in an interface" 15 | }, 16 | { 17 | "name": "CheckInputParamBoolean", 18 | "description": "Check for importing parameter of type boolean" 19 | }, 20 | { 21 | "name": "CheckInputParamOptional", 22 | "description": "Check for importing parameter which are optional" 23 | }, 24 | { 25 | "name": "CheckOutputParamNumber", 26 | "description": "Check number of output parameter (exporting, changing, returning)" 27 | }, 28 | { 29 | "name": "CheckOutputParamType", 30 | "description": "Check for output parameter combinations (exporting, changing, returning)" 31 | }, 32 | { 33 | "name": "CheckRetParamNotNamedResult", 34 | "description": "Check returning parameter not named RESULT" 35 | }, 36 | { 37 | "name": "CheckExpParamNumberNotOne", 38 | "description": "Check number of exporting parameter more than 1" 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_method_signature_1.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS /cc4a/test_method_signature_1 DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC ABSTRACT. 4 | 5 | PUBLIC SECTION. 6 | INTERFACES /cc4a/test_method_signature_if. 7 | 8 | CLASS-METHODS public_stat_no_interface_meth. 9 | 10 | METHODS constructor. 11 | METHODS public_inst_no_interface_meth1 ABSTRACT. 12 | METHODS public_inst_no_interface_meth2. 13 | 14 | PROTECTED SECTION. 15 | METHODS prot_inst_not_interface_meth. 16 | 17 | PRIVATE SECTION. 18 | METHODS priv_inst_not_interface_meth. 19 | 20 | ENDCLASS. 21 | 22 | 23 | 24 | CLASS /CC4A/TEST_METHOD_SIGNATURE_1 IMPLEMENTATION. 25 | 26 | 27 | METHOD /cc4a/test_method_signature_if~public_inst_interface_meth. 28 | "only signature is relevant for this test 29 | ENDMETHOD. 30 | 31 | 32 | METHOD constructor. 33 | "only signature is relevant for this test 34 | ENDMETHOD. 35 | 36 | 37 | METHOD priv_inst_not_interface_meth. 38 | "only signature is relevant for this test 39 | ENDMETHOD. 40 | 41 | 42 | METHOD prot_inst_not_interface_meth. 43 | "only signature is relevant for this test 44 | ENDMETHOD. 45 | 46 | 47 | METHOD public_inst_no_interface_meth2. 48 | "only signature is relevant for this test 49 | ENDMETHOD. 50 | 51 | 52 | METHOD public_stat_no_interface_meth. 53 | "only signature is relevant for this test 54 | ENDMETHOD. 55 | ENDCLASS. 56 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Code of Conduct 4 | 5 | All members of the project community must abide by the [Contributor Covenant, version 2.1](CODE_OF_CONDUCT.md). 6 | Only by respecting each other we can develop a productive, collaborative community. 7 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting [a project maintainer](.reuse/dep5). 8 | 9 | ## Contributing Code or Documentation 10 | 11 | Contributions should be submitted as GitHub pull requests. 12 | 13 | - If you're working on a contribution that will resolve an issue, please claim that issue beforehand (by commenting on it) so that other people know you're working on it. 14 | - Contributions must be licensed under the [Apache 2.0 License](./LICENSE) 15 | - For legal reasons, contributors will be asked to accept a Developer Certificate of Origin (DCO) when they create their first pull request to this project. This happens in an automated fashion during the submission process. SAP uses [the standard DCO text of the Linux Foundation](https://developercertificate.org/). 16 | 17 | See our [guide for code contributors](contributing-code.md) for coding style and architectural guidelines. 18 | 19 | ## Issues and Planning 20 | 21 | We use GitHub issues to track bugs and enhancement requests. 22 | 23 | Please provide as much context as possible when you open an issue. In particular, when reporting a false positive or negative finding, always provide a code sample with which other contributors can reproduce that finding. 24 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_equal_sign_chaining.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS /cc4a/test_equal_sign_chaining DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. 7 | " Currently one method per finding needed due to a bug in CL_CI_ATC_UNIT_DRIVER 8 | METHODS finding_1. 9 | METHODS finding_2. 10 | METHODS finding_3. 11 | METHODS finding_4. 12 | protected section. 13 | private section. 14 | ENDCLASS. 15 | 16 | 17 | 18 | CLASS /CC4A/TEST_EQUAL_SIGN_CHAINING IMPLEMENTATION. 19 | 20 | 21 | METHOD finding_1. 22 | DATA: 23 | a TYPE string, 24 | b TYPE string, 25 | c TYPE string, 26 | d TYPE string. 27 | a = b = c = d. 28 | " Space needed because of bug 29 | " Space needed because of bug 30 | ENDMETHOD. 31 | 32 | 33 | METHOD finding_2. 34 | DATA: 35 | a TYPE string, 36 | b TYPE string, 37 | c TYPE string. 38 | a = b = CONV #( c ). 39 | ENDMETHOD. 40 | 41 | 42 | METHOD finding_3. 43 | DATA: 44 | a TYPE string, 45 | b TYPE string, 46 | c TYPE string, 47 | d TYPE string. 48 | a = b = c = d. "#EC EQUALS_CHAINING 49 | " Space needed because of bug 50 | " Space needed because of bug 51 | ENDMETHOD. 52 | 53 | 54 | METHOD finding_4. 55 | DATA: 56 | a TYPE string, 57 | b TYPE string, 58 | c TYPE string. 59 | " Intentional offset, don't pretty print 60 | a = b = c. 61 | " Space needed because of bug 62 | ENDMETHOD. 63 | ENDCLASS. 64 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_avoid_self_ref.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | class test definition final for testing 2 | duration short 3 | risk level harmless. 4 | 5 | private section. 6 | 7 | data att1 type i. 8 | data att2 type string. 9 | data att3 type c. 10 | data att4 type i. 11 | data att5 type string. 12 | methods m1 importing att1 type i. 13 | methods m2 changing att3 type c. 14 | methods m3 returning value(att4) type string. 15 | endclass. 16 | 17 | class test implementation. 18 | method m1. 19 | 20 | endmethod. 21 | 22 | method m2. 23 | data att2 type f. 24 | me->att2 = 'Hugo'. 25 | att2 = '1.2'. 26 | me->att3 = 'Hugo'. 27 | me->att4 = 7. 28 | endmethod. 29 | 30 | method m3. 31 | me->att4 = 5. 32 | me->att1 = 2. 33 | att4 = 'HUHU'. 34 | endmethod. 35 | endclass. 36 | 37 | class test2 definition final for testing 38 | duration short 39 | risk level harmless. 40 | 41 | private section. 42 | 43 | data att1 type i. 44 | data att2 type string. 45 | data att3 type c. 46 | data att4 type i. 47 | data att5 type string. 48 | methods m1. 49 | methods m2. 50 | methods m3. 51 | endclass. 52 | 53 | class test2 implementation. 54 | method m1. 55 | 56 | endmethod. 57 | 58 | method m2. 59 | data att2 type f. 60 | me->att2 = 'Hugo'. 61 | att2 = '1.2'. 62 | me->att3 = 'Hugo'. 63 | me->att4 = 7. 64 | endmethod. 65 | 66 | method m3. 67 | me->att4 = 5. 68 | me->att1 = 2. 69 | att4 = 'HUHU'. 70 | endmethod. 71 | endclass. 72 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_check_constant_if1.clas.locals_imp.abap: -------------------------------------------------------------------------------- 1 | *"* use this source file for the definition and implementation of 2 | *"* local helper classes, interface definitions and type 3 | *"* declarations 4 | INTERFACE if_local_1. 5 | " Finding expected 6 | CONSTANTS: 7 | co_1 TYPE symsgty VALUE 'E', 8 | co_2 TYPE symsgty VALUE 'W', 9 | co_3 TYPE symsgty VALUE 'N'. 10 | ENDINTERFACE. 11 | 12 | CLASS cl_local_1 DEFINITION. 13 | PUBLIC SECTION. 14 | INTERFACES if_local_1. 15 | ENDCLASS. 16 | 17 | INTERFACE if_local_2. 18 | " Finding expected 19 | CONSTANTS: 20 | co_1 TYPE symsgty VALUE 'E', 21 | co_2 TYPE symsgty VALUE 'W', 22 | co_3 TYPE symsgty VALUE 'N'. 23 | ENDINTERFACE. 24 | 25 | CLASS cl_local_2 DEFINITION. 26 | PUBLIC SECTION. 27 | INTERFACES if_local_2. 28 | ENDCLASS. 29 | 30 | INTERFACE if_local_3. "#EC CONS_INTF 31 | " No finding expected due to pseudo comment 32 | CONSTANTS: 33 | co_1 TYPE symsgty VALUE 'E', 34 | co_2 TYPE symsgty VALUE 'W', 35 | co_3 TYPE symsgty VALUE 'N'. 36 | ENDINTERFACE. 37 | 38 | CLASS cl_local_3 DEFINITION. 39 | PUBLIC SECTION. 40 | INTERFACES if_local_3. 41 | ENDCLASS. 42 | 43 | INTERFACE if_local_4. 44 | " No finding expected due to method declaration 45 | CONSTANTS: 46 | co_1 TYPE symsgty VALUE 'E', 47 | co_2 TYPE symsgty VALUE 'W', 48 | co_3 TYPE symsgty VALUE 'N'. 49 | METHODS: 50 | a. 51 | ENDINTERFACE. 52 | 53 | INTERFACE if_local_5. 54 | " No finding expected since no constants are declared 55 | ENDINTERFACE. 56 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_avoid_test_seam.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/test_avoid_test_seam definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | protected section. 8 | private section. 9 | methods without_pseudo_comments. 10 | methods with_pseudo_comments. 11 | endclass. 12 | 13 | 14 | 15 | class /cc4a/test_avoid_test_seam implementation. 16 | method without_pseudo_comments. 17 | test-seam abc. 18 | data(a) = 1. 19 | end-test-seam. 20 | 21 | data b type standard table of i. 22 | 23 | loop at b assigning field-symbol(). 24 | if < 2. 25 | test-seam hij. 26 | end-test-seam. 27 | endif. 28 | endloop. 29 | 30 | if 1 = 2. 31 | if 1 = 3. 32 | if 3 = 2. 33 | test-seam rtz. 34 | end-test-seam. 35 | endif. 36 | endif. 37 | endif. 38 | endmethod. 39 | 40 | method with_pseudo_comments. 41 | test-seam opl. "#EC TEST_SEAM_USAGE 42 | data(a) = 1. 43 | end-test-seam. 44 | 45 | data b type standard table of i. 46 | 47 | loop at b assigning field-symbol(). 48 | if < 2. 49 | test-seam qwe. "#EC TEST_SEAM_USAGE 50 | end-test-seam. 51 | endif. 52 | endloop. 53 | 54 | if 1 = 2. 55 | if 1 = 3. 56 | if 3 = 2. 57 | test-seam tzu. "#EC TEST_SEAM_USAGE 58 | end-test-seam. 59 | endif. 60 | endif. 61 | endif. 62 | endmethod. 63 | 64 | endclass. 65 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_rap_unamanaged.bdef.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_RAP_UNAMANAGED 7 | BDEF/BDO 8 | Test RAP unmanaged 9 | 60 10 | EN 11 | 12 | 13 | ./%2Fcc4a%2Ftest_rap_unamanaged/source/main/versions 14 | http://www.sap.com/adt/relations/versions 15 | Historic versions 16 | 17 | 18 | ./%2Fcc4a%2Ftest_rap_unamanaged/source/main 19 | http://www.sap.com/adt/relations/source 20 | text/plain 21 | Source Content 22 | 23 | 24 | ./%2Fcc4a%2Ftest_rap_unamanaged/source/main 25 | http://www.sap.com/adt/relations/source 26 | text/html 27 | Source Content (HTML) 28 | 29 | 30 | EN 31 | 5 32 | ./%2Fcc4a%2Ftest_rap_unamanaged/source/main 33 | ABAP_SOURCE 34 | true 35 | true 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/checks/#cc4a#proper_bool_expression.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/PROPER_BOOL_EXPRESSION 7 | E 8 | Use proper boolean expression 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | BOL 19 | 'X', ' ', or SPACE can be replaced by ABAP_TRUE or ABAP_FALSE 20 | 122 21 | 22 | 23 | I 24 | DES 25 | Standard boolean expressions 26 | 88 27 | 28 | 29 | I 30 | INI 31 | IS (NOT) INITIAL can be replaced by comparison with ABAP_BOOL 32 | 122 33 | 34 | 35 | I 36 | QCE 37 | Replace literal with ABAP_TRUE or ABAP_FALSE 38 | 66 39 | 40 | 41 | I 42 | QIB 43 | Replace with comparison to ABAP_TRUE or ABAP_FALSE 44 | 62 45 | 46 | 47 | I 48 | QIE 49 | Replace with call to XSDBOOL 50 | 40 51 | 52 | 53 | I 54 | XSD 55 | IF...ENDIF block can be replaced by inline XSDBOOL( ) 56 | 106 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/core/(cc4a)code_pal_remote.chkv.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "Remote CodePal checks", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "selectedChecks": [ 9 | { 10 | "checkName": "/CC4A/PREFER_IS_NOT" 11 | }, 12 | { 13 | "checkName": "/CC4A/ASSIGNMENT_CHAINING" 14 | }, 15 | { 16 | "checkName": "/CC4A/AVOID_DB_ACCESS_IN_AUNIT" 17 | }, 18 | { 19 | "checkName": "/CC4A/AVOID_TEST_SEAM" 20 | }, 21 | { 22 | "checkName": "/CC4A/CHAIN_DECLARATIONS" 23 | }, 24 | { 25 | "checkName": "/CC4A/CONSTANTS_INTERFACE" 26 | }, 27 | { 28 | "checkName": "/CC4A/AVOID_SELF_REFERENCE" 29 | }, 30 | { 31 | "checkName": "/CC4A/AVOID_DEFAULT_KEY" 32 | }, 33 | { 34 | "checkName": "/CC4A/METHOD_SIGNATURE", 35 | "parameters": [ 36 | { 37 | "name": "CheckPubMethodNoInterface", 38 | "value": "true" 39 | }, 40 | { 41 | "name": "CheckInputParamBoolean", 42 | "value": "true" 43 | }, 44 | { 45 | "name": "CheckInputParamOptional", 46 | "value": "true" 47 | }, 48 | { 49 | "name": "CheckOutputParamNumber", 50 | "value": "true" 51 | }, 52 | { 53 | "name": "CheckOutputParamType", 54 | "value": "true" 55 | }, 56 | { 57 | "name": "CheckRetParamNotNamedResult", 58 | "value": "true" 59 | }, 60 | { 61 | "name": "CheckExpParamNumberNotOne", 62 | "value": "true" 63 | } 64 | ] 65 | }, 66 | { 67 | "checkName": "/CC4A/CHECK_IN_ITERATION" 68 | }, 69 | { 70 | "checkName": "/CC4A/PROPER_BOOL_USAGE" 71 | }, 72 | { 73 | "checkName": "/CC4A/MODERN" 74 | }, 75 | { 76 | "checkName": "/CC4A/VARIABLE_SCOPE" 77 | } 78 | ] 79 | } 80 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_db.tabl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_DB 7 | E 8 | TRANSP 9 | X 10 | Database Table for testing checks 11 | E 12 | A 13 | 1 14 | 15 | 16 | /CC4A/TEST_DB 17 | A 18 | 0 19 | APPL0 20 | N 21 | 22 | 23 | 24 | USER_ID 25 | X 26 | 0 27 | C 28 | 000006 29 | X 30 | CLNT 31 | 000003 32 | CLNT 33 | 34 | 35 | FIRST_NAME 36 | 0 37 | g 38 | 000008 39 | SSTR 40 | 000030 41 | SSTR 42 | 43 | 44 | LAST_NAME 45 | 0 46 | g 47 | 000008 48 | SSTR 49 | 000030 50 | SSTR 51 | 52 | 53 | AGE 54 | 0 55 | X 56 | 000001 57 | INT1 58 | 000003 59 | INT1 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/checks/#cc4a#method_signature.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/METHOD_SIGNATURE 7 | E 8 | Message Signature 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | DS1 19 | Findings regarding method signature. 20 | 132 21 | 22 | 23 | I 24 | PC1 25 | Method with more than one output parameter type 26 | 132 27 | 28 | 29 | I 30 | PC2 31 | Method with more than one output parameter 32 | 132 33 | 34 | 35 | I 36 | PC3 37 | Method with importing parameter of type boolean 38 | 132 39 | 40 | 41 | I 42 | PC4 43 | Method with optional importing parameter 44 | 132 45 | 46 | 47 | I 48 | PC5 49 | Public instance method which is not part of an interface 50 | 132 51 | 52 | 53 | I 54 | PC6 55 | Method with one exporting parameter 56 | 132 57 | 58 | 59 | I 60 | PC7 61 | Returning Parameter of method not named RESULT 62 | 132 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/core/(cc4a)code_pal_full.chkv.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": "1", 3 | "header": { 4 | "description": "All CodePal checks", 5 | "originalLanguage": "en", 6 | "abapLanguageVersion": "cloudDevelopment" 7 | }, 8 | "selectedChecks": [ 9 | { 10 | "checkName": "/CC4A/PREFER_IS_NOT" 11 | }, 12 | { 13 | "checkName": "/CC4A/ASSIGNMENT_CHAINING" 14 | }, 15 | { 16 | "checkName": "/CC4A/AVOID_DB_ACCESS_IN_AUNIT" 17 | }, 18 | { 19 | "checkName": "/CC4A/AVOID_TEST_SEAM" 20 | }, 21 | { 22 | "checkName": "/CC4A/CHAIN_DECLARATIONS" 23 | }, 24 | { 25 | "checkName": "/CC4A/CONSTANTS_INTERFACE" 26 | }, 27 | { 28 | "checkName": "/CC4A/AVOID_SELF_REFERENCE" 29 | }, 30 | { 31 | "checkName": "/CC4A/AVOID_DEFAULT_KEY" 32 | }, 33 | { 34 | "checkName": "/CC4A/METHOD_SIGNATURE", 35 | "parameters": [ 36 | { 37 | "name": "CheckPubMethodNoInterface", 38 | "value": "true" 39 | }, 40 | { 41 | "name": "CheckInputParamBoolean", 42 | "value": "true" 43 | }, 44 | { 45 | "name": "CheckInputParamOptional", 46 | "value": "true" 47 | }, 48 | { 49 | "name": "CheckOutputParamNumber", 50 | "value": "true" 51 | }, 52 | { 53 | "name": "CheckOutputParamType", 54 | "value": "true" 55 | }, 56 | { 57 | "name": "CheckRetParamNotNamedResult", 58 | "value": "true" 59 | }, 60 | { 61 | "name": "CheckExpParamNumberNotOne", 62 | "value": "true" 63 | } 64 | ] 65 | }, 66 | { 67 | "checkName": "/CC4A/PREFER_METHODS" 68 | }, 69 | { 70 | "checkName": "/CC4A/CHECK_IN_ITERATION" 71 | }, 72 | { 73 | "checkName": "/CC4A/PROPER_BOOL_USAGE" 74 | }, 75 | { 76 | "checkName": "/CC4A/MODERN" 77 | }, 78 | { 79 | "checkName": "/CC4A/VARIABLE_SCOPE" 80 | } 81 | ] 82 | } 83 | -------------------------------------------------------------------------------- /src/checks/#cc4a#prefer_methods.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | class test definition final for testing 2 | duration short 3 | risk level harmless. 4 | 5 | private section. 6 | constants test_class type c length 30 value '/CC4A/TEST_PREFER_METHODS'. 7 | constants form_finding_class type c length 30 value '/CC4A/SAPLTEST_PREFER_METHODS'. 8 | constants method_finding_class type c length 30 value '/CC4A/LTEST_PREFER_METHODS$01'. 9 | methods execute_test_class for testing raising cx_static_check. 10 | endclass. 11 | 12 | class test implementation. 13 | method execute_test_class. 14 | 15 | data(form_finding_1) = value if_ci_atc_check=>ty_location( 16 | object = value #( name = form_finding_class type = `PROG` ) 17 | position = value #( line = 17 column = 0 ) ). 18 | 19 | data(methods_finding_1) = value if_ci_atc_check=>ty_location( 20 | object = value #( name = method_finding_class type = `PROG` ) 21 | position = value #( line = 1 column = 0 ) ). 22 | 23 | data(form_finding_1_pseudo) = value if_ci_atc_check=>ty_location( 24 | object = value #( name = form_finding_class type = `PROG` ) 25 | position = value #( line = 22 column = 0 ) ). 26 | 27 | cl_ci_atc_unit_driver=>create_asserter( )->check_and_assert( 28 | check = new /cc4a/prefer_methods( ) 29 | object = value #( type = 'FUGR' name = test_class ) 30 | expected_findings = value #( 31 | ( 32 | location = form_finding_1 33 | code = /cc4a/prefer_methods=>finding_codes-avoid_form 34 | ) 35 | ( 36 | location = methods_finding_1 37 | code = /cc4a/prefer_methods=>finding_codes-prefer_methods 38 | ) 39 | ( 40 | location = form_finding_1_pseudo 41 | code = /cc4a/prefer_methods=>finding_codes-avoid_form 42 | ) 43 | ) 44 | asserter_config = value #( quickfixes = abap_false ) ). 45 | endmethod. 46 | endclass. 47 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_avoid_default_key.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/test_avoid_default_key definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | protected section. 8 | private section. 9 | class-methods static_findings. 10 | methods with_pseudo_comments. 11 | methods without_pseudo_comments. 12 | 13 | types: 14 | begin of ty_struct, 15 | comp1 type i, 16 | comp2 type string, 17 | end of ty_struct. 18 | 19 | class-data abc type table of ty_struct with default key. 20 | class-data def type table of ty_struct with empty key. 21 | class-data ghi type table of ty_struct with default key. "#EC DEFAULT_KEY 22 | ENDCLASS. 23 | 24 | 25 | 26 | CLASS /CC4A/TEST_AVOID_DEFAULT_KEY IMPLEMENTATION. 27 | 28 | 29 | method with_pseudo_comments. 30 | data mno type table of ty_struct with empty key. 31 | data pqr type table of ty_struct with empty key. 32 | data stu type table of ty_struct with default key. "#EC DEFAULT_KEY 33 | 34 | types: begin of type1, 35 | vwx type standard table of ty_struct with non-unique key comp2, 36 | yza type standard table of i with default key, "#EC DEFAULT_KEY 37 | bcd type standard table of string with empty key, 38 | end of type1. 39 | 40 | data with. 41 | types: 42 | begin of ty_malicious, 43 | with type i, 44 | default type i, 45 | key type i, 46 | end of ty_malicious. 47 | types ty_table type sorted table of ty_malicious with unique key !with default key. 48 | endmethod. 49 | 50 | 51 | method without_pseudo_comments. 52 | data mno type table of ty_struct with empty key. 53 | data pqr type table of ty_struct with empty key. 54 | data stu type table of ty_struct with default key. 55 | 56 | types: begin of type1, 57 | vwx type standard table of ty_struct with non-unique key comp2, 58 | yza type standard table of i with default key, 59 | bcd type standard table of string with empty key, 60 | end of type1. 61 | endmethod. 62 | 63 | 64 | method static_findings. 65 | statics memo type standard table of string with default key. "#EC DEFAULT_KEY 66 | statics mamo type standard table of string with default key. 67 | endmethod. 68 | ENDCLASS. 69 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#bp_test_rap_unamanaged.clas.locals_imp.abap: -------------------------------------------------------------------------------- 1 | class lhc_test_rap_unamanaged definition inheriting from cl_abap_behavior_handler. 2 | private section. 3 | 4 | methods get_instance_authorizations for instance authorization 5 | importing keys request requested_authorizations for /cc4a/test_rap_unamanaged result result. 6 | 7 | methods create for modify 8 | importing entities for create /cc4a/test_rap_unamanaged 9 | changing mapped type data 10 | failed type data 11 | reported type data. 12 | 13 | methods update for modify 14 | importing entities for update /cc4a/test_rap_unamanaged 15 | changing mapped type data 16 | failed type data 17 | reported type data. 18 | 19 | methods delete for modify 20 | importing keys for delete /cc4a/test_rap_unamanaged. 21 | 22 | methods read for read 23 | importing keys for read /cc4a/test_rap_unamanaged result result 24 | changing failed type data 25 | reported type data. 26 | 27 | methods lock for lock 28 | importing keys for lock /cc4a/test_rap_unamanaged 29 | changing failed type data 30 | reported type data. 31 | 32 | methods this_is_a_custom_method 33 | changing mapped type data 34 | failed type data 35 | reported type data. 36 | 37 | endclass. 38 | 39 | class lhc_test_rap_unamanaged implementation. 40 | 41 | method get_instance_authorizations. 42 | endmethod. 43 | 44 | method create. 45 | endmethod. 46 | 47 | method update. 48 | endmethod. 49 | 50 | method delete. 51 | endmethod. 52 | 53 | method read. 54 | endmethod. 55 | 56 | method lock. 57 | endmethod. 58 | 59 | method this_is_a_custom_method. 60 | 61 | endmethod. 62 | 63 | endclass. 64 | 65 | class lsc_test_rap_unamanaged definition inheriting from cl_abap_behavior_saver. 66 | protected section. 67 | 68 | methods finalize redefinition. 69 | 70 | methods check_before_save redefinition. 71 | 72 | methods save redefinition. 73 | 74 | methods cleanup redefinition. 75 | 76 | methods cleanup_finalize redefinition. 77 | 78 | endclass. 79 | 80 | class lsc_test_rap_unamanaged implementation. 81 | 82 | method finalize. 83 | endmethod. 84 | 85 | method check_before_save. 86 | endmethod. 87 | 88 | method save. 89 | endmethod. 90 | 91 | method cleanup. 92 | endmethod. 93 | 94 | method cleanup_finalize. 95 | endmethod. 96 | 97 | endclass. 98 | -------------------------------------------------------------------------------- /src/checks/#cc4a#scope_of_variable.clas.locals_imp.abap: -------------------------------------------------------------------------------- 1 | class block_finder implementation. 2 | method constructor. 3 | me->first_valid_block = first_valid_block. 4 | me->blocks = blocks. 5 | endmethod. 6 | 7 | method find_parent_branch. 8 | result-block = block. 9 | while result-block <> first_valid_block. 10 | data(current_block) = blocks[ result-block ]. 11 | case current_block-type. 12 | when if_ci_atc_source_code_provider=>block_type-alternation 13 | or if_ci_atc_source_code_provider=>block_type-iteration 14 | or if_ci_atc_source_code_provider=>block_type-condition. 15 | return. 16 | 17 | when others. 18 | if current_block-statement_type = if_ci_atc_source_code_provider=>statement_type-inject. 19 | result-inside_injection = abap_true. 20 | endif. 21 | result-block = current_block-parent. 22 | 23 | endcase. 24 | endwhile. 25 | endmethod. 26 | 27 | method find_outer_block. 28 | if line_exists( blocks[ table_line = first_valid_block ] ). 29 | result = first_valid_block. 30 | return. 31 | endif. 32 | result = blocks[ 1 ]. 33 | loop at blocks from 2 into data(block_no). 34 | result = least_common_parent( block_1 = result block_2 = block_no ). 35 | if result = first_valid_block. 36 | return. 37 | endif. 38 | endloop. 39 | if me->blocks[ result ]-type = if_ci_atc_source_code_provider=>block_type-sequence. 40 | result = me->blocks[ result ]-parent. 41 | endif. 42 | endmethod. 43 | 44 | method least_common_parent. 45 | if block_1 = first_valid_block or block_2 = first_valid_block. 46 | result = first_valid_block. 47 | elseif block_1 = block_2. 48 | result = block_1. 49 | elseif blocks[ block_1 ]-parent = blocks[ block_2 ]-parent. 50 | result = blocks[ block_1 ]-parent. 51 | else. 52 | if is_parent( parent = block_1 child = block_2 ) = abap_true. 53 | result = block_1. 54 | elseif is_parent( parent = block_2 child = block_1 ) = abap_true. 55 | result = block_2. 56 | else. 57 | result = least_common_parent( block_1 = value #( blocks[ block_1 ]-parent ) 58 | block_2 = value #( blocks[ block_2 ]-parent ) ). 59 | endif. 60 | endif. 61 | endmethod. 62 | 63 | method is_parent. 64 | result = abap_false. 65 | if parent = first_valid_block. 66 | result = abap_true. 67 | else. 68 | data(p) = blocks[ child ]-parent. 69 | while p <> first_valid_block and p <> parent. 70 | p = blocks[ p ]-parent. 71 | endwhile. 72 | if p = parent. 73 | result = abap_true. 74 | endif. 75 | endif. 76 | endmethod. 77 | endclass. 78 | -------------------------------------------------------------------------------- /src/checks/#cc4a#avoid_test_seam.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/avoid_test_seam definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | interfaces if_ci_atc_check. 8 | 9 | constants: 10 | begin of finding_codes, 11 | test_seam type if_ci_atc_check=>ty_finding_code value 'TESTSEAMUS', 12 | end of finding_codes. 13 | 14 | methods constructor. 15 | 16 | protected section. 17 | private section. 18 | constants pseudo_comment type string value 'TEST_SEAM_USAGE'. 19 | 20 | data code_provider type ref to if_ci_atc_source_code_provider. 21 | data assistant_factory type ref to cl_ci_atc_assistant_factory. 22 | data meta_data type ref to /cc4a/if_check_meta_data. 23 | 24 | methods analyze_procedure 25 | importing procedure type if_ci_atc_source_code_provider=>ty_procedure 26 | returning value(findings) type if_ci_atc_check=>ty_findings. 27 | ENDCLASS. 28 | 29 | 30 | 31 | CLASS /CC4A/AVOID_TEST_SEAM IMPLEMENTATION. 32 | 33 | 34 | method analyze_procedure. 35 | loop at procedure-statements assigning field-symbol() where keyword eq 'TEST-SEAM' ##PRIMKEY[KEYWORD]. 36 | insert value #( code = finding_codes-test_seam 37 | location = code_provider->get_statement_location( ) 38 | checksum = code_provider->get_statement_checksum( ) 39 | has_pseudo_comment = meta_data->has_valid_pseudo_comment( 40 | statement = 41 | finding_code = finding_codes-test_seam ) 42 | ) into table findings. 43 | endloop. 44 | endmethod. 45 | 46 | 47 | method if_ci_atc_check~get_meta_data. 48 | meta_data = me->meta_data. 49 | endmethod. 50 | 51 | method constructor. 52 | meta_data = /cc4a/check_meta_data=>create( 53 | value #( checked_types = /cc4a/check_meta_data=>checked_types-abap_programs 54 | description = 'Usage of TEST-SEAM'(des) 55 | remote_enablement = /cc4a/check_meta_data=>remote_enablement-unconditional 56 | finding_codes = value #( 57 | ( code = finding_codes-test_seam pseudo_comment = pseudo_comment text = 'Usage of TEST-SEAM'(uot) ) ) ) ). 58 | endmethod. 59 | 60 | 61 | method if_ci_atc_check~run. 62 | code_provider = data_provider->get_code_provider( ). 63 | data(procedures) = code_provider->get_procedures( code_provider->object_to_comp_unit( object ) ). 64 | loop at procedures->* assigning field-symbol(). 65 | insert lines of analyze_procedure( ) into table findings. 66 | endloop. 67 | endmethod. 68 | 69 | 70 | method if_ci_atc_check~set_assistant_factory. 71 | assistant_factory = factory. 72 | endmethod. 73 | 74 | 75 | method if_ci_atc_check~verify_prerequisites. 76 | 77 | endmethod. 78 | ENDCLASS. 79 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_avoid_self_ref.clas.locals_imp.abap: -------------------------------------------------------------------------------- 1 | *"* use this source file for the definition and implementation of 2 | *"* local helper classes, interface definitions and type 3 | *"* declarations 4 | class lz_self_reference definition 5 | create public . 6 | 7 | public section. 8 | data att1 type i. 9 | data att2 type string. 10 | data att3 type c. 11 | methods m1 importing att1 type i. 12 | methods m2 changing att3 type c. 13 | methods m3 returning value(att4) type string. 14 | protected section. 15 | data att5 type string. 16 | private section. 17 | data att4 type i. 18 | endclass. 19 | 20 | 21 | 22 | class lz_self_reference implementation. 23 | method m1. 24 | 25 | endmethod. 26 | 27 | method m2. 28 | data att2 type f. 29 | me->att2 = 'Hugo'. 30 | att2 = '1.2'. 31 | me->att3 = 'Hugo'. 32 | me->att4 = 7. 33 | endmethod. 34 | 35 | method m3. 36 | me->att4 = 5. 37 | me->att1 = 2. 38 | att4 = 'HUHU'. 39 | endmethod. 40 | 41 | endclass. 42 | 43 | class lz_self_reference2 definition inheriting from lz_self_reference. 44 | public section. 45 | methods m2 redefinition. 46 | methods m3 redefinition. 47 | private section. 48 | data att7 type c. 49 | 50 | endclass. 51 | 52 | class lz_self_reference2 implementation. 53 | 54 | method m2. 55 | data att2 type f. 56 | me->att2 = 'Hugo'. 57 | att2 = '1.2'. 58 | me->att3 = 'Hugo'. 59 | endmethod. 60 | 61 | method m3. 62 | data att7 type string. 63 | me->att5 = 5. 64 | me->att1 = 2. 65 | att4 = 'HUHU'. 66 | 67 | final(att8) = 5. 68 | 69 | endmethod. 70 | 71 | endclass. 72 | 73 | class impl_interface definition. 74 | public section. 75 | interfaces /cc4a/if_test_avoid_self_ref. 76 | private section. 77 | data var_1 type i. 78 | endclass. 79 | 80 | class impl_interface implementation. 81 | 82 | method /cc4a/if_test_avoid_self_ref~meth_1. 83 | me->var_1 = var_1. 84 | endmethod. 85 | 86 | endclass. 87 | 88 | class inheriting_from_global definition inheriting from /cc4a/test_avoid_self_ref_sup. 89 | public section. 90 | methods super_meth redefinition. 91 | private section. 92 | data imp type i. 93 | endclass. 94 | 95 | CLASS inheriting_from_global IMPLEMENTATION. 96 | 97 | METHOD super_meth. 98 | me->imp = imp. 99 | ENDMETHOD. 100 | 101 | ENDCLASS. 102 | 103 | interface local_interface. 104 | methods meth_1 105 | importing par_1 type i. 106 | methods meth_2. 107 | endinterface. 108 | 109 | class impl_local_interface definition. 110 | public section. 111 | interfaces local_interface. 112 | endclass. 113 | 114 | CLASS impl_local_interface IMPLEMENTATION. 115 | 116 | METHOD local_interface~meth_1. 117 | 118 | ENDMETHOD. 119 | 120 | METHOD local_interface~meth_2. 121 | 122 | ENDMETHOD. 123 | 124 | ENDCLASS. 125 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_rap.tabl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TEST_RAP 7 | E 8 | TRANSP 9 | X 10 | Database Table for Root Entity of RAP BO 11 | E 12 | X 13 | A 14 | 1 15 | 16 | 17 | /CC4A/TEST_RAP 18 | A 19 | 0 20 | APPL0 21 | N 22 | Q 23 | 24 | 25 | 26 | CLIENT 27 | X 28 | MANDT 29 | 0 30 | X 31 | E 32 | 33 | 34 | KEY_FIELD 35 | X 36 | 0 37 | X 38 | 000004 39 | X 40 | INT4 41 | 000010 42 | INT4 43 | 44 | 45 | DATA_FIELD 46 | 0 47 | g 48 | 000008 49 | STRG 50 | STRG 51 | 52 | 53 | CHAR_FIELD 54 | 0 55 | C 56 | 000050 57 | CHAR 58 | 000025 59 | CHAR 60 | 61 | 62 | CHAR_FIELD_2 63 | 0 64 | C 65 | 000050 66 | CHAR 67 | 000025 68 | CHAR 69 | 70 | 71 | DEC_FIELD 72 | 0 73 | P 74 | 000008 75 | DEC 76 | 000015 77 | 000002 78 | DEC 79 | 80 | 81 | CREA_DATE_TIME 82 | TIMESTAMPL 83 | 0 84 | E 85 | 86 | 87 | LCHG_DATE_TIME 88 | TIMESTAMPL 89 | 0 90 | E 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /src/checks/#cc4a#check_constant_interface.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | class ltcl_ definition final for testing 2 | duration short 3 | risk level harmless. 4 | 5 | private section. 6 | constants: 7 | begin of co_test_object, 8 | object_type_1 type if_ci_atc_check=>ty_object-type value 'CLAS', 9 | object_name_1 type if_ci_atc_check=>ty_object-name value '/CC4A/TEST_CHECK_CONSTANT_IF1', 10 | object_type_2 type if_ci_atc_check=>ty_object-type value 'INTF', 11 | object_name_2 type if_ci_atc_check=>ty_object-name value '/CC4A/TEST_CHECK_CONSTANT_IF2', 12 | end of co_test_object. 13 | 14 | methods: 15 | run_test_local_intf for testing raising cx_static_check, 16 | run_test_global_intf for testing raising cx_static_check. 17 | 18 | endclass. 19 | 20 | 21 | class ltcl_ implementation. 22 | 23 | method run_test_global_intf. 24 | 25 | " Location of expected findings 26 | data(finding_1_loc) = value if_ci_atc_check=>ty_location( 27 | object = value #( name = '/CC4A/TEST_CHECK_CONSTANT_IF2=IU' type = 'PROG' ) 28 | position = value #( line = 1 column = 0 ) ). 29 | 30 | cl_ci_atc_unit_driver=>create_asserter( )->check_and_assert( 31 | check = new /cc4a/check_constant_interface( ) 32 | object = value #( name = co_test_object-object_name_2 33 | type = co_test_object-object_type_2 ) 34 | asserter_config = value #( quickfixes = abap_false 35 | remove_findings_with_pcoms = abap_true ) 36 | expected_findings = value #( ( code = /cc4a/check_constant_interface=>finding_codes-cons_intf 37 | location = finding_1_loc ) ) ). 38 | 39 | endmethod. 40 | 41 | 42 | method run_test_local_intf. 43 | 44 | " Location of expected findings 45 | data(finding_1_loc) = value if_ci_atc_check=>ty_location( 46 | object = value #( name = '/CC4A/TEST_CHECK_CONSTANT_IF1=CCIMP' type = 'PROG' ) 47 | position = value #( line = 4 column = 0 ) ). 48 | data(finding_2_loc) = value if_ci_atc_check=>ty_location( 49 | object = value #( name = '/CC4A/TEST_CHECK_CONSTANT_IF1=CCIMP' type = 'PROG' ) 50 | position = value #( line = 17 column = 0 ) ). 51 | " Finding 3 should not appear due to the pseudo comment 52 | 53 | cl_ci_atc_unit_driver=>create_asserter( )->check_and_assert( 54 | check = new /cc4a/check_constant_interface( ) 55 | object = value #( name = co_test_object-object_name_1 56 | type = co_test_object-object_type_1 ) 57 | asserter_config = value #( quickfixes = abap_false 58 | remove_findings_with_pcoms = abap_true ) 59 | expected_findings = value #( ( code = /cc4a/check_constant_interface=>finding_codes-cons_intf 60 | location = finding_1_loc ) 61 | ( code = /cc4a/check_constant_interface=>finding_codes-cons_intf 62 | location = finding_2_loc ) ) ). 63 | 64 | endmethod. 65 | 66 | endclass. 67 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_check_in_iteration.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/test_check_in_iteration definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | protected section. 8 | private section. 9 | methods without_pseudo_comments. 10 | methods with_pseudo_comments. 11 | 12 | types: begin of ty_table, 13 | delflag type abap_bool, 14 | end of ty_table. 15 | 16 | data itab_range type range of ty_table. 17 | ENDCLASS. 18 | 19 | 20 | 21 | CLASS /CC4A/TEST_CHECK_IN_ITERATION IMPLEMENTATION. 22 | 23 | 24 | method without_pseudo_comments. 25 | " Checks with do 26 | do 10 times. 27 | check 1 = 1. 28 | enddo. 29 | 30 | data(a) = 125. 31 | data(b) = 250. 32 | 33 | do 10 times. 34 | if abap_true = abap_true. 35 | if 1 = 3. 36 | check a = b. 37 | else. 38 | check b = 3. 39 | endif. 40 | endif. 41 | enddo. 42 | 43 | " Checks with while 44 | data(x) = 5. 45 | data(y) = 15. 46 | 47 | while abap_true = abap_false. 48 | check x = y. 49 | 50 | if 3 = 3. 51 | check x <> 150. 52 | endif. 53 | endwhile. 54 | 55 | " Check with loop 56 | types: begin of ty_table, 57 | delflag type abap_bool, 58 | end of ty_table. 59 | 60 | data itab type table of ty_table with empty key. 61 | loop at itab assigning field-symbol(). 62 | check -delflag = abap_true. 63 | if a = x. 64 | check -delflag <= abap_false. 65 | endif. 66 | endloop. 67 | 68 | " Checks that shouldn't show quickfixes 69 | check a = a. 70 | 71 | if a = 3. 72 | check b = a. 73 | endif. 74 | 75 | " Some special cases 76 | 77 | loop at itab into data(tab). 78 | check abap_false = tab-delflag. 79 | endloop. 80 | 81 | loop at itab assigning . 82 | check -delflag = abap_true. 83 | check xsdbool( 1 > 3 ) = abap_true. 84 | endloop. 85 | 86 | 87 | loop at itab assigning . 88 | check in itab_range. 89 | endloop. 90 | 91 | endmethod. 92 | 93 | 94 | method with_pseudo_comments. 95 | 96 | data(a) = 55. 97 | 98 | if 3 = 2. 99 | while 3 = a * 2. 100 | check a = a. "#EC CHECK_IN_ITERATION 101 | endwhile. 102 | endif. 103 | 104 | do a times. 105 | if a = 3. 106 | check 55 = a. "#EC CHECK_IN_ITERATION 107 | endif. 108 | enddo. 109 | 110 | types: begin of ty_table, 111 | delflag type string, 112 | end of ty_table. 113 | 114 | data itab type table of ty_table with empty key. 115 | while a = 1. 116 | do a times. 117 | loop at itab assigning field-symbol(). 118 | check -delflag = abap_true. "#EC CHECK_IN_ITERATION 119 | if a = a / 2. 120 | check -delflag = abap_false. "#EC CHECK_IN_ITERATION 121 | endif. 122 | endloop. 123 | enddo. 124 | endwhile. 125 | endmethod. 126 | ENDCLASS. 127 | -------------------------------------------------------------------------------- /src/checks/#cc4a#avoid_test_seam.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | class test definition final for testing 2 | duration short 3 | risk level harmless. 4 | 5 | private section. 6 | constants test_class type c length 30 value '/CC4A/TEST_AVOID_TEST_SEAM'. 7 | constants: 8 | begin of test_class_methods, 9 | without_pseudo_comments type c length 30 value 'WITHOUT_PSEUDO_COMMENTS', 10 | with_pseudo_comments type c length 30 value 'WITH_PSEUDO_COMMENTS', 11 | end of test_class_methods. 12 | 13 | methods execute_test_class for testing raising cx_static_check. 14 | endclass. 15 | 16 | class test implementation. 17 | method execute_test_class. 18 | 19 | data(without_pseudo_comment_1) = value if_ci_atc_check=>ty_location( 20 | object = cl_ci_atc_unit_driver=>get_method_object( 21 | value #( class = test_class method = test_class_methods-without_pseudo_comments ) ) 22 | position = value #( line = 2 column = 4 ) ). 23 | data(without_pseudo_comment_2) = value if_ci_atc_check=>ty_location( 24 | object = cl_ci_atc_unit_driver=>get_method_object( 25 | value #( class = test_class method = test_class_methods-without_pseudo_comments ) ) 26 | position = value #( line = 10 column = 8 ) ). 27 | data(without_pseudo_comment_3) = value if_ci_atc_check=>ty_location( 28 | object = cl_ci_atc_unit_driver=>get_method_object( 29 | value #( class = test_class method = test_class_methods-without_pseudo_comments ) ) 30 | position = value #( line = 18 column = 10 ) ). 31 | 32 | data(with_pseudo_comment_1) = value if_ci_atc_check=>ty_location( 33 | object = cl_ci_atc_unit_driver=>get_method_object( 34 | value #( class = test_class method = test_class_methods-with_pseudo_comments ) ) 35 | position = value #( line = 2 column = 4 ) ). 36 | data(with_pseudo_comment_2) = value if_ci_atc_check=>ty_location( 37 | object = cl_ci_atc_unit_driver=>get_method_object( 38 | value #( class = test_class method = test_class_methods-with_pseudo_comments ) ) 39 | position = value #( line = 10 column = 8 ) ). 40 | data(with_pseudo_comment_3) = value if_ci_atc_check=>ty_location( 41 | object = cl_ci_atc_unit_driver=>get_method_object( 42 | value #( class = test_class method = test_class_methods-with_pseudo_comments ) ) 43 | position = value #( line = 18 column = 10 ) ). 44 | 45 | cl_ci_atc_unit_driver=>create_asserter( )->check_and_assert( 46 | check = new /cc4a/avoid_test_seam( ) 47 | object = value #( type = 'CLASS' name = test_class ) 48 | expected_findings = value #( code = /cc4a/avoid_test_seam=>finding_codes-test_seam 49 | ( location = without_pseudo_comment_1 ) 50 | ( location = without_pseudo_comment_2 ) 51 | ( location = without_pseudo_comment_3 ) 52 | ( location = with_pseudo_comment_1 ) 53 | ( location = with_pseudo_comment_2 ) 54 | ( location = with_pseudo_comment_3 ) ) 55 | asserter_config = value #( quickfixes = abap_false ) ). 56 | endmethod. 57 | 58 | endclass. 59 | -------------------------------------------------------------------------------- /src/checks/#cc4a#modern_language.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/MODERN_LANGUAGE 7 | E 8 | check for modern language 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | I 18 | 001 19 | MOVE is obsolete 20 | 26 21 | 22 | 23 | I 24 | 002 25 | TRANSLATE TO UPPER/LOWERCASE is obsolete 26 | 80 27 | 28 | 29 | I 30 | 003 31 | Prefer LINE_EXISTS/LINE_INDEX 32 | 50 33 | 34 | 35 | I 36 | 004 37 | Prefer NEW instead of CREATE OBJECT 38 | 70 39 | 40 | 41 | I 42 | 005 43 | Prefer functional call instead of CALL METHOD 44 | 90 45 | 46 | 47 | I 48 | 006 49 | Omit EXPORTING in functional Method Call if possible 50 | 104 51 | 52 | 53 | I 54 | 007 55 | Do not use RECEIVING in functional Method Call if possible 56 | 116 57 | 58 | 59 | I 60 | 008 61 | Use string templates instead of && 62 | 68 63 | 64 | 65 | I 66 | DES 67 | Modern Language 68 | 25 69 | 70 | 71 | I 72 | QF1 73 | Replace MOVE statement 74 | 44 75 | 76 | 77 | I 78 | QF2 79 | Replace TRANSLATE statement 80 | 54 81 | 82 | 83 | I 84 | QF3 85 | Use LINE_EXISTS/LINE_INDEX 86 | 52 87 | 88 | 89 | I 90 | QF4 91 | Use NEW instead of CREATE OBJECT 92 | 64 93 | 94 | 95 | I 96 | QF5 97 | Use functional call instead of CALL METHOD 98 | 84 99 | 100 | 101 | I 102 | QF6 103 | Omit EXPORTING 104 | 24 105 | 106 | 107 | I 108 | QF7 109 | Do not use EXPORTING/RECEIVING 110 | 60 111 | 112 | 113 | I 114 | QF8 115 | Replace && by string templates 116 | 60 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_modern_language.clas.locals_imp.abap: -------------------------------------------------------------------------------- 1 | CLASS lcx_error DEFINITION FINAL 2 | INHERITING FROM cx_static_check. 3 | ENDCLASS. 4 | 5 | CLASS lcx_error IMPLEMENTATION. 6 | ENDCLASS. 7 | 8 | CLASS lcl_test DEFINITION FINAL. 9 | PUBLIC SECTION. 10 | METHODS constructor 11 | IMPORTING param1 TYPE i 12 | param2 TYPE i ##NEEDED. 13 | METHODS test1 14 | IMPORTING param1 TYPE i 15 | RETURNING VALUE(result) TYPE i. 16 | METHODS test2 17 | IMPORTING param1 TYPE string 18 | EXPORTING param2 TYPE string 19 | CHANGING param3 TYPE string. 20 | METHODS test3 21 | IMPORTING param1 TYPE i 22 | RETURNING VALUE(result) TYPE i 23 | EXCEPTIONS error1 error2 ##NEEDED. 24 | METHODS test4 25 | IMPORTING param1 TYPE i 26 | param2 TYPE i 27 | param3 TYPE i 28 | EXPORTING param4 TYPE i. 29 | METHODS test5 30 | IMPORTING param1 TYPE string 31 | param2 TYPE string 32 | RETURNING VALUE(result) TYPE string. 33 | methods test6 34 | importing param type string 35 | returning value(result) type string. 36 | METHODS test7 37 | IMPORTING param1 TYPE i 38 | EXPORTING param2 TYPE i 39 | RETURNING VALUE(result) TYPE i. 40 | ENDCLASS. 41 | 42 | CLASS lcl_test IMPLEMENTATION. 43 | METHOD test1. 44 | result = param1. 45 | ENDMETHOD. 46 | METHOD test2. 47 | param2 = |{ param1 }{ param3 }|. 48 | CLEAR param3. 49 | ENDMETHOD. 50 | METHOD test3. 51 | IF param1 > 10. 52 | RAISE error1. 53 | ENDIF. 54 | result = param1 + 5. 55 | IF result < 0. 56 | RAISE error2. 57 | ENDIF. 58 | ENDMETHOD. 59 | METHOD test4. 60 | param4 = param1 + param2 + param3. 61 | ENDMETHOD. 62 | METHOD test5. 63 | result = |{ param1 } { param2 }|. 64 | ENDMETHOD. 65 | METHOD test6. 66 | result = |{ param } end|. 67 | ENDMETHOD. 68 | METHOD test7. 69 | result = param1 + 3. 70 | param2 = param1 + 5. 71 | ENDMETHOD. 72 | METHOD constructor ##NEEDED. 73 | ENDMETHOD. 74 | ENDCLASS. 75 | 76 | CLASS lcl_test1 DEFINITION FINAL. 77 | PUBLIC SECTION. 78 | METHODS constructor 79 | IMPORTING param1 TYPE i 80 | RAISING lcx_error. 81 | ENDCLASS. 82 | CLASS lcl_test1 IMPLEMENTATION. 83 | METHOD constructor. 84 | IF param1 <= 0. 85 | RAISE EXCEPTION TYPE lcx_error. 86 | ENDIF. 87 | ENDMETHOD. 88 | ENDCLASS. 89 | 90 | 91 | CLASS lcl_test2 DEFINITION FINAL. 92 | PUBLIC SECTION. 93 | METHODS constructor 94 | IMPORTING param1 TYPE i 95 | EXCEPTIONS error. 96 | ENDCLASS. 97 | CLASS lcl_test2 IMPLEMENTATION. 98 | METHOD constructor. 99 | IF param1 <= 0. 100 | RAISE error. 101 | ENDIF. 102 | ENDMETHOD. 103 | ENDCLASS. 104 | 105 | CLASS lcl_test3 DEFINITION FINAL. 106 | PUBLIC SECTION. 107 | METHODS constructor 108 | IMPORTING param1 TYPE string 109 | param2 TYPE string ##NEEDED. 110 | ENDCLASS. 111 | CLASS lcl_test3 IMPLEMENTATION. 112 | METHOD constructor ##NEEDED. 113 | ENDMETHOD. 114 | ENDCLASS. 115 | 116 | CLASS lcl_test_selfish DEFINITION FINAL. 117 | PUBLIC SECTION. 118 | METHODS constructor 119 | IMPORTING val TYPE i ##NEEDED. 120 | DATA my_val TYPE i. 121 | ENDCLASS. 122 | 123 | CLASS lcl_test_selfish IMPLEMENTATION. 124 | METHOD constructor ##NEEDED. 125 | ENDMETHOD. 126 | ENDCLASS. 127 | 128 | CLASS lcl_test4 DEFINITION FINAL. 129 | PUBLIC SECTION. 130 | METHODS test 131 | IMPORTING param TYPE abap_bool ##NEEDED. 132 | ENDCLASS. 133 | 134 | CLASS lcl_test4 IMPLEMENTATION. 135 | METHOD test ##NEEDED. 136 | ENDMETHOD. 137 | ENDCLASS. 138 | -------------------------------------------------------------------------------- /src/checks/#cc4a#prefer_methods.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/prefer_methods definition 2 | public 3 | final 4 | create public . 5 | public section. 6 | interfaces if_ci_atc_check. 7 | 8 | constants: 9 | begin of pseudo_comment, 10 | avoid_form type string value 'CI_FORM', 11 | end of pseudo_comment. 12 | 13 | constants: 14 | begin of finding_codes, 15 | avoid_form type if_ci_atc_check=>ty_finding_code value 'C_FORM', 16 | prefer_methods type if_ci_atc_check=>ty_finding_code value 'C_METHODS', 17 | end of finding_codes. 18 | 19 | methods constructor. 20 | protected section. 21 | private section. 22 | data code_provider type ref to if_ci_atc_source_code_provider. 23 | data assistant_factory type ref to cl_ci_atc_assistant_factory. 24 | data meta_data type ref to /cc4a/if_check_meta_data. 25 | 26 | methods analyze_procedure 27 | importing procedure type if_ci_atc_source_code_provider=>ty_procedure 28 | returning value(findings) type if_ci_atc_check=>ty_findings. 29 | 30 | methods function_is_rfc_enabled 31 | importing function_module type ref to if_xco_function_module 32 | returning value(is_rfc_enabled) type abap_bool. 33 | 34 | endclass. 35 | 36 | class /cc4a/prefer_methods implementation. 37 | 38 | method function_is_rfc_enabled. 39 | data(rfc_contract) = function_module->content( )->get_rfc_interface_contract( ). 40 | is_rfc_enabled = xsdbool( rfc_contract is not initial ). 41 | endmethod. 42 | 43 | method analyze_procedure. 44 | loop at procedure-statements assigning field-symbol() where keyword = `FORM` or keyword = `FUNCTION`. 45 | case -keyword. 46 | when `FUNCTION`. 47 | data(finding_code) = finding_codes-prefer_methods. 48 | data(function_module) = xco_cp_abap=>function_module( iv_name = |{ -tokens[ 2 ]-lexeme }| ). 49 | if function_is_rfc_enabled( function_module = function_module ). 50 | continue. 51 | endif. 52 | when `FORM`. 53 | finding_code = finding_codes-avoid_form. 54 | data(findings_pseudo_comment) = pseudo_comment-avoid_form. 55 | endcase. 56 | insert value #( code = finding_code 57 | location = code_provider->get_statement_location( ) 58 | checksum = code_provider->get_statement_checksum( ) 59 | has_pseudo_comment = meta_data->has_valid_pseudo_comment( statement = finding_code = finding_code ) 60 | parameters = value #( param_1 = -tokens[ 2 ]-lexeme ) 61 | ) into table findings. 62 | endloop. 63 | endmethod. 64 | 65 | method if_ci_atc_check~run. 66 | code_provider = data_provider->get_code_provider( ). 67 | data(procedures) = code_provider->get_procedures( code_provider->object_to_comp_unit( object ) ). 68 | loop at procedures->* assigning field-symbol(). 69 | insert lines of analyze_procedure( ) into table findings. 70 | endloop. 71 | endmethod. 72 | 73 | method constructor. 74 | meta_data = /cc4a/check_meta_data=>create( 75 | value #( checked_types = /cc4a/check_meta_data=>checked_types-abap_programs 76 | description = 'Prefer methods over other procedures'(des) 77 | remote_enablement = /cc4a/check_meta_data=>remote_enablement-no 78 | finding_codes = value #( 79 | ( code = finding_codes-avoid_form pseudo_comment = pseudo_comment-avoid_form text = 'Definition of FORM routine &1'(ufr) ) 80 | ( code = finding_codes-prefer_methods text = 'Definition of function module &1'(prm) ) ) 81 | quickfix_codes = value #( ) ) ). 82 | endmethod. 83 | 84 | method if_ci_atc_check~get_meta_data. 85 | meta_data = me->meta_data. 86 | endmethod. 87 | 88 | method if_ci_atc_check~set_assistant_factory. 89 | assistant_factory = factory. 90 | endmethod. 91 | 92 | method if_ci_atc_check~verify_prerequisites. 93 | 94 | endmethod. 95 | 96 | endclass. 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Code Pal for ABAP - Cloud Edition 2 | 3 | [![REUSE status](https://api.reuse.software/badge/github.com/SAP/code-pal-for-abap-cloud)](https://api.reuse.software/info/github.com/SAP/code-pal-for-abap-cloud) 4 | 5 | ## About this Project 6 | 7 | Code Pal is a project that provides ATC checks to assist ABAP programmers in adhering to the [Clean ABAP style guide](https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md). This is a version of that project that provides ATC checks that can be executed in an ABAP Cloud (["Steampunk"](https://blogs.sap.com/2019/08/20/its-steampunk-now/)) environment. The legacy version for SAP_BASIS releases starting at 7.40 is [here](https://github.com/SAP/code-pal-for-abap). 8 | 9 | 10 | ## Requirements and Setup 11 | 12 | Install via [abapGit Eclipse plugin](https://github.com/abapGit/ADT_Frontend) on ABAP cloud systems and [abapGit for SAPGUI](https://docs.abapgit.org/guide-online-install.html) on systems with SAP_BASIS 7.58 or higher. Since Code Pal is developed in English, logon language EN is required during installation. In a Steampunk system, the abapGit plugin may report errors related to the object types NSPC and SCO2. These are caused by differences between the on Premise and cloud ABAP environments and can be ignored as these object types are only relevant when the project is imported into an on Premise environment. 13 | 14 | It's recommended to install the project into a package named `/CC4A/CODE_PAL`. You can choose the superpackage of this package arbitrarily, e.g. the default root package `ZLOCAL` for custom development. The namespace `/CC4A/` comes pre-installed in all Steampunk systems. It is currently unavailable in S/4 Public Cloud systems, but SAP is working on enabling it there, too. 15 | 16 | Compatibility of the most recent version is only guaranteed for the current version of ABAP for Cloud Development. For the SAP_BASIS 7.58-compatible version, use the `SAP_BASIS-7.58-compatible` branch. 17 | 18 | ## Features 19 | 20 | Our main functional goals that differ from the legacy version are: 21 | 22 | - Providing automated quick fixes for many findings in ADT 23 | - Enabling all checks to run in a [remote check scenario](https://blogs.sap.com/2016/12/12/remote-code-analysis-in-atc-one-central-check-system-for-multiple-systems-on-various-releases/). 24 | - All code lives in the `/CC4A/` (Clean Code for ABAP) namespace so collisions with Y*/Z* objects from other projects are avoided. You can get namespace keys at [SAP for Me]( https://me.sap.com/namespace/opensource) to use that namespace in an on Premise customer ABAP enviroment. 25 | 26 | The project contains an ABAP Test Cockpit variant called `/CC4A/CODE_PAL_FULL` that includes all currently available checks. For general information on how to use the ABAP Test Cockpit, see [the official SAP documentation](https://help.sap.com/docs/ABAP_PLATFORM_NEW/ba879a6e2ea04d9bb94c7ccd7cdac446/145568d2a3434ef5bf8352c74853c5eb.html?locale=en-US). 27 | 28 | The [check migration list](check_migration_list.md) shows the current migration status of checks from the legacy version. Use that list to navigate to the documentation of the checks. 29 | 30 | ## Feedback and Support 31 | 32 | Please submit feedback and bug reports as a [GitHub issue](https://github.com/SAP/code-pal-for-abap-cloud/issues) on this project. 33 | 34 | ## Contributing 35 | 36 | We welcome all contributions to this project, no matter whether you fixed a typo, repaired a bug or wrote a new check. See our [contributor guide](CONTRIBUTING.md) for details. 37 | 38 | ## Code of Conduct 39 | 40 | We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. By participating in this project, you agree to abide by its [Code of Conduct](CODE_OF_CONDUCT.md) at all times. 41 | 42 | ## Licensing 43 | 44 | Copyright 2022 SAP SE or an SAP affiliate company and Code Pal for ABAP Cloud contributors. Please see our [license](LICENSES/Apache-2.0.txt) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/SAP/code-pal-for-abap-cloud). 45 | -------------------------------------------------------------------------------- /src/checks/#cc4a#check_constant_interface.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/check_constant_interface definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | interfaces if_ci_atc_check. 8 | 9 | constants: 10 | begin of finding_codes, 11 | cons_intf type if_ci_atc_check=>ty_finding_code value 'CONS_INTF', 12 | end of finding_codes. 13 | constants: 14 | begin of pseudo_comments, 15 | cons_intf type string value 'CONS_INTF', 16 | end of pseudo_comments. 17 | methods constructor. 18 | 19 | protected section. 20 | private section. 21 | data code_provider type ref to if_ci_atc_source_code_provider. 22 | data meta_data type ref to /cc4a/if_check_meta_data. 23 | ENDCLASS. 24 | 25 | 26 | 27 | CLASS /CC4A/CHECK_CONSTANT_INTERFACE IMPLEMENTATION. 28 | 29 | 30 | method if_ci_atc_check~get_meta_data. 31 | meta_data = me->meta_data. 32 | endmethod. 33 | 34 | method constructor. 35 | meta_data = /cc4a/check_meta_data=>create( value #( 36 | checked_types = /cc4a/check_meta_data=>checked_types-abap_programs 37 | description = 'Constants in Interfaces'(des) 38 | finding_codes = value #( 39 | ( code = finding_codes-cons_intf 40 | pseudo_comment = pseudo_comments-cons_intf 41 | text = 'Interface contains only constants'(mc1) ) ) 42 | remote_enablement = /cc4a/check_meta_data=>remote_enablement-unconditional ) ). 43 | endmethod. 44 | 45 | method if_ci_atc_check~run. 46 | code_provider = data_provider->get_code_provider( ). 47 | data(procedures) = code_provider->get_procedures( code_provider->object_to_comp_unit( object = object ) ). 48 | 49 | loop at procedures->* assigning field-symbol(). 50 | 51 | data(has_something_else) = abap_false. 52 | data(if_definition) = abap_false. 53 | 54 | loop at -statements assigning field-symbol(). 55 | case -keyword. 56 | when 'INTERFACE'. 57 | if lines( -tokens ) >= 3. 58 | " Ignore interface load and deferred statements, we are only interested in interface definitions 59 | check -tokens[ 3 ]-lexeme <> 'LOAD' and -tokens[ 3 ]-lexeme <> 'DEFERRED'. 60 | endif. 61 | if_definition = abap_true. 62 | data(at_least_one_constant) = abap_false. 63 | data(intf_decl_statement) = . 64 | continue. 65 | 66 | when 'ENDINTERFACE'. 67 | if has_something_else = abap_false and at_least_one_constant = abap_true. 68 | insert value #( 69 | code = finding_codes-cons_intf 70 | location = code_provider->get_statement_location( intf_decl_statement ) 71 | checksum = code_provider->get_statement_checksum( intf_decl_statement ) 72 | has_pseudo_comment = meta_data->has_valid_pseudo_comment( 73 | statement = intf_decl_statement 74 | finding_code = finding_codes-cons_intf ) 75 | ) into table findings. 76 | else. 77 | has_something_else = abap_false. 78 | endif. 79 | if_definition = abap_false. 80 | continue. 81 | endcase. 82 | 83 | if if_definition = abap_true. 84 | " Only interfaces with at least one constant should be reported, we don't want to report empty interfaces 85 | if at_least_one_constant = abap_false and -tokens[ 1 ]-lexeme = 'CONSTANTS'. 86 | at_least_one_constant = abap_true. 87 | endif. 88 | " Check if there is anything else except constants 89 | if has_something_else = abap_false and -tokens[ 1 ]-lexeme <> 'CONSTANTS'. 90 | has_something_else = abap_true. 91 | endif. 92 | endif. 93 | 94 | endloop. 95 | 96 | endloop. 97 | endmethod. 98 | 99 | 100 | method if_ci_atc_check~set_assistant_factory. 101 | 102 | endmethod. 103 | 104 | 105 | method if_ci_atc_check~verify_prerequisites. 106 | 107 | endmethod. 108 | ENDCLASS. 109 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_avoid_self_ref.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/test_avoid_self_ref definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | protected section. 8 | private section. 9 | class-data string1 type string. 10 | class-data string2 type string. 11 | data number1 type i. 12 | data number2 type i. 13 | 14 | types: 15 | begin of ty_struct, 16 | comp type i, 17 | end of ty_struct. 18 | 19 | data struct type ty_struct. 20 | 21 | constants number3 type i value 0. 22 | constants string3 type string value 'abc'. 23 | 24 | methods without_pseudo_comments 25 | importing number type i 26 | string type string. 27 | 28 | methods with_pseudo_comments 29 | importing number type i 30 | string type string. 31 | 32 | methods importing_parameter 33 | importing number4 type i 34 | number5 type i 35 | string4 type string 36 | returning value(string5) type string. 37 | 38 | methods exporting_parameter 39 | exporting number4 type i 40 | string4 type string 41 | returning value(string5) type string. 42 | ENDCLASS. 43 | 44 | 45 | 46 | CLASS /CC4A/TEST_AVOID_SELF_REF IMPLEMENTATION. 47 | 48 | 49 | method exporting_parameter. 50 | data(string) = me->string1. 51 | final(second_string) = me->string2. 52 | final(string3) = me->string3. 53 | data(number1) = me->number1. 54 | data(struct) = me->struct-comp. 55 | struct = me->struct-comp. 56 | endmethod. 57 | 58 | 59 | method importing_parameter. 60 | data(string1) = me->string1. 61 | final(string) = me->string2. 62 | final(string3) = me->string3. 63 | data(number) = me->number1. 64 | data(structure) = me->struct-comp. 65 | structure = me->struct-comp. 66 | structure = struct-comp. 67 | assign me->(string4) to field-symbol(). 68 | assign me->(string5) to field-symbol(). 69 | endmethod. 70 | 71 | 72 | method without_pseudo_comments. 73 | data number1 type i. 74 | data number4 type i. 75 | data number5 type i. 76 | 77 | data string1 type string. 78 | data string4 type string. 79 | data string5 type string. 80 | 81 | number1 = me->number1 + me->number1. 82 | number1 = me->number1 + me->number2. 83 | number5 = me->number2 + me->number3. 84 | me->number2 = number4 + number5.. 85 | 86 | string1 = me->string1 + me->string1. 87 | string1 = me->string1 + me->string2. 88 | string5 = me->string2 + me->string3. 89 | me->string2 = string4 + string5. 90 | 91 | me->without_pseudo_comments( number = me->number3 string = me->string3 ). 92 | me->with_pseudo_comments( number = me->number1 string = me->string3 ). 93 | me->with_pseudo_comments( number = number4 string = string4 ). 94 | me->with_pseudo_comments( number = number2 string = string5 ). 95 | endmethod. 96 | 97 | 98 | method with_pseudo_comments. 99 | data number1 type i. 100 | data number4 type i. 101 | data number5 type i. 102 | 103 | data string1 type string. 104 | data string4 type string. 105 | data string5 type string. 106 | 107 | number1 = me->number1 + me->number1. 108 | number1 = me->number1 + me->number2. "#EC SELF_REF 109 | number5 = me->number2 + me->number3. "#EC SELF_REF 110 | me->number2 = number4 + number5. "#EC SELF_REF 111 | 112 | string1 = me->string1 + me->string1. 113 | string1 = me->string1 + me->string2. "#EC SELF_REF 114 | string5 = me->string2 + me->string3. "#EC SELF_REF 115 | me->string2 = string4 + string5. "#EC SELF_REF 116 | 117 | me->without_pseudo_comments( number = me->number3 string = me->string3 ). "#EC SELF_REF 118 | me->with_pseudo_comments( number = me->number1 string = me->string3 ). "#EC SELF_RE 119 | me->with_pseudo_comments( number = number4 string = string4 ). "#EC SELF_REF 120 | me->with_pseudo_comments( number = number2 string = string5 ). "#EC SELF_REF 121 | 122 | endmethod. 123 | ENDCLASS. 124 | -------------------------------------------------------------------------------- /src/checks/#cc4a#equals_sign_chaining.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | class ltcl_test definition final for testing 2 | duration short 3 | risk level harmless 4 | friends /cc4a/equals_sign_chaining. 5 | 6 | private section. 7 | constants: 8 | begin of co_test_object, 9 | object_type type if_ci_atc_check=>ty_object-type value 'CLAS', 10 | object_name type if_ci_atc_check=>ty_object-name value '/CC4A/TEST_EQUAL_SIGN_CHAINING', 11 | end of co_test_object. 12 | constants: 13 | begin of co_test_method_name, 14 | finding_1 type cl_ci_atc_unit_driver=>ty_method_name value 'FINDING_1', 15 | finding_2 type cl_ci_atc_unit_driver=>ty_method_name value 'FINDING_2', 16 | finding_3 type cl_ci_atc_unit_driver=>ty_method_name value 'FINDING_3', 17 | finding_4 type cl_ci_atc_unit_driver=>ty_method_name value 'FINDING_4', 18 | end of co_test_method_name. 19 | 20 | 21 | methods run_test_check_findings for testing raising cx_static_check. 22 | 23 | endclass. 24 | 25 | 26 | class ltcl_test implementation. 27 | 28 | method run_test_check_findings. 29 | 30 | " Location and quickfixes of expected findings 31 | data(finding_1_obj) = cl_ci_atc_unit_driver=>get_method_object( 32 | value #( class = co_test_object-object_name method = co_test_method_name-finding_1 ) ). 33 | data(finding_1_loc) = value if_ci_atc_check=>ty_location( 34 | object = finding_1_obj 35 | position = value #( line = 7 column = 4 ) ). 36 | data(qf1_finding_1) = value if_ci_atc_unit_asserter=>ty_expected_quickfixes( 37 | ( code = value #( 38 | ( |C = D.| ) 39 | ( |B = C.| ) 40 | ( |A = B.| ) ) 41 | location = finding_1_loc 42 | quickfix_code = /cc4a/equals_sign_chaining=>quickfix_codes-break_chain ) ). 43 | data(finding_2_obj) = cl_ci_atc_unit_driver=>get_method_object( 44 | value #( class = co_test_object-object_name method = co_test_method_name-finding_2 ) ). 45 | data(finding_2_loc) = value if_ci_atc_check=>ty_location( 46 | object = finding_2_obj 47 | position = value #( line = 6 column = 4 ) ). 48 | data(qf1_finding_2) = value if_ci_atc_unit_asserter=>ty_expected_quickfixes( 49 | ( code = value #( 50 | ( |B = CONV #( c ).| ) 51 | ( |A = B.| ) ) 52 | location = finding_1_loc 53 | quickfix_code = /cc4a/equals_sign_chaining=>quickfix_codes-break_chain ) ). 54 | " Finding 3 should not appear due to the pseudo comment 55 | data(finding_4_obj) = cl_ci_atc_unit_driver=>get_method_object( 56 | value #( class = co_test_object-object_name method = co_test_method_name-finding_4 ) ). 57 | data(finding_4_loc) = value if_ci_atc_check=>ty_location( 58 | object = finding_4_obj 59 | position = value #( line = 7 column = 6 ) ). 60 | data(qf1_finding_4) = value if_ci_atc_unit_asserter=>ty_expected_quickfixes( 61 | ( code = value #( 62 | ( |B = C.| ) 63 | ( |A = B.| ) ) 64 | location = finding_4_loc 65 | quickfix_code = /cc4a/equals_sign_chaining=>quickfix_codes-break_chain ) ). 66 | 67 | cl_ci_atc_unit_driver=>create_asserter( )->check_and_assert( 68 | check = new /cc4a/equals_sign_chaining( ) 69 | object = value #( name = co_test_object-object_name 70 | type = co_test_object-object_type ) 71 | asserter_config = value #( quickfixes = abap_false 72 | remove_findings_with_pcoms = abap_true ) 73 | expected_findings = value #( ( code = /cc4a/equals_sign_chaining=>finding_codes-equals_sign_chaining 74 | location = finding_1_loc 75 | quickfixes = qf1_finding_1 ) 76 | ( code = /cc4a/equals_sign_chaining=>finding_codes-equals_sign_chaining 77 | location = finding_2_loc 78 | quickfixes = qf1_finding_2 ) 79 | ( code = /cc4a/equals_sign_chaining=>finding_codes-equals_sign_chaining 80 | location = finding_4_loc 81 | quickfixes = qf1_finding_4 ) ) ). 82 | 83 | endmethod. 84 | 85 | endclass. 86 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_prefer_is_not.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/test_prefer_is_not definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | protected section. 8 | private section. 9 | 10 | types: begin of table_type, 11 | position type i, 12 | name type string, 13 | end of table_type. 14 | 15 | methods without_brackets. 16 | methods with_brackets. 17 | methods with_pseudo_comments. 18 | methods chained_method_call. 19 | 20 | 21 | methods getint 22 | importing zahl1 type i optional 23 | zahl2 type i optional 24 | returning value(int) type i. 25 | methods getbool 26 | importing true type abap_bool optional 27 | returning value(bool) type abap_bool. 28 | methods get_tester 29 | returning value(tester) type ref to tester. 30 | 31 | data x type i. 32 | data obj type ref to object. 33 | data int_tab type range of i. 34 | ENDCLASS. 35 | 36 | 37 | 38 | CLASS /CC4A/TEST_PREFER_IS_NOT IMPLEMENTATION. 39 | 40 | 41 | method chained_method_call. 42 | if not get_tester( )->check( 2 ). 43 | endif. 44 | endmethod. 45 | 46 | 47 | method getbool. 48 | 49 | endmethod. 50 | 51 | 52 | method getint. 53 | 54 | endmethod. 55 | 56 | 57 | method get_tester. 58 | 59 | endmethod. 60 | 61 | 62 | method without_brackets. 63 | 64 | assert not getint( ) = getbool( ). 65 | 66 | if not x > 1. 67 | endif. 68 | 69 | if not x <> getint( ). 70 | elseif not x < getint( zahl1 = 2 zahl2 = 3 ). 71 | endif. 72 | 73 | if not x in int_tab. 74 | endif. 75 | 76 | if not obj is initial. 77 | elseif not obj is bound. 78 | endif. 79 | 80 | if not x <= getbool( ). 81 | endif. 82 | 83 | if not x ne xsdbool( 1 = 2 ). 84 | endif. 85 | 86 | if not x lt 1 or not x ge getbool( xsdbool( 1 = 2 ) ). 87 | endif. 88 | 89 | if not x le 1 and not x eq 2 . 90 | endif. 91 | 92 | assert not 1 <> 2. 93 | 94 | if not getbool( true = abap_false ). 95 | endif. 96 | 97 | if not getbool( ). 98 | endif. 99 | endmethod. 100 | 101 | 102 | method with_brackets. 103 | 104 | assert not ( getint( ) = getbool( ) ). 105 | 106 | if not ( x = 1 ). 107 | endif. 108 | 109 | if not ( x <> getint( ) ). 110 | elseif not ( x < getint( zahl1 = 2 zahl2 = 3 ) ). 111 | endif. 112 | 113 | if not ( x in int_tab ). 114 | endif. 115 | 116 | if not ( obj is initial ). 117 | elseif not ( obj is bound ). 118 | endif. 119 | 120 | if not ( x <= getbool( ) ). 121 | endif. 122 | 123 | if not ( x ne xsdbool( 1 = xsdbool( 1 = 2 ) ) ). 124 | endif. 125 | 126 | if not ( x lt 1 or x ge getbool( xsdbool( 1 = 2 ) ) ). 127 | endif. 128 | 129 | if not ( x le 1 and not x eq 2 ). 130 | endif. 131 | 132 | assert not ( 1 <> 2 ). 133 | 134 | if not ( ( 1 + 2 ) = 3 ). 135 | endif. 136 | 137 | if not ( ( 1 + 2 ) + 3 = 3 ). 138 | endif. 139 | 140 | if not ( ( 1 + 2 ) + ( 3 + 3 ) = 3 ). 141 | endif. 142 | 143 | endmethod. 144 | 145 | 146 | method with_pseudo_comments. 147 | 148 | assert not getint( ) = getbool( ). "#EC PREFER_IS_NOT 149 | 150 | if not x = 1. "#EC PREFER_IS_NOT 151 | endif. 152 | 153 | if not x <> getint( ). "#EC PREFER_IS_NOT 154 | elseif not x < getint( zahl1 = 2 zahl2 = 3 ). "#EC PREFER_IS_NOT 155 | endif. 156 | 157 | if not x in int_tab. "#EC PREFER_IS_NOT 158 | endif. 159 | 160 | if not obj is initial. "#EC PREFER_IS_NOT 161 | elseif not obj is bound. "#EC PREFER_IS_NOT 162 | endif. 163 | 164 | if not ( x <= getbool( ) ). "#EC PREFER_IS_NOT 165 | endif. 166 | 167 | if not ( x ne xsdbool( 1 = xsdbool( 1 = 2 ) ) ). "#EC PREFER_IS_NOT 168 | endif. 169 | 170 | if not ( x lt 1 or x ge getbool( xsdbool( 1 = 2 ) ) ). 171 | endif. 172 | 173 | if not ( x le 1 and not x eq 2 ). "#EC PREFER_IS_NOT 174 | endif. 175 | 176 | assert not ( 1 <> 2 ). "#EC PREFER_IS_NOT 177 | 178 | endmethod. 179 | ENDCLASS. 180 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_proper_bool_expr.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/test_proper_bool_expr definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | constants: bool type abap_bool value 'X'. 8 | data a type abap_bool. 9 | 10 | types: begin of number_and_bool, 11 | number type i, 12 | boolean type abap_bool, 13 | end of number_and_bool. 14 | 15 | types: begin of struc_of_nab, 16 | nab type number_and_bool, 17 | end of struc_of_nab. 18 | 19 | types tabletype type table of number_and_bool with empty key. 20 | 21 | types: begin of struc_of_table, 22 | table type tabletype, 23 | end of struc_of_table. 24 | 25 | data table2 type table of struc_of_table. 26 | types j type table of struc_of_nab. 27 | 28 | data table type tabletype. 29 | data structure_of_table type struc_of_table. 30 | data abapboolean type abap_boolean. 31 | 32 | data number_bool_table type table of number_and_bool. 33 | data number_bool_structure type number_and_bool. 34 | data strc_nab_table type table of struc_of_nab. 35 | data test_struc_nab type struc_of_nab. 36 | methods test_method 37 | importing iparameter type i optional 38 | returning value(rparameter) type i. 39 | 40 | types: 41 | begin of enum ty_my_bool structure my_bool base type abap_bool, 42 | false value is initial, 43 | true value 'X', 44 | end of enum ty_my_bool structure my_bool. 45 | 46 | protected section. 47 | constants: not_a_bool type string value ' '. 48 | private section. 49 | methods test_if_then_else. 50 | methods test_correct_bool_usage. 51 | methods test_bool_initial. 52 | data int_tab type range of i. 53 | data x type i. 54 | data implicit. 55 | endclass. 56 | 57 | 58 | 59 | class /cc4a/test_proper_bool_expr implementation. 60 | 61 | method test_if_then_else. 62 | data(test) = 'test'. 63 | data(test_number) = 5. 64 | data(b) = abap_true. 65 | if test is initial. 66 | b = abap_true. 67 | else. 68 | b = abap_false. 69 | endif. 70 | 71 | if test is initial. 72 | b = abap_false. 73 | else. 74 | b = abap_true. 75 | endif. 76 | 77 | if test is not initial. 78 | b = abap_false. 79 | else. 80 | b = abap_true. 81 | endif. 82 | 83 | if x in int_tab. 84 | b = abap_false. 85 | else. 86 | b = abap_true. 87 | endif. 88 | 89 | if x not in int_tab. 90 | b = abap_false. 91 | else. 92 | b = abap_true. 93 | endif. 94 | 95 | if test_number lt 38. 96 | b = abap_false. 97 | else. 98 | b = abap_true. 99 | endif. 100 | 101 | if test_number <> 4 or test is not initial. 102 | b = abap_false. 103 | else. 104 | b = abap_true. 105 | endif. 106 | 107 | data(string) = 'teststring'. 108 | if 1 = 2 and 'test' ne substring( len = test_method( iparameter = 3 ) val = string ) and 5 gt 2. 109 | b = ' '. 110 | else. 111 | b = 'X'. 112 | endif. 113 | 114 | if a is not initial. 115 | number_bool_structure-boolean = abap_false. 116 | else. 117 | number_bool_structure-boolean = abap_true. 118 | endif. 119 | 120 | if a is initial. 121 | b = abap_true. 122 | else. 123 | b = abap_false. 124 | endif. 125 | 126 | if table2[ 4 ]-table[ 1 ]-boolean is initial. 127 | b = abap_false. 128 | else. 129 | b = abap_true. 130 | endif. 131 | 132 | if table2[ 4 ]-table[ 1 ]-boolean is initial. 133 | data(c) = abap_true. 134 | else. 135 | c = abap_false. 136 | endif. 137 | 138 | if test_method( 22 ) is initial. 139 | data(d) = abap_true. 140 | endif. 141 | 142 | endmethod. 143 | 144 | 145 | method test_correct_bool_usage. 146 | data t type abap_bool. 147 | t = 'X'. 148 | number_bool_structure-boolean = ' '. 149 | a = space. 150 | test_struc_nab-nab-boolean = 'X'. 151 | 152 | 153 | endmethod. 154 | 155 | method test_bool_initial. 156 | if a is initial. 157 | endif. 158 | if table2[ 4 ]-table[ 1 ]-boolean is initial. 159 | endif. 160 | if test_struc_nab-nab-boolean is initial. 161 | endif. 162 | endmethod. 163 | 164 | 165 | method test_method. 166 | 167 | endmethod. 168 | 169 | endclass. 170 | 171 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#tstflight1.tabl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /CC4A/TSTFLIGHT1 7 | TRANSP 8 | X 9 | D 10 | X 11 | A 12 | 1 13 | 14 | 15 | /CC4A/TSTFLIGHT1 16 | A 17 | 0 18 | APPL1 19 | N 20 | 21 | 22 | 23 | MANDT 24 | X 25 | 0 26 | C 27 | 000006 28 | X 29 | CLNT 30 | 000003 31 | CLNT 32 | 33 | 34 | CARRID 35 | X 36 | 0 37 | C 38 | 000006 39 | X 40 | CHAR 41 | 000003 42 | CHAR 43 | 44 | 45 | CONNID 46 | X 47 | 0 48 | N 49 | 000008 50 | X 51 | NUMC 52 | 000004 53 | NUMC 54 | 55 | 56 | FLDATE 57 | X 58 | 0 59 | D 60 | 000016 61 | X 62 | DATS 63 | 000008 64 | DATS 65 | T 66 | 67 | 68 | CURRENCY 69 | 0 70 | C 71 | 000010 72 | X 73 | CUKY 74 | 000005 75 | CUKY 76 | 77 | 78 | PLANETYPE 79 | 0 80 | C 81 | 000120 82 | X 83 | CHAR 84 | 000060 85 | CHAR 86 | 87 | 88 | QUANTITY 89 | 0 90 | X 91 | 000002 92 | X 93 | INT2 94 | 000005 95 | INT2 96 | 97 | 98 | 99 | D 100 | 101 | 102 | 103 | D 104 | Test / Flug 105 | 106 | 107 | 108 | 109 | 110 | TB 111 | /CC4A/TSTFLIGHT1 112 | D 113 | E 114 | 0002 115 | X 116 | 00002 117 | A 118 | 119 | 120 | DOKU 121 | /CC4A/TSTFLIGHT1 122 | TB 123 | D 124 | S_DOCU_SHOW 125 | S_DOCUS1 126 | 00002 127 | 072 128 | 129 | 130 | 131 | U1 132 | &USE& 133 | 134 | 135 | AS 136 | Diese Tabelle wird im Rahmen der ABAP/4-Schulungen verwendet. Sie ent- 137 | 138 | 139 | hält Informationen zu angebotenen Flügen. 140 | 141 | 142 | U1 143 | &MAINTENANCE& 144 | 145 | 146 | AS 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /src/core/#cc4a#check_meta_data.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/check_meta_data definition 2 | public 3 | final 4 | create private. 5 | 6 | public section. 7 | interfaces /cc4a/if_check_meta_data. 8 | 9 | types: 10 | begin of enum ty_checked_types structure checked_types, 11 | abap_programs, 12 | end of enum ty_checked_types structure checked_types. 13 | types: 14 | "! Remote enablement status of a check. 15 | "! 16 | "! Extend this enum with new variants if a check needs additional functionality in the target system 17 | "! besides the standard Code Inspector infrastructure to analyze ABAP code. 18 | begin of enum ty_remote_enablement structure remote_enablement, 19 | unconditional, 20 | no, 21 | end of enum ty_remote_enablement structure remote_enablement. 22 | types: 23 | begin of ty_finding_code, 24 | code type if_ci_atc_check=>ty_finding_code, 25 | text type if_ci_atc_check_meta_data=>ty_finding_code_info-text, 26 | pseudo_comment type if_ci_atc_check_meta_data=>ty_finding_code_info-pseudo_comment, 27 | end of ty_finding_code. 28 | types ty_finding_codes type hashed table of ty_finding_code with unique key code. 29 | types: 30 | begin of ty_meta_data, 31 | checked_types type ty_checked_types, 32 | description type string, 33 | remote_enablement type ty_remote_enablement, 34 | finding_codes type ty_finding_codes, 35 | quickfix_codes type if_ci_atc_check_meta_data=>ty_quickfix_code_infos, 36 | attributes type if_ci_atc_check_meta_data=>ty_attributes, 37 | end of ty_meta_data. 38 | 39 | class-methods create 40 | importing meta_data type ty_meta_data 41 | returning value(result) type ref to /cc4a/if_check_meta_data. 42 | methods constructor 43 | importing meta_data type ty_meta_data. 44 | 45 | protected section. 46 | 47 | private section. 48 | data meta_data type ty_meta_data. 49 | endclass. 50 | 51 | 52 | 53 | class /cc4a/check_meta_data implementation. 54 | 55 | 56 | method constructor. 57 | me->meta_data = meta_data. 58 | " Callers will usually pass references to the actual attributes of their check as the value. 59 | " This can lead to various unexpected phenomena when these references are then passed back in SET_ATTRIBUTES 60 | " to the checks. In order to isolate us againnst these errors we copy all the attribute references to freshly 61 | " allocated anonymous references on the heap that are used for nother else. 62 | loop at me->meta_data-attributes assigning field-symbol(). 63 | data(type_handle) = cast cl_abap_datadescr( cl_abap_typedescr=>describe_by_data_ref( -value ) ). 64 | data value type ref to data. 65 | create data value type handle type_handle. 66 | value->* = -value->*. 67 | -value = value. 68 | endloop. 69 | loop at me->meta_data-finding_codes assigning field-symbol(). 70 | -pseudo_comment = |CI_{ -pseudo_comment }|. 71 | endloop. 72 | endmethod. 73 | 74 | 75 | method create. 76 | result = new /cc4a/check_meta_data( meta_data ). 77 | endmethod. 78 | 79 | 80 | method if_ci_atc_check_meta_data~get_attributes. 81 | attributes = meta_data-attributes. 82 | endmethod. 83 | 84 | 85 | method if_ci_atc_check_meta_data~get_checked_object_types. 86 | types = switch #( meta_data-checked_types 87 | when checked_types-abap_programs then value #( ( 'PROG' ) ( 'CLAS' ) ( 'FUGR' ) ( 'INTF' ) ) ). 88 | endmethod. 89 | 90 | 91 | method if_ci_atc_check_meta_data~get_description. 92 | description = meta_data-description. 93 | endmethod. 94 | 95 | 96 | method if_ci_atc_check_meta_data~get_finding_code_infos. 97 | finding_code_infos = corresponding #( meta_data-finding_codes ). 98 | endmethod. 99 | 100 | 101 | method if_ci_atc_check_meta_data~get_quickfix_code_infos. 102 | quickfix_code_infos = meta_data-quickfix_codes. 103 | endmethod. 104 | 105 | 106 | method if_ci_atc_check_meta_data~is_remote_enabled. 107 | is_remote_enabled = switch #( meta_data-remote_enablement 108 | when remote_enablement-unconditional then abap_true 109 | when remote_enablement-no then abap_false ). 110 | endmethod. 111 | 112 | 113 | method if_ci_atc_check_meta_data~uses_checksums. 114 | uses_checksums = abap_true. 115 | endmethod. 116 | 117 | 118 | method /cc4a/if_check_meta_data~has_valid_pseudo_comment. 119 | data(pseudo_comment) = meta_data-finding_codes[ code = finding_code ]-pseudo_comment. 120 | has_valid_pseudo_comment = xsdbool( 121 | line_exists( statement-pseudo_comments[ table_line = pseudo_comment ] ) or 122 | line_exists( statement-pseudo_comments[ table_line = pseudo_comment+3 ] ) ). 123 | endmethod. 124 | 125 | endclass. 126 | -------------------------------------------------------------------------------- /src/checks/#cc4a#avoid_default_key.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/avoid_default_key definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | interfaces if_ci_atc_check. 8 | 9 | constants: 10 | begin of finding_codes, 11 | default_key type if_ci_atc_check=>ty_finding_code value 'DEFAULTKEY', 12 | end of finding_codes. 13 | constants: 14 | begin of quickfix_codes, 15 | empty_key type cl_ci_atc_quickfixes=>ty_quickfix_code value 'EMPTYKEY', 16 | end of quickfix_codes. 17 | 18 | methods constructor. 19 | 20 | protected section. 21 | private section. 22 | constants pseudo_comment type string value 'DEFAULT_KEY'. 23 | 24 | data code_provider type ref to if_ci_atc_source_code_provider. 25 | data assistant_factory type ref to cl_ci_atc_assistant_factory. 26 | data meta_data type ref to /cc4a/if_check_meta_data. 27 | 28 | methods analyze_procedure 29 | importing procedure type if_ci_atc_source_code_provider=>ty_procedure 30 | returning value(findings) type if_ci_atc_check=>ty_findings. 31 | methods replace_empty_key 32 | importing statement type if_ci_atc_source_code_provider=>ty_statement 33 | key_word_position type i 34 | returning value(modified_statement) type if_ci_atc_quickfix=>ty_code. 35 | 36 | ENDCLASS. 37 | 38 | 39 | 40 | CLASS /CC4A/AVOID_DEFAULT_KEY IMPLEMENTATION. 41 | 42 | 43 | method analyze_procedure. 44 | loop at procedure-statements assigning field-symbol() 45 | where keyword = 'DATA' or keyword = 'TYPES' 46 | or keyword = 'CLASS-DATA' or keyword = 'CONSTANTS' or keyword = 'STATICS'. 47 | 48 | data(found_at_position) = /cc4a/abap_analyzer=>create( )->find_key_words( 49 | key_words = value #( ( `WITH` ) ( `DEFAULT` ) ( `KEY` ) ) 50 | statement = ). 51 | 52 | if found_at_position > 0. 53 | data(available_quickfixes) = assistant_factory->create_quickfixes( ). 54 | available_quickfixes->create_quickfix( quickfix_codes-empty_key )->replace( 55 | context = assistant_factory->create_quickfix_context( 56 | value #( procedure_id = procedure-id statements = value #( from = sy-tabix to = sy-tabix ) ) ) 57 | code = replace_empty_key( statement = key_word_position = found_at_position ) ). 58 | insert value #( 59 | code = finding_codes-default_key 60 | location = code_provider->get_statement_location( ) 61 | checksum = code_provider->get_statement_checksum( ) 62 | has_pseudo_comment = meta_data->has_valid_pseudo_comment( 63 | statement = 64 | finding_code = finding_codes-default_key ) 65 | details = assistant_factory->create_finding_details( )->attach_quickfixes( available_quickfixes ) 66 | ) into table findings. 67 | endif. 68 | endloop. 69 | 70 | endmethod. 71 | 72 | 73 | method if_ci_atc_check~get_meta_data. 74 | meta_data = me->meta_data. 75 | endmethod. 76 | 77 | method constructor. 78 | meta_data = /cc4a/check_meta_data=>create( 79 | value #( checked_types = /cc4a/check_meta_data=>checked_types-abap_programs 80 | description = 'Avoid default keys'(des) 81 | remote_enablement = /cc4a/check_meta_data=>remote_enablement-unconditional 82 | finding_codes = value #( 83 | ( code = finding_codes-default_key 84 | pseudo_comment = pseudo_comment text = 'Usage of default table key'(dtk) ) ) 85 | quickfix_codes = value #( 86 | ( code = quickfix_codes-empty_key short_text = 'Replace WITH DEFAULT KEY with WITH EMPTY KEY'(qek) ) ) ) ). 87 | endmethod. 88 | 89 | 90 | method if_ci_atc_check~run. 91 | code_provider = data_provider->get_code_provider( ). 92 | data(procedures) = code_provider->get_procedures( code_provider->object_to_comp_unit( object ) ). 93 | loop at procedures->* assigning field-symbol(). 94 | insert lines of analyze_procedure( ) into table findings. 95 | endloop. 96 | endmethod. 97 | 98 | 99 | method if_ci_atc_check~set_assistant_factory. 100 | assistant_factory = factory. 101 | endmethod. 102 | 103 | 104 | method if_ci_atc_check~verify_prerequisites. 105 | 106 | endmethod. 107 | 108 | 109 | method replace_empty_key. 110 | data(new_statement) = statement. 111 | loop at new_statement-tokens from key_word_position assigning field-symbol(). 112 | if -lexeme eq 'DEFAULT'. 113 | -lexeme = 'EMPTY'. 114 | endif. 115 | endloop. 116 | data(flat_new_statement) = /cc4a/abap_analyzer=>create( )->flatten_tokens( new_statement-tokens ) && `.`. 117 | modified_statement = /cc4a/abap_analyzer=>create( )->break_into_lines( flat_new_statement ). 118 | endmethod. 119 | ENDCLASS. 120 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_method_signature.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS /cc4a/test_method_signature DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. "#EC INTF_IN_CLASS 7 | INTERFACES /cc4a/test_method_signature_if. 8 | 9 | METHODS public_inst_not_interface_meth. 10 | 11 | PROTECTED SECTION. 12 | 13 | PRIVATE SECTION. 14 | METHODS multi_ouput_params_types_1 15 | EXPORTING param1 TYPE c 16 | CHANGING param2 TYPE c 17 | RETURNING VALUE(result) TYPE string. 18 | 19 | METHODS multi_ouput_params_types_2 20 | EXPORTING param1 TYPE c 21 | param2 TYPE c 22 | CHANGING param3 TYPE c 23 | RETURNING VALUE(result) TYPE string. 24 | 25 | METHODS multi_ouput_params_types_3 26 | EXPORTING param1 TYPE c 27 | CHANGING param2 TYPE c 28 | RETURNING VALUE(result) TYPE string. "#EC PARAMETER_OUT 29 | 30 | METHODS multi_ouput_params_1 31 | EXPORTING param1 TYPE c 32 | param2 TYPE c. 33 | 34 | METHODS multi_ouput_params_2 35 | CHANGING param1 TYPE c 36 | param2 TYPE c. 37 | 38 | METHODS multi_ouput_params_3 39 | IMPORTING param1 TYPE abap_boolean 40 | param2 TYPE c 41 | CHANGING param3 TYPE c 42 | param4 TYPE c. 43 | 44 | METHODS multi_ouput_params_4 45 | IMPORTING param1 TYPE c 46 | param2 TYPE c 47 | CHANGING param3 TYPE c. 48 | 49 | METHODS multi_ouput_params_5 50 | EXPORTING param1 TYPE c 51 | param2 TYPE c. "#EC NUM_OUTPUT_PARA 52 | 53 | METHODS single_export_param 54 | EXPORTING param1 TYPE abap_bool. 55 | 56 | METHODS input_param_bool_1 57 | IMPORTING param1 TYPE abap_bool. 58 | 59 | METHODS input_param_bool_2 60 | IMPORTING param1 TYPE abap_bool 61 | param2 TYPE c. 62 | 63 | METHODS input_param_bool_3 64 | IMPORTING param1 TYPE abap_bool 65 | RETURNING VALUE(result) TYPE string. 66 | 67 | METHODS get_result 68 | RETURNING VALUE(not_result) TYPE string. 69 | 70 | METHODS input_param_bool_4 71 | IMPORTING param1 TYPE abap_bool. "#EC BOOL_PARAM 72 | 73 | METHODS set_param 74 | IMPORTING param TYPE abap_bool. 75 | 76 | METHODS do_one_or_the_other 77 | IMPORTING what_i_need TYPE string OPTIONAL 78 | something_else TYPE i OPTIONAL. 79 | 80 | METHODS do_one_or_the_other_prag 81 | IMPORTING 82 | what_i_need TYPE string OPTIONAL 83 | something_else TYPE i OPTIONAL. "#EC OPTL_PARAM 84 | 85 | ENDCLASS. 86 | 87 | 88 | 89 | CLASS /cc4a/test_method_signature IMPLEMENTATION. 90 | 91 | 92 | METHOD multi_ouput_params_types_1. 93 | "only signature is relevant for this test 94 | ENDMETHOD. 95 | 96 | 97 | METHOD multi_ouput_params_types_2. 98 | "only signature is relevant for this test 99 | ENDMETHOD. 100 | 101 | 102 | METHOD multi_ouput_params_types_3. 103 | "only signature is relevant for this test 104 | ENDMETHOD. 105 | 106 | 107 | METHOD multi_ouput_params_1. 108 | "only signature is relevant for this test 109 | ENDMETHOD. 110 | 111 | 112 | METHOD multi_ouput_params_2. 113 | "only signature is relevant for this test 114 | ENDMETHOD. 115 | 116 | 117 | METHOD multi_ouput_params_3. 118 | "only signature is relevant for this test 119 | ENDMETHOD. 120 | 121 | 122 | METHOD multi_ouput_params_4. 123 | "only signature is relevant for this test 124 | ENDMETHOD. 125 | 126 | 127 | METHOD multi_ouput_params_5. 128 | "only signature is relevant for this test 129 | ENDMETHOD. 130 | 131 | 132 | METHOD input_param_bool_1. 133 | "only signature is relevant for this test 134 | ENDMETHOD. 135 | 136 | 137 | METHOD input_param_bool_2. 138 | "only signature is relevant for this test 139 | ENDMETHOD. 140 | 141 | 142 | METHOD input_param_bool_3. 143 | "only signature is relevant for this test 144 | ENDMETHOD. 145 | 146 | 147 | METHOD input_param_bool_4. 148 | "only signature is relevant for this test 149 | ENDMETHOD. 150 | 151 | 152 | METHOD do_one_or_the_other. 153 | "only signature is relevant for this test 154 | ENDMETHOD. 155 | 156 | 157 | METHOD do_one_or_the_other_prag. 158 | "only signature is relevant for this test 159 | ENDMETHOD. 160 | 161 | 162 | METHOD set_param. 163 | "only signature is relevant for this test 164 | ENDMETHOD. 165 | 166 | 167 | METHOD public_inst_not_interface_meth. 168 | "only signature is relevant for this test 169 | ENDMETHOD. 170 | 171 | 172 | METHOD /cc4a/test_method_signature_if~public_inst_interface_meth. 173 | "only signature is relevant for this test 174 | ENDMETHOD. 175 | 176 | 177 | METHOD single_export_param. 178 | "only signature is relevant for this test 179 | ENDMETHOD. 180 | 181 | METHOD get_result. 182 | "only signature is relevant for this test 183 | ENDMETHOD. 184 | 185 | ENDCLASS. 186 | -------------------------------------------------------------------------------- /src/core/#cc4a#if_abap_analyzer.intf.abap: -------------------------------------------------------------------------------- 1 | "! Shared functionality to analyze ABAP code. 2 | "! 3 | "! Any logic that processes ABAP code information (e.g. parsing a specific assignment) should be located here 4 | "! so it can be accessed by any check that needs it. 5 | interface /cc4a/if_abap_analyzer 6 | public . 7 | constants max_line_length type i value 255. 8 | types: 9 | begin of enum ty_bracket_type structure bracket_type, 10 | no_bracket, 11 | opening, 12 | closing, 13 | "! Closed and opening. Due to quirks in the ABAP tokenizer, a chained method call like 14 | "! obj->method_1( )->method_2( ) produces a single token `)->method_2(` that is both a closing and an 15 | "! opening bracket. 16 | clopening, 17 | end of enum ty_bracket_type structure bracket_type. 18 | types: 19 | begin of ty_db_statement, 20 | is_db type abap_bool, 21 | dbtab type string, 22 | dbtab_subquery type string, 23 | end of ty_db_statement. 24 | types: 25 | begin of enum ty_parameter_kind structure parameter_kind, 26 | importing, 27 | exporting, 28 | changing, 29 | returning, 30 | end of enum ty_parameter_kind structure parameter_kind. 31 | types: 32 | begin of ty_method_parameter, 33 | name type string, 34 | kind type ty_parameter_kind, 35 | end of ty_method_parameter. 36 | types ty_method_parameters type hashed table of ty_method_parameter with unique key name. 37 | types: 38 | begin of ty_method_definition, 39 | name type string, 40 | is_redefinition type abap_bool, 41 | parameters type ty_method_parameters, 42 | end of ty_method_definition. 43 | types: 44 | begin of enum ty_logical_connective structure logical_connective, 45 | none, 46 | and, 47 | or, 48 | equiv, 49 | not, 50 | end of enum ty_logical_connective structure logical_connective. 51 | 52 | 53 | methods find_key_words 54 | importing 55 | key_words type string_table 56 | statement type if_ci_atc_source_code_provider=>ty_statement 57 | returning 58 | value(position) type i . 59 | methods break_into_lines 60 | importing code type string 61 | returning value(code_lines) type if_ci_atc_quickfix=>ty_code 62 | raising /cc4a/cx_line_break_impossible. 63 | methods flatten_tokens 64 | importing 65 | tokens type if_ci_atc_source_code_provider=>ty_tokens 66 | returning 67 | value(flat_statement) type string . 68 | methods is_bracket 69 | importing 70 | token type if_ci_atc_source_code_provider=>ty_token 71 | returning 72 | value(bracket_type) type ty_bracket_type . 73 | methods calculate_bracket_end 74 | importing 75 | statement type if_ci_atc_source_code_provider=>ty_statement 76 | bracket_position type i 77 | returning 78 | value(end_of_bracket) type i 79 | raising 80 | /cc4a/cx_token_is_no_bracket . 81 | "! The method analyze the given token whether this is an comparison operator or not. 82 | "! Operators like +, -, * and / does not count as comparison operator. 83 | "! The following operators are currently supported: is, in, >, gt, <, lt, >=, ge, <=, le, =, eq, <>, ne 84 | methods token_is_comparison_operator 85 | importing 86 | token type if_ci_atc_source_code_provider=>ty_token 87 | returning 88 | value(is_operator) type abap_bool . 89 | methods negate_comparison_operator 90 | importing 91 | comparison_operator type string 92 | returning 93 | value(negated_comparison_operator) type string 94 | raising 95 | /cc4a/cx_token_is_no_operator . 96 | methods negate_logical_expression 97 | importing 98 | tokens type if_ci_atc_source_code_provider=>ty_tokens 99 | returning 100 | value(negated_expression) type string. 101 | methods is_db_statement 102 | importing 103 | statement type if_ci_atc_source_code_provider=>ty_statement 104 | get_dbtab_name type abap_bool default abap_false 105 | include_subqueries type abap_bool default abap_true 106 | returning 107 | value(result) type ty_db_statement. 108 | 109 | "! The method checks if clause is contained in tokens 110 | "! if so it returns the index of the first token of the first occurrence of the clause 111 | "! otherwise token_index = 0 112 | methods find_clause_index 113 | importing 114 | tokens type if_ci_atc_source_code_provider=>ty_tokens 115 | clause type string 116 | start_index type i default 1 117 | returning 118 | value(token_index) type i 119 | raising 120 | /cc4a/cx_clause_is_initial . 121 | methods is_token_keyword 122 | importing 123 | token type if_ci_atc_source_code_provider=>ty_token 124 | keyword type string 125 | returning 126 | value(result) type abap_bool . 127 | methods is_logical_connective 128 | importing token type if_ci_atc_source_code_provider=>ty_token 129 | returning value(is_logical_connective) type ty_logical_connective. 130 | methods parse_method_definition 131 | importing statement type if_ci_atc_source_code_provider=>ty_statement 132 | returning value(method_definition) type ty_method_definition. 133 | endinterface. 134 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_for_db_statements.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS /cc4a/test_for_db_statements DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. 7 | PROTECTED SECTION. 8 | PRIVATE SECTION. 9 | METHODS no_db. 10 | METHODS dyn. 11 | METHODS mixed. 12 | ENDCLASS. 13 | 14 | 15 | 16 | CLASS /CC4A/TEST_FOR_DB_STATEMENTS IMPLEMENTATION. 17 | 18 | 19 | METHOD dyn. 20 | CONSTANTS c_name TYPE tabname VALUE '/CC4A/DB_TEST2'. 21 | DATA: itab TYPE TABLE OF i, 22 | entry TYPE i, 23 | single TYPE /cc4a/db_test1. 24 | DELETE FROM (`/CC4A/DB_TEST1`) 25 | WHERE obj_name = 'BLABLA'. 26 | LOOP AT itab INTO entry. 27 | SELECT SINGLE * FROM ('/CC4A/DB_TEST2') INTO @entry. 28 | ENDLOOP. 29 | DO. 30 | SELECT SINGLE * FROM (c_name) INTO @entry. 31 | ENDDO. 32 | SELECT SINGLE * FROM ('/CC4A/DB_TEST1') INTO @entry. 33 | SELECT * FROM ('/CC4A/DB_TEST1') INTO @entry. 34 | ENDSELECT. 35 | SELECT * FROM ('/CC4A/DB_TEST1') INTO TABLE @itab. 36 | INSERT ('/CC4A/DB_TEST1') FROM @entry. 37 | INSERT INTO ('/CC4A/DB_TEST1') VALUES @entry. 38 | UPDATE ('/CC4A/DB_TEST1') FROM @entry. 39 | UPDATE ('/CC4A/DB_TEST1') SET pgmid = 'BLAB'. 40 | MODIFY ('/CC4A/DB_TEST1') FROM @entry. 41 | DELETE FROM ('/CC4A/DB_TEST1'). " 42 | DELETE FROM ('/CC4A/DB_TEST1') 43 | WHERE pgmid = 'BLAB'. 44 | DELETE ('/CC4A/DB_TEST1') FROM @entry. 45 | ENDMETHOD. 46 | 47 | 48 | METHOD mixed. 49 | DATA: dbcur TYPE cursor, 50 | entry TYPE /cc4a/db_test1, 51 | itab TYPE TABLE OF /cc4a/db_test1. 52 | * OPEN CURSOR dbcur FOR SELECT * FROM /cc4a/db_test1. 53 | * OPEN CURSOR WITH HOLD dbcur FOR SELECT * FROM /cc4a/db_test1. 54 | 55 | SELECT SINGLE * FROM /cc4a/db_test1 INTO @entry. 56 | SELECT FROM /cc4a/db_test1 INNER JOIN /cc4a/db_test2 ON /cc4a/db_test2~object = /cc4a/db_test1~object 57 | FIELDS * INTO @DATA(dummy). 58 | ENDSELECT. 59 | 60 | DELETE FROM /cc4a/db_test1. 61 | DELETE FROM /cc4a/db_test2 WHERE object NOT IN ( SELECT object FROM /cc4a/db_test1 WHERE pgmid = 'R3TR' ). 62 | DELETE FROM /cc4a/db_test1 63 | WHERE obj_name = 'BLABLA'. 64 | DELETE FROM /cc4a/db_test1. 65 | DELETE FROM /cc4a/db_test1 66 | WHERE pgmid = 'BLAB'. 67 | * DELETE /cc4a/db_test1 FROM entry. 68 | * DELETE FROM DATABASE demo_indx_blob(sc) ID 'DEMO'. 69 | 70 | INSERT /cc4a/db_test2 FROM ( SELECT * FROM /cc4a/db_test1 ) ##LOGGING_VERSUS_FROM_SELECT[/CC4A/DB_TEST2]. 71 | INSERT entry INTO TABLE itab. "no db 72 | LOOP AT itab INTO entry. 73 | INSERT entry INTO itab. "no db 74 | ENDLOOP. 75 | 76 | UPDATE /cc4a/db_test2 SET object = '1' WHERE object NOT IN ( SELECT object FROM /cc4a/db_test1 WHERE pgmid = 'R3TR' ). 77 | UPDATE /cc4a/db_test1 FROM @entry. 78 | UPDATE /cc4a/db_test1 SET pgmid = 'BLAB'. 79 | 80 | MODIFY /cc4a/db_test1 FROM @entry. 81 | 82 | * EXPORT scarr = itab TO DATABASE demo_indx_blob(sc) ID 'DEMO'. 83 | * IMPORT scarr = itab FROM DATABASE demo_indx_blob(sc) ID 'DEMO'. 84 | 85 | * EXEC 86 | * SQL 87 | * . 88 | * COMMIT WORK. 89 | * ENDEXEC. 90 | 91 | DATA from_id TYPE /cc4a/testflight-carrid VALUE 'AA'. 92 | DATA to_id TYPE /cc4a/testflight-carrid VALUE 'UA'. 93 | WITH 94 | +connections AS ( 95 | SELECT /cc4a/testflight~carrid, /cc4a/testflight~planetype, /cc4a/tstflight1~connid 96 | FROM /cc4a/testflight 97 | INNER JOIN /cc4a/tstflight1 98 | ON /cc4a/tstflight1~carrid = /cc4a/testflight~carrid 99 | WHERE /cc4a/testflight~carrid BETWEEN @from_id AND @to_id ), 100 | +sum_seats AS ( 101 | SELECT carrid, connid, SUM( quantity ) AS sum_seats 102 | FROM /cc4a/tstflight1 103 | WHERE carrid BETWEEN @from_id AND @to_id 104 | GROUP BY carrid, connid ), 105 | +result( name, connection, departure ) AS ( 106 | SELECT planetype, c~connid, sum_seats 107 | FROM +connections AS c 108 | INNER JOIN +sum_seats AS s 109 | ON c~carrid = s~carrid AND 110 | c~connid = s~connid ) 111 | SELECT * 112 | FROM +result 113 | ORDER BY name, connection 114 | INTO TABLE @DATA(result). 115 | 116 | ENDMETHOD. 117 | 118 | 119 | METHOD no_db. 120 | DATA: itab TYPE TABLE OF /cc4a/db_test1, 121 | entry TYPE /cc4a/db_test1, 122 | include TYPE TABLE OF string, 123 | * texts TYPE TABLE OF textpool, 124 | * report TYPE t100, 125 | where TYPE string, 126 | itab2 TYPE TABLE OF /cc4a/db_test1. 127 | 128 | INSERT entry INTO TABLE itab. 129 | LOOP AT itab INTO entry. 130 | INSERT entry INTO itab. 131 | ENDLOOP. 132 | DELETE itab INDEX 1. 133 | * MODIFY CURRENT LINE. 134 | * INSERT REPORT sy-repid FROM include. 135 | * DELETE REPORT sy-repid. 136 | DELETE ADJACENT DUPLICATES FROM itab. 137 | * INSERT TEXTPOOL sy-repid LANGUAGE sy-langu FROM texts. 138 | * DELETE TEXTPOOL sy-repid LANGUAGE sy-langu. 139 | DELETE TABLE itab FROM entry. 140 | DELETE itab FROM 5. 141 | DELETE itab TO 7. 142 | DELETE itab WHERE pgmid = 'R3TR'. 143 | DELETE itab WHERE (where). 144 | INSERT entry INTO TABLE itab. 145 | INSERT entry INTO itab INDEX 5. 146 | ENDMETHOD. 147 | ENDCLASS. 148 | -------------------------------------------------------------------------------- /src/checks/#cc4a#avoid_default_key.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | class test definition final for testing 2 | duration short 3 | risk level harmless. 4 | 5 | private section. 6 | constants test_class type c length 30 value '/CC4A/TEST_AVOID_DEFAULT_KEY'. 7 | constants: 8 | begin of test_class_methods, 9 | with_pseudo_comments type c length 30 value 'WITH_PSEUDO_COMMENTS', 10 | without_pseudo_comments type c length 30 value 'WITHOUT_PSEUDO_COMMENTS', 11 | static_findings type c length 30 value 'STATIC_FINDINGS', 12 | end of test_class_methods. 13 | 14 | methods execute_test_class for testing raising cx_static_check. 15 | endclass. 16 | 17 | class test implementation. 18 | 19 | method execute_test_class. 20 | 21 | data(psuedo_comment_1) = value if_ci_atc_check=>ty_location( 22 | object = cl_ci_atc_unit_driver=>get_class_section_object( 23 | value #( class = test_class kind = cl_ci_atc_unit_driver=>class_section_kind-private ) ) 24 | position = value #( line = 14 column = 4 ) ). 25 | data(psuedo_comment_2) = value if_ci_atc_check=>ty_location( 26 | object = cl_ci_atc_unit_driver=>get_method_object( 27 | value #( class = test_class method = test_class_methods-with_pseudo_comments ) ) 28 | position = value #( line = 4 column = 4 ) ). 29 | data(psuedo_comment_3) = value if_ci_atc_check=>ty_location( 30 | object = cl_ci_atc_unit_driver=>get_method_object( 31 | value #( class = test_class method = test_class_methods-with_pseudo_comments ) ) 32 | position = value #( line = 8 column = 4 ) ). 33 | data(finding_1) = value if_ci_atc_check=>ty_location( 34 | object = cl_ci_atc_unit_driver=>get_class_section_object( 35 | value #( class = test_class kind = cl_ci_atc_unit_driver=>class_section_kind-private ) ) 36 | position = value #( line = 12 column = 4 ) ). 37 | data(finding_2) = value if_ci_atc_check=>ty_location( 38 | object = cl_ci_atc_unit_driver=>get_method_object( 39 | value #( class = test_class method = test_class_methods-without_pseudo_comments ) ) 40 | position = value #( line = 4 column = 4 ) ). 41 | data(finding_3) = value if_ci_atc_check=>ty_location( 42 | object = cl_ci_atc_unit_driver=>get_method_object( 43 | value #( class = test_class method = test_class_methods-without_pseudo_comments ) ) 44 | position = value #( line = 8 column = 4 ) ). 45 | data(static_finding_1) = value if_ci_atc_check=>ty_location( 46 | object = cl_ci_atc_unit_driver=>get_method_object( 47 | value #( class = test_class method = test_class_methods-static_findings ) ) 48 | position = value #( line = 2 column = 4 ) ). 49 | data(static_finding_2) = value if_ci_atc_check=>ty_location( 50 | object = cl_ci_atc_unit_driver=>get_method_object( 51 | value #( class = test_class method = test_class_methods-static_findings ) ) 52 | position = value #( line = 3 column = 4 ) ). 53 | 54 | cl_ci_atc_unit_driver=>create_asserter( )->check_and_assert( 55 | check = new /cc4a/avoid_default_key( ) 56 | object = value #( type = 'CLAS' name = test_class ) 57 | expected_findings = value #( 58 | ( code = /cc4a/avoid_default_key=>finding_codes-default_key 59 | location = psuedo_comment_1 60 | quickfixes = value #( ( 61 | quickfix_code = /cc4a/avoid_default_key=>quickfix_codes-empty_key 62 | location = psuedo_comment_1 63 | code = value #( 64 | ( `CLASS-DATA GHI TYPE TABLE OF TY_STRUCT WITH EMPTY KEY .` ) ) ) ) ) 65 | ( code = /cc4a/avoid_default_key=>finding_codes-default_key 66 | location = psuedo_comment_2 67 | quickfixes = value #( ( 68 | quickfix_code = /cc4a/avoid_default_key=>quickfix_codes-empty_key 69 | location = psuedo_comment_2 70 | code = value #( 71 | ( `DATA STU TYPE TABLE OF TY_STRUCT WITH EMPTY KEY .` ) ) ) ) ) 72 | ( code = /cc4a/avoid_default_key=>finding_codes-default_key 73 | location = psuedo_comment_3 ) 74 | ( code = /cc4a/avoid_default_key=>finding_codes-default_key 75 | location = finding_1 76 | quickfixes = value #( ( 77 | quickfix_code = /cc4a/avoid_default_key=>quickfix_codes-empty_key 78 | location = finding_1 79 | code = value #( 80 | ( `CLASS-DATA ABC TYPE TABLE OF TY_STRUCT WITH EMPTY KEY .` ) ) ) ) ) 81 | ( code = /cc4a/avoid_default_key=>finding_codes-default_key 82 | location = finding_2 83 | quickfixes = value #( ( 84 | quickfix_code = /cc4a/avoid_default_key=>quickfix_codes-empty_key 85 | location = finding_2 86 | code = value #( 87 | ( `DATA STU TYPE TABLE OF TY_STRUCT WITH EMPTY KEY .` ) ) ) ) ) 88 | ( code = /cc4a/avoid_default_key=>finding_codes-default_key 89 | location = finding_3 ) 90 | ( code = /cc4a/avoid_default_key=>finding_codes-default_key 91 | location = static_finding_1 92 | quickfixes = value #( ( 93 | quickfix_code = /cc4a/avoid_default_key=>quickfix_codes-empty_key 94 | location = static_finding_1 95 | code = value #( 96 | ( `STATICS MEMO TYPE STANDARD TABLE OF STRING WITH EMPTY KEY .` ) ) ) ) ) 97 | ( code = /cc4a/avoid_default_key=>finding_codes-default_key 98 | location = static_finding_2 99 | quickfixes = value #( ( 100 | quickfix_code = /cc4a/avoid_default_key=>quickfix_codes-empty_key 101 | location = static_finding_2 102 | code = value #( 103 | ( `STATICS MAMO TYPE STANDARD TABLE OF STRING WITH EMPTY KEY .` ) ) ) ) ) ) 104 | asserter_config = value #( quickfixes = abap_false ) ). 105 | 106 | endmethod. 107 | endclass. 108 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, caste, color, religion, or sexual 10 | identity and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the overall 26 | community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or advances of 31 | any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email address, 35 | without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | [INSERT CONTACT METHOD]. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series of 86 | actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or permanent 93 | ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within the 113 | community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.1, available at 119 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 120 | 121 | Community Impact Guidelines were inspired by 122 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 123 | 124 | For answers to common questions about this code of conduct, see the FAQ at 125 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at 126 | [https://www.contributor-covenant.org/translations][translations]. 127 | 128 | [homepage]: https://www.contributor-covenant.org 129 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 130 | [Mozilla CoC]: https://github.com/mozilla/diversity 131 | [FAQ]: https://www.contributor-covenant.org/faq 132 | [translations]: https://www.contributor-covenant.org/translations 133 | -------------------------------------------------------------------------------- /src/checks/#cc4a#equals_sign_chaining.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/equals_sign_chaining definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | interfaces if_ci_atc_check. 8 | 9 | constants: 10 | begin of finding_codes, 11 | equals_sign_chaining type if_ci_atc_check=>ty_finding_code value 'EQ_CHAIN', 12 | end of finding_codes. 13 | constants: 14 | begin of pseudo_comments, 15 | eqals_sign_chaining type string value 'EQUALS_CHAINING', 16 | end of pseudo_comments. 17 | constants: 18 | begin of quickfix_codes, 19 | break_chain type cl_ci_atc_quickfixes=>ty_quickfix_code value 'BRK_CHAIN', 20 | end of quickfix_codes. 21 | methods constructor. 22 | 23 | protected section. 24 | private section. 25 | types: 26 | begin of ty_qf_data, 27 | replacement type if_ci_atc_quickfix=>ty_code, 28 | insert_after type if_ci_atc_quickfix=>ty_code, 29 | token_tabix_last_eq_sign type i, 30 | end of ty_qf_data. 31 | 32 | data code_provider type ref to if_ci_atc_source_code_provider. 33 | data assistant_factory type ref to cl_ci_atc_assistant_factory. 34 | data meta_data type ref to /cc4a/if_check_meta_data. 35 | 36 | methods calculate_quickfix_data importing statement type if_ci_atc_source_code_provider=>ty_statement 37 | returning value(qf_data) type ty_qf_data. 38 | 39 | ENDCLASS. 40 | 41 | 42 | 43 | CLASS /CC4A/EQUALS_SIGN_CHAINING IMPLEMENTATION. 44 | 45 | 46 | method calculate_quickfix_data. 47 | data(line_offset) = statement-tokens[ 1 ]-position-column. 48 | 49 | " Find last relevant equal sign of statement 50 | loop at statement-tokens assigning field-symbol(). 51 | 52 | if sy-tabix mod 2 <> 0. 53 | continue. 54 | else. 55 | if -lexeme <> '='. 56 | exit. 57 | endif. 58 | qf_data-token_tabix_last_eq_sign = sy-tabix. 59 | endif. 60 | 61 | endloop. 62 | 63 | " Calculate replacement code 64 | data(line_of_code) = |{ statement-tokens[ qf_data-token_tabix_last_eq_sign - 1 ]-lexeme } = |. 65 | insert line_of_code into table qf_data-replacement. 66 | 67 | " Calculate insert after code 68 | data(token_tabix) = qf_data-token_tabix_last_eq_sign. 69 | clear line_of_code. 70 | data(offset) = |{ '' width = line_offset pad = ` ` }|. 71 | do ( qf_data-token_tabix_last_eq_sign / 2 ) - 1 times. 72 | token_tabix -= 2. 73 | line_of_code = 74 | |{ offset }{ statement-tokens[ token_tabix - 1 ]-lexeme } = { statement-tokens[ token_tabix + 1 ]-lexeme }.|. 75 | insert line_of_code into table qf_data-insert_after. 76 | enddo. 77 | 78 | endmethod. 79 | 80 | 81 | method if_ci_atc_check~get_meta_data. 82 | 83 | meta_data = me->meta_data. 84 | 85 | endmethod. 86 | 87 | method constructor. 88 | meta_data = /cc4a/check_meta_data=>create( value #( 89 | checked_types = /cc4a/check_meta_data=>checked_types-abap_programs 90 | description = 'Assignment Chaining'(des) 91 | finding_codes = value #( ( 92 | code = finding_codes-equals_sign_chaining 93 | pseudo_comment = pseudo_comments-eqals_sign_chaining 94 | text = 'Values are allocated more than once within one statement'(mc1) ) ) 95 | quickfix_codes = value #( ( 96 | code = quickfix_codes-break_chain 97 | short_text = 'Break assignment chain into multiple rows'(q1s) ) ) 98 | remote_enablement = /cc4a/check_meta_data=>remote_enablement-unconditional ) ). 99 | endmethod. 100 | 101 | 102 | method if_ci_atc_check~run. 103 | 104 | code_provider = data_provider->get_code_provider( ). 105 | data(procedures) = code_provider->get_procedures( code_provider->object_to_comp_unit( object = object ) ). 106 | 107 | loop at procedures->* assigning field-symbol(). 108 | 109 | " Access with primary key needed to receive correct sy-tabix in loop 110 | loop at -statements assigning field-symbol() where keyword = 'COMPUTE' ##PRIMKEY[KEYWORD]. 111 | 112 | data(nr_of_tokens) = lines( -tokens ). 113 | check nr_of_tokens > 3. 114 | if -tokens[ 2 ]-lexeme = '=' and -tokens[ 4 ]-lexeme = '='. 115 | 116 | " Create quickfix BRK_CHAIN 117 | data(qf_data) = calculate_quickfix_data( ). 118 | data(quickfixes) = assistant_factory->create_quickfixes( ). 119 | data(quickfix_1) = quickfixes->create_quickfix( quickfix_codes-break_chain ). 120 | quickfix_1->replace( context = assistant_factory->create_quickfix_context( 121 | value #( 122 | procedure_id = -id 123 | statements = value #( from = sy-tabix to = sy-tabix ) 124 | tokens = value #( from = 1 to = qf_data-token_tabix_last_eq_sign ) ) ) 125 | code = qf_data-replacement ). 126 | quickfix_1->insert_after( 127 | context = assistant_factory->create_quickfix_context( value #( 128 | procedure_id = -id 129 | statements = value #( from = sy-tabix to = sy-tabix ) ) ) 130 | code = qf_data-insert_after ). 131 | 132 | insert value #( 133 | code = finding_codes-equals_sign_chaining 134 | location = code_provider->get_statement_location( ) 135 | checksum = code_provider->get_statement_checksum( ) 136 | has_pseudo_comment = meta_data->has_valid_pseudo_comment( 137 | statement = 138 | finding_code = finding_codes-equals_sign_chaining ) 139 | details = assistant_factory->create_finding_details( )->attach_quickfixes( quickfixes ) 140 | ) into table findings. 141 | endif. 142 | 143 | endloop. 144 | 145 | endloop. 146 | 147 | endmethod. 148 | 149 | 150 | method if_ci_atc_check~set_assistant_factory. 151 | 152 | assistant_factory = factory. 153 | 154 | endmethod. 155 | 156 | 157 | method if_ci_atc_check~verify_prerequisites. 158 | 159 | " Nothing to check 160 | 161 | endmethod. 162 | ENDCLASS. 163 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_scope_of_variable.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/test_scope_of_variable definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | methods test1. 8 | methods test2. 9 | methods test3. 10 | methods test4. 11 | methods test5. 12 | methods test6. 13 | methods test7. 14 | methods test8. 15 | methods test9. 16 | methods test10. 17 | methods test11. 18 | protected section. 19 | private section. 20 | types ty_char2 type c length 2. 21 | methods my_method1 22 | importing val type ty_char2 23 | num type i 24 | lexeme type string. 25 | methods my_method2 26 | importing par_1 type i 27 | exporting par_2 type i. 28 | endclass. 29 | 30 | 31 | 32 | class /cc4a/test_scope_of_variable implementation. 33 | method test1. 34 | data(a) = 14. 35 | if 1 = 2. 36 | data(var1) = 5. 37 | else. 38 | var1 = 6. 39 | endif. 40 | endmethod. 41 | method test2. 42 | do. 43 | case sy-subrc. 44 | when 0. 45 | data(var2) = 'blabla'. 46 | when 1. 47 | var2 = 'x'. 48 | data(varx) = 15. 49 | when 15. 50 | varx += 1. 51 | endcase. 52 | if 1 = 2. 53 | var2 += 1. 54 | endif. 55 | enddo. 56 | varx += 1. 57 | endmethod. 58 | method test3. 59 | if 1 = 2. 60 | data(new) = 'hallo'. 61 | else. 62 | data(var) = 15. 63 | if sy-subrc = 0. 64 | var += 1. 65 | else. 66 | data(bla) = var + 1. 67 | endif. 68 | endif. 69 | endmethod. 70 | method test4. 71 | types: ty_range type range of i. 72 | data itab type table of string. 73 | data itab1 type table of string. 74 | if sy-subrc = 0. 75 | data(var) = value ty_range( for in itab ( low = sign = 'I' option = 'EQ' ) ). 76 | else. 77 | var = value ty_range( for in itab1 ( low = sign = 'I' option = 'EQ' ) ). 78 | endif. 79 | if sy-subrc = 0. 80 | field-symbols type string. 81 | assign `blabla` to . 82 | else. 83 | assign `blub` to . 84 | endif. 85 | if 1 = 2. 86 | data(test) = value #( itab1[ 1 ] ). 87 | else. 88 | test = `blabla`. 89 | endif. 90 | endmethod. 91 | method test5. 92 | data number type i. 93 | case number. 94 | when 1. 95 | if sy-subrc = 0. 96 | data(condition) = ` AND `. 97 | else. 98 | condition = ` OR `. 99 | endif. 100 | data(new) = condition. 101 | when 2. 102 | data(result) = 0. 103 | endcase. 104 | endmethod. 105 | method test6. 106 | case sy-subrc. 107 | when 1. 108 | if sy-subrc = 0. 109 | types t_itab type standard table of string with default key. 110 | data itab type t_itab. 111 | data condition type ref to t_itab. 112 | data condition1 like ref to itab. 113 | data flag. 114 | else. 115 | loop at condition->* assigning field-symbol(). 116 | endloop. 117 | if is initial or condition1 is initial. 118 | endif. 119 | endif. 120 | when 2. 121 | types: begin of t_test, 122 | a type i, 123 | b type i, 124 | end of t_test. 125 | field-symbols type t_test. 126 | flag = 'a'. 127 | endcase. 128 | data test type t_test. 129 | assign test to . 130 | endmethod. 131 | method test7. 132 | if sy-subrc = 0. 133 | data: begin of line, 134 | format type i, 135 | text type string, 136 | end of line. 137 | clear line. 138 | else. 139 | data(new) = line. 140 | line-format = 15. 141 | line-text = 'blabla'. 142 | endif. 143 | endmethod. 144 | method test8. 145 | types: begin of t_line, 146 | val(2) type c, 147 | num type i, 148 | end of t_line. 149 | data itab type standard table of t_line. 150 | data num type i. 151 | if sy-subrc = 0. 152 | data(entry) = itab[ val = `a` && `b` ]. 153 | data(idx) = line_index( itab[ val = `a` && `b` ] ). 154 | data(test) = 'ab'. 155 | data(test_string) = | blabla { test }|. 156 | else. 157 | data(new) = entry. 158 | my_method1( val = test num = idx lexeme = test_string ). 159 | endif. 160 | endmethod. 161 | 162 | method test9. 163 | data itab type standard table of i. 164 | data number type i. 165 | data data(30) type c. 166 | if sy-subrc = 0. 167 | data a(1) value 'F'. 168 | data b type string value `blabla`. 169 | data c value 0 like sy-tabix. 170 | data(2) = 'AB'. 171 | data: begin of d, 172 | one type string, 173 | two type string, 174 | end of d. 175 | data: begin of d_1, 176 | a type i, 177 | begin of d_2, 178 | x type i, 179 | y type i, 180 | end of d_2, 181 | end of d_1. 182 | else. 183 | a = 'B'. 184 | data(new) = |{ b }1|. 185 | c += 1. 186 | data(3) = 'ABC'. 187 | data(new1) = d_1. 188 | d-one = `blabla`. 189 | endif. 190 | if number > 1. 191 | number = lines( itab ). "COMPUTE number = lines( itab ). 192 | else. 193 | number = 5. 194 | endif. 195 | 196 | endmethod. 197 | method test10. 198 | data var_1 type i. 199 | data itab type table of i. 200 | if var_1 = 2. 201 | data(var_2) = var_1. 202 | my_method2( exporting par_1 = var_2 importing par_2 = data(var_3) ). 203 | select from i_custabapobjdirectoryentry fields * into table @data(var_4). 204 | read table itab index 5 assigning field-symbol(). 205 | else. 206 | var_2 = 3. 207 | var_3 = 3. 208 | select from i_custabapobjdirectoryentry fields * into table @var_4. 209 | = 13. 210 | endif. 211 | endmethod. 212 | method test11. 213 | select * from i_custabapobjdirectoryentry into @data(stuff). 214 | data(var_1) = stuff-abapobjectresponsibleuser. 215 | endselect. 216 | data(var_2) = stuff-abapobjectresponsibleuser. 217 | var_2 = var_1. 218 | endmethod. 219 | method my_method1. 220 | 221 | endmethod. 222 | method my_method2. 223 | endmethod. 224 | endclass. 225 | -------------------------------------------------------------------------------- /src/test_objects/#cc4a#test_chain_declaration.clas.abap: -------------------------------------------------------------------------------- 1 | class /cc4a/test_chain_declaration definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | protected section. 8 | private section. 9 | class-methods test_statics. 10 | methods without_pseudo_comments. 11 | methods with_pseudo_comments. 12 | 13 | constants: q type i value 0, w type i value 0. "#EC CHAIN_DECL_USAG 14 | 15 | constants: begin of ty_constants, 16 | first type i value 0, 17 | second type i value 0, 18 | end of ty_constants. 19 | 20 | class-data: begin of ty_class_data, 21 | abcde type i, 22 | abcd type i, 23 | end of ty_class_data. 24 | 25 | class-data: o type i, 26 | p type i. 27 | 28 | data: asd type d, fdg type d. 29 | ENDCLASS. 30 | 31 | 32 | 33 | CLASS /CC4A/TEST_CHAIN_DECLARATION IMPLEMENTATION. 34 | 35 | 36 | method test_statics. 37 | statics: third type i, 38 | fourth type i. 39 | 40 | statics: dsgz type i, asg type i. "#EC CHAIN_DECL_USAG 41 | 42 | statics: begin of ty_statics, 43 | kelvin type i, 44 | watt type i, 45 | end of ty_statics. 46 | endmethod. 47 | 48 | 49 | method without_pseudo_comments. 50 | data: z type i, k type i, b type i, d type i. 51 | 52 | types: begin of ty_types, 53 | type1 type i, 54 | type2 type i, 55 | end of ty_types. 56 | 57 | types ty_type1 type ty_types. 58 | 59 | types: ty_type2 type ty_types, 60 | ty_type3 type ty_types. 61 | 62 | types: ty_type11 type ty_types. 63 | 64 | types: 65 | ty_exemptions type standard table of string with empty key, 66 | begin of ty_object_with_exemptions, 67 | begin of key, 68 | obj_name type c length 40, 69 | obj_type type c length 4, 70 | end of key, 71 | end of ty_object_with_exemptions, 72 | begin of current_dlvunit_t, 73 | dlvunit type ty_types, 74 | range type range of ty_type1, 75 | end of current_dlvunit_t, 76 | begin of current_chkid_t, 77 | module_id type ty_type11, 78 | chkid type ty_type3, 79 | range type range of ty_type1, 80 | exemption_granularity type ty_object_with_exemptions-key-obj_type, 81 | check_is_unknown type abap_bool, 82 | end of current_chkid_t, 83 | begin of current_chkmsgid_t, 84 | chkmsgid type xstring, 85 | range type range of xstring, 86 | end of current_chkmsgid_t. 87 | 88 | constants: 89 | begin of c_cfg_param2, 90 | display_load type ty_object_with_exemptions-key-obj_name value 'DISPLAY_LOAD', 91 | object_provider_id type ty_object_with_exemptions-key-obj_name value 'OBJECT_PROVIDER', 92 | restart_memento type ty_object_with_exemptions-key-obj_name value 'RESTART_MEMENTO', 93 | worklist_id type ty_object_with_exemptions-key-obj_name value 'WORKLIST_ID', 94 | end of c_cfg_param2, 95 | c_module_id2 type xstring value '005056A7004E1EE682F6E8FEE661C090'. 96 | endmethod. 97 | 98 | 99 | method with_pseudo_comments. 100 | data: q type i, "#EC CHAIN_DECL_USAG 101 | w type i, 102 | e type i, 103 | r type i. 104 | types: begin of ty_types, 105 | type1 type i, 106 | type2 type i, 107 | end of ty_types. 108 | 109 | types: ty_type10 type ty_types, "#EC CHAIN_DECL_USAG 110 | ty_type13 type ty_types. 111 | 112 | types: ty_type11 type ty_types. 113 | 114 | types: begin of ty_structure, 115 | a type string, 116 | b type string, 117 | c type string, 118 | end of ty_structure. 119 | 120 | types: begin of st_out. 121 | types: begin of sadasd, 122 | sts_chg type ty_structure, 123 | lock_exs type c length 2, 124 | status type ty_type10, 125 | sub_status type ty_type13, 126 | msgguid type ty_type10. 127 | include type ty_structure. 128 | types end of sadasd. 129 | types: 130 | create_date type ty_types, 131 | create_time type ty_structure. 132 | types: end of st_out. 133 | 134 | constants: "#EC CHAIN_DECL_USAG 135 | begin of c_cfg_param, 136 | display_load type c length 40 value 'DISPLAY_LOAD', 137 | object_provider_id type c length 40 value 'OBJECT_PROVIDER', 138 | restart_memento type c length 40 value 'RESTART_MEMENTO', 139 | worklist_id type c length 40 value 'WORKLIST_ID', 140 | end of c_cfg_param, 141 | 142 | begin of c_set_param, 143 | object type c length 40 value 'OBJECT', 144 | failure type c length 40 value 'FAILURE', 145 | gen_failure type c length 40 value 'GEN_FAILURE', 146 | finding type c length 40 value 'FINDING', 147 | object_context type c length 40 value 'OBJCTX', 148 | dyntest_object type c length 40 value 'DYNTEST_OBJECT', 149 | end of c_set_param. 150 | 151 | data(asd) = c_cfg_param-display_load. 152 | 153 | types: "#EC CHAIN_DECL_USAG 154 | ty_exemptions type standard table of string with empty key, 155 | begin of ty_object_with_exemptions, 156 | begin of key, 157 | obj_type type c length 4, 158 | obj_name type c length 40, 159 | end of key, 160 | end of ty_object_with_exemptions, 161 | begin of current_dlvunit_t, 162 | dlvunit type ty_type10, 163 | range type range of ty_type10, 164 | end of current_dlvunit_t, 165 | begin of current_chkid_t, 166 | module_id type xstring, 167 | chkid type xstring, 168 | range type range of ty_type10, 169 | exemption_granularity type ty_object_with_exemptions-key, 170 | check_is_unknown type abap_bool, 171 | end of current_chkid_t, 172 | begin of current_chkmsgid_t, 173 | chkmsgid type xstring, 174 | range type range of xstring, 175 | end of current_chkmsgid_t. 176 | endmethod. 177 | ENDCLASS. 178 | --------------------------------------------------------------------------------