From e45ffb4b7ac82ff1b95e05ab723888d45084d087 Mon Sep 17 00:00:00 2001 From: Lucas Borin <5233413+lucasborin@users.noreply.github.com> Date: Fri, 23 Apr 2021 10:59:44 -0300 Subject: [PATCH] 1.14.0 (#345) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 1.14.0 * fixing version * adding missing checks feature (#346) * adding missing checks feature * minor update Co-authored-by: Eugen Guenther * Update changelog.txt * Standard Functions in Prefer IS NOT to NOT IS (#353) * solves #338 * Update changelog.txt * contains_any_not_of and contains_any_of * Prefer New to Create Object (#354) * implements #283 * Update check_documentation.md * minor fixes * Create prefer-new-to-create-object.md * Update changelog.txt * Update prefer-new-to-create-object.md * adding example Co-authored-by: estevao-schultz-neto-SAP <63100656+estevao-schultz-neto-SAP@users.noreply.github.com> * Unit Test Assert Check (#347) * new check * fixing class description * adding demo * comparing token type * Update check_documentation.md * Update check_documentation.md * Create unit_test_assert.md * Update changelog.txt * Update unit_test_assert.md Co-authored-by: estevao-schultz-neto-SAP <63100656+estevao-schultz-neto-SAP@users.noreply.github.com> * Update y_check_unit_test_assert.clas.abap * Update y_check_unit_test_assert.clas.abap * Part 1 - core feature - allow pseudo comment exception #329 (#357) * feature - allow pseudo comment exception * Update y_check_unit_test_assert.clas.abap Co-authored-by: Lucas Borin <5233413+lucasborin@users.noreply.github.com> * Revert "Part 1 - core feature - allow pseudo comment exception #329 (#357)" (#358) This reverts commit 4da128bbb1a5b569adc6aa88bcfe4f5c3f137bb6. * fixes #359 (#366) * Update changelog.txt * New abapLint Rules (#304) * Update abaplint.json * Update abaplint.json * Update abaplint.json * Update abaplint.json * disabling empty_line_in_statement * Remove double space * disabling exit_or_check * disabling line_only_punc Reporting false-positives: https://github.com/abaplint/abaplint/issues/1888 * Update abaplint.json * Update abaplint.json * Compare operator "EQ" not preferred * Disabling no_yoda_conditions https://github.com/abaplint/abaplint/issues/1891 * Method "get_first_character" not used * Compare operator "EQ" not preferred * Keep single parameter on one line * Statement "ADD" is obsolete * Compare operator "GE" not preferred Co-authored-by: abaplint[bot] <24845621+abaplint[bot]@users.noreply.github.com> * Compare operator "GE" not preferred Co-authored-by: abaplint[bot] <24845621+abaplint[bot]@users.noreply.github.com> * Compare operator "EQ" not preferred * Avoid use of SELECT * * Uncaught exception cx_sy_itab_line_not_found * Compare operator "EQ", "LT, "GT" not preferred * Reorder definitions to top of routine * Too many parenthesis, simple * Prefer Inline Declarations, CHECK_CONFIGURATION * Missing space between string or character literal * wrongly commited object * Some fixes Compare operator "EQ" not preferred Prefer Inline Declarations, FM_NAME Reorder definitions to top of routine * Statement "ADD" is obsolete * Compare operator "EQ" not preferred * Some fixes Compare operator "EQ" not preferred Statement "ADD" is obsolete Statement "SUBTRACT" is obsolete Line break multiple parameters * Some fixes Compare operator "EQ" not preferred Method "check_token_content" not used Statement "ADD" is obsolete * Some fixes Line break multiple parameters Compare operator "GE" not preferred Compare operator "EQ" not preferred * ops, fixing bug * Compare operator "EQ" not preferred * Statement "ADD" is obsolete * Some fixes Statement "ADD" is obsolete Statement "SUBTRACT" is obsolete Too many parenthesis, complex * Some fixes Omit default parameter name "FIRST_TOKEN" Statement "SUBTRACT" is obsolete Statement "ADD" is obsolete * several fixes * Update y_check_unit_test_assert.clas.abap * Update abaplint.json * Update abaplint.json * Update abaplint.json * Several fixes * several fixes * SEVERAL FIXES * Update abaplint.json * Update abaplint.json * several fixes * Update abaplint.json * Update abaplint.json * Update abaplint.json * Update abaplint.json * a few fixes * Update abaplint.json * several fixes * Update abaplint.json * several fixes * Update abaplint.json * a few fixes * Update abaplint.json * Update y_exemption_general.clas.abap * Update y_test_code_detector.clas.abap * Update y_check_empty_catches.clas.abap * Don't mix RETURNING and EXPORTING/CHANGING paramet * Update abaplint.json * Update abaplint.json * Update abaplint.json Co-authored-by: Eugen Günther <64586309+eugen-guenther-sap@users.noreply.github.com> Co-authored-by: abaplint[bot] <24845621+abaplint[bot]@users.noreply.github.com> * Update changelog.txt * Update y_check_base.clas.abap * Update src/foundation/y_check_base.clas.abap Co-authored-by: abaplint[bot] <24845621+abaplint[bot]@users.noreply.github.com> * Update unit_test_assert.md * Feature allow pseudo comment exception (#361) * feature - allow pseudo comment exception * Update y_check_unit_test_assert.clas.abap * update * minor update * requested changes * Update src/profiles/y_profile_admin_classes.prog.abap Co-authored-by: abaplint[bot] <24845621+abaplint[bot]@users.noreply.github.com> * UX update * abaplint fix * Update y_check_base.clas.abap * Update y_profile_admin_classes.prog.abap * Update y_profile_manager.clas.abap * Update src/profiles/y_profile_admin_classes.prog.abap Co-authored-by: abaplint[bot] <24845621+abaplint[bot]@users.noreply.github.com> * Update y_profile_administrator.prog.xml * Update y_profile_admin_classes.prog.abap * Update y_profile_admin_classes.prog.abap * minor change * abaplint fix * Update y_check_base.clas.abap * update * update * Update y_profile_admin_classes.prog.abap * update * Update how-to-configure.md * Update how-to-configure.md * Update how-to-configure.md * Update changelog.txt Co-authored-by: Eugen Guenther Co-authored-by: Eugen Günther <64586309+eugen-guenther-sap@users.noreply.github.com> Co-authored-by: abaplint[bot] <24845621+abaplint[bot]@users.noreply.github.com> * Prefer LINE_EXISTS or LINE_INDEX to READ TABLE or LOOP AT (#355) * implements #286 * Update changelog.txt * Update check_documentation.md * demo + description * Create prefer-line-exists.md * Update y_check_unit_test_assert.clas.abap * fixing from/to * Update y_check_prefer_line_exists.clas.testclasses.abap Co-authored-by: Eugen Günther <64586309+eugen-guenther-sap@users.noreply.github.com> * Update changelog.txt * Update abaplint.json (#377) * adjust of ignore pseudocomment on relevant checks (#375) * adjust of ignore pseudocomment on relevant checks * update * update Co-authored-by: Lucas Borin <5233413+lucasborin@users.noreply.github.com> * changing default severity (#376) * changing default severity * fixing version * c_note * Update README.md * Update README.md * Update how-to-configure.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update how-to-configure.md * Update how-to-configure.md * Update how-to-configure.md * Update how-to-configure.md * Update how-to-configure.md * Update changelog.txt * Update README.md * Update how-to-configure.md * Update how-to-configure.md * Update how-to-configure.md * Update how-to-configure.md * Update how-to-configure.md Co-authored-by: estevao-schultz-neto-SAP <63100656+estevao-schultz-neto-SAP@users.noreply.github.com> * Update changelog.txt * Update changelog.txt * Update changelog.txt * fixing broken ut Co-authored-by: Eugen Guenther Co-authored-by: estevao-schultz-neto-SAP <63100656+estevao-schultz-neto-SAP@users.noreply.github.com> Co-authored-by: Eugen Günther <64586309+eugen-guenther-sap@users.noreply.github.com> Co-authored-by: abaplint[bot] <24845621+abaplint[bot]@users.noreply.github.com> --- README.md | 65 ++-- abaplint.json | 207 ++++-------- changelog.txt | 13 +- docs/check_documentation.md | 3 + docs/checks/prefer-line-exists.md | 57 ++++ docs/checks/prefer-new-to-create-object.md | 44 +++ docs/checks/unit_test_assert.md | 65 ++++ pages/how-to-configure.md | 105 +++--- src/categories/y_category_code_pal.clas.abap | 2 +- src/checks/y_check_branch_coverage.clas.abap | 23 +- src/checks/y_check_chain_decl_usage.clas.abap | 1 - .../y_check_check_stmnt_position.clas.abap | 18 +- src/checks/y_check_comment_position.clas.abap | 20 +- src/checks/y_check_comment_type.clas.abap | 14 +- src/checks/y_check_comment_usage.clas.abap | 49 ++- src/checks/y_check_cx_root_usage.clas.abap | 4 +- .../y_check_cyclomatic_complexity.clas.abap | 26 +- src/checks/y_check_db_access_in_ut.clas.abap | 50 +-- src/checks/y_check_empty_catches.clas.abap | 9 +- .../y_check_empty_if_branches.clas.abap | 14 +- src/checks/y_check_empty_procedures.clas.abap | 3 +- .../y_check_equals_sign_chaining.clas.abap | 4 +- .../y_check_external_call_in_ut.clas.abap | 31 +- src/checks/y_check_function.clas.abap | 5 +- .../y_check_function.clas.locals_imp.abap | 12 +- .../y_check_function.clas.testclasses.abap | 14 +- .../y_check_is_interface_in_class.clas.abap | 3 +- src/checks/y_check_magic_number.clas.abap | 8 +- .../y_check_max_nesting_depth.clas.abap | 28 +- .../y_check_method_output_param.clas.abap | 22 +- .../y_check_method_return_bool.clas.abap | 19 +- .../y_check_non_class_exception.clas.abap | 2 +- .../y_check_num_exec_statements.clas.abap | 2 +- .../y_check_num_public_attributes.clas.abap | 12 +- .../y_check_number_attributes.clas.abap | 14 +- src/checks/y_check_number_events.clas.abap | 2 +- .../y_check_number_interfaces.clas.abap | 2 +- src/checks/y_check_number_methods.clas.abap | 2 +- .../y_check_optional_parameters.clas.abap | 2 +- .../y_check_prefer_case_to_elseif.clas.abap | 2 +- src/checks/y_check_prefer_is_not.clas.abap | 18 +- ..._check_prefer_is_not.clas.testclasses.abap | 80 ++++- .../y_check_prefer_line_exists.clas.abap | 65 ++++ ...k_prefer_line_exists.clas.testclasses.abap | 141 ++++++++ .../y_check_prefer_line_exists.clas.xml | 17 + .../y_check_prefer_new_to_crt_obj.clas.abap | 44 +++ ...refer_new_to_crt_obj.clas.testclasses.abap | 68 ++++ .../y_check_prefer_new_to_crt_obj.clas.xml | 17 + .../y_check_procedure_coverage.clas.abap | 23 +- src/checks/y_check_profile_message.clas.abap | 56 ++-- .../y_check_pseudo_comment_usage.clas.abap | 38 ++- src/checks/y_check_receiving_usage.clas.abap | 10 +- src/checks/y_check_returning_name.clas.abap | 3 +- .../y_check_scope_of_variable.clas.abap | 3 +- src/checks/y_check_self_reference.clas.abap | 2 +- .../y_check_statement_coverage.clas.abap | 23 +- src/checks/y_check_test_seam_usage.clas.abap | 10 +- src/checks/y_check_unit_test_assert.clas.abap | 92 +++++ ...eck_unit_test_assert.clas.testclasses.abap | 307 +++++++++++++++++ src/checks/y_check_unit_test_assert.clas.xml | 17 + src/examples/y_demo_failures.clas.abap | 18 + .../y_demo_failures.clas.testclasses.abap | 15 + src/foundation/y_check_base.clas.abap | 146 ++++---- .../y_ci_check_registration.prog.abap | 30 +- src/foundation/y_clean_code_manager.clas.abap | 30 +- .../y_code_pal_pseudo_comments.dtel.xml | 23 ++ src/foundation/y_code_pal_service.clas.abap | 3 +- src/foundation/y_exemption_general.clas.abap | 9 +- src/foundation/y_exemption_of_class.clas.abap | 125 ++----- .../y_exemption_of_function_group.clas.abap | 53 ++- .../y_exemption_of_program.clas.abap | 42 +-- .../y_if_clean_code_manager.intf.abap | 37 +- .../y_object_creation_date.clas.abap | 9 +- .../y_pseudo_comment_detector.clas.abap | 6 +- src/foundation/y_test_code_detector.clas.abap | 28 +- ...y_test_code_detector.clas.testclasses.abap | 14 +- src/profiles/y_alv_events.clas.abap | 4 +- src/profiles/y_alv_tree_control.clas.abap | 23 +- .../y_alv_tree_control.clas.testclasses.abap | 1 - src/profiles/y_if_list.intf.abap | 2 +- src/profiles/y_list.clas.abap | 6 +- src/profiles/y_list.clas.testclasses.abap | 20 +- .../y_profile_admin_classes.prog.abap | 315 +++++++++++------- src/profiles/y_profile_admin_data.prog.abap | 2 + .../y_profile_administrator.prog.abap | 2 +- src/profiles/y_profile_administrator.prog.xml | 53 ++- src/profiles/y_profile_manager.clas.abap | 149 +++++---- src/profiles/ytab_checks.tabl.xml | 34 +- src/profiles/ytab_delegates.tabl.xml | 4 - src/profiles/ytab_profiles.tabl.xml | 12 - src/y_code_pal_version.intf.abap | 2 +- 91 files changed, 2170 insertions(+), 1059 deletions(-) create mode 100644 docs/checks/prefer-line-exists.md create mode 100644 docs/checks/prefer-new-to-create-object.md create mode 100644 docs/checks/unit_test_assert.md create mode 100644 src/checks/y_check_prefer_line_exists.clas.abap create mode 100644 src/checks/y_check_prefer_line_exists.clas.testclasses.abap create mode 100644 src/checks/y_check_prefer_line_exists.clas.xml create mode 100644 src/checks/y_check_prefer_new_to_crt_obj.clas.abap create mode 100644 src/checks/y_check_prefer_new_to_crt_obj.clas.testclasses.abap create mode 100644 src/checks/y_check_prefer_new_to_crt_obj.clas.xml create mode 100644 src/checks/y_check_unit_test_assert.clas.abap create mode 100644 src/checks/y_check_unit_test_assert.clas.testclasses.abap create mode 100644 src/checks/y_check_unit_test_assert.clas.xml create mode 100644 src/foundation/y_code_pal_pseudo_comments.dtel.xml diff --git a/README.md b/README.md index ba6c1986..c892b80a 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,32 @@ # code pal for ABAP -[![abap package version](https://img.shields.io/endpoint?url=https://shield.abap.space/version-shield-json/github/SAP/code-pal-for-abap/src/y_code_pal_version.intf.abap/abap&label=version)](https://github.com/SAP/code-pal-for-abap/blob/master/changelog.txt) +[![abap package version](https://img.shields.io/endpoint?url=https://shield.abap.space/version-shield-json/github/SAP/code-pal-for-abap/src/y_code_pal_version.intf.abap/abap&label=version)](changelog.txt) [![license](https://img.shields.io/github/license/SAP/code-pal-for-abap)](LICENSE) -This tool supports you in writing a clean ABAP code. Clean Code allows you to read your code like well-written prose, it is easily understandable, maintainable, and extensible. In addition, you can write high quality and reliable Unit Tests without hurdles and thereby reduce the total cost of ownership of the software. +Based on the [Clean ABAP](https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md) style guide, this tool contains a set of checks to guarantee the [Clean ABAP](https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md) adherence. +Together, we both support you in writing a clean ABAP code. -Furthermore... It's **free** and **open-source**! +❣️ It's **free** and **open-source**. -It is licensed under the Apache License, Version 2.0 - see [LICENSE](LICENSE). - -## News - -**:warning: Migration Required :warning:** - -From version `v1.01.0` to `v1.02.0` the folder logic was changed, and the abapGit is not able to perform this migration automatically. Therefore, please, follow the step-by-step described in [How To Migrate](pages/how-to-migrate.md)! +## Features -Check the [change log](changelog.txt) for further information. +- Supported by Code Inspector (`SCI` / `SCII`) and ABAP Test Cockpit (ATC) (`SE80` / Eclipse); +- Ignores automatically generated code; +- Supports exemptions; +- Provides a new user-friendly way to create variants ([Profile Management](pages/how-to-configure.md)); +- Allows configuration based on: + - Threshold; + - Severity / Priority; + - Validity for productive code, test code, or both; + - Validity for objects created since a specific date; + - Validity period; + - Allow / Deny exemption. + +⚠️ Tool is not RFC-Enabled ([#268](https://github.com/SAP/code-pal-for-abap/issues/268)). -## Features +⚠️ Severities set to `Notification` / `Priority 3` by default ([#368](https://github.com/SAP/code-pal-for-abap/issues/368)). -- Checks are ready-to-use; -- Checks can be executed via SUT, SCI, SCII (Code-Inspector) and via ATC (e.g. directly in SE80, Eclipse...); -- Automatic exclusion of code which shall not be checked (e.g. generated code); -- The scope is customizable (filter option on object creation date); -- Thresholds are customizable; -- Message severity is customizable (error, warning, or notification); -- Checking may be activated in productive-code and/or test-code (customizable); -- Findings can be suppressed via Code-Inspector Pragmas; -- Usage of a "Profile Management Tool" (Optional). - -The Profile Management Tool, which is an alternative of working with SCI based variant(s), offers among others: -- An user friendly UI; -- A user-based or group-based execution of Checks; -- Creation, assignment and unassignment of Profiles (unassigning a profile will only delete it if no checks are registered to this profile); -- Import/Export a profile among systems (download/upload function – UI button or API Post Service); -- Single-Click registration of all code pal checks at once to a profile (UI button); -- Multiple execution of several profiles at the same time (the sharpest/strongest and time valid configuration/threshold will be taken); -- Delegation principle to facilitate team work (all delegates, for instance: team members, can work with the same profile); - -:warning: The checks are not RFC-Enabled due to local dependencies. - -## List of Checks +## Set of Checks - [Check Documentation](docs/check_documentation.md) @@ -56,11 +42,14 @@ The Profile Management Tool, which is an alternative of working with SCI based v - **[Execute](pages/how-to-execute.md)** - **[Contribute](pages/how-to-contribute.md)** -## Further Reading +## Recommended Readings -- [ABAP Styleguides on Clean Code](https://github.com/SAP/styleguides/blob/master/clean-abap/CleanABAP.md) -- [Writing Testable Code for ABAP](https://open.sap.com/courses/wtc1/items/2gzG0sRlN1yjkTUREB02L9) -- [ABAP Development for S/4HANA](https://open.sap.com/courses/a4h1) +- [Clean ABAP](https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md) - [ABAP 7.40 Quick Reference](https://blogs.sap.com/2015/10/25/abap-740-quick-reference/) - [ABAP Built-in Functions](https://blogs.sap.com/2015/11/30/reminder-abap-built-in-functions/) - [ABAP - Release-Specific Changes](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/abennews.htm) + +## Recommended Courses + +- [Writing Testable Code for ABAP](https://open.sap.com/courses/wtc1/items/2gzG0sRlN1yjkTUREB02L9) +- [ABAP Development for S/4HANA](https://open.sap.com/courses/a4h1) diff --git a/abaplint.json b/abaplint.json index 0c8cbe25..a0cffa68 100644 --- a/abaplint.json +++ b/abaplint.json @@ -12,16 +12,11 @@ "url": "https://github.com/abaplint/deps", "folder": "/deps1", "files": "/src/**/*.*" - }, - { - "url": "https://github.com/abapGit/abapGit", - "folder": "/deps2", - "files": "/src/**/*.*" } ], "syntax": { "version": "v740sp08", - "errorNamespace": "^(Z|Y|LCL_|TY_|LIF_)", + "errorNamespace": "^(Y)", "globalConstants": ["cntb_btype_button", "scan_struc_stmnt_type", "scan_stmnt_type", "scan_struc_type", "scan_token_type"], "globalMacros": [] }, @@ -29,114 +24,64 @@ "7bit_ascii": true, "abapdoc": false, "allowed_object_naming": true, - "allowed_object_types": { - "exclude": [], - "severity": "Error", - "allowed": [] - }, + "allowed_object_types": false, "ambiguous_statement": false, - "avoid_use": { - "exclude": [], - "severity": "Error", - "define": true, - "endselect": true, - "execSQL": true, - "kernelCall": true, - "communication": true, - "statics": true, - "systemCall": true, - "defaultKey": false, - "break": false, - "describeLines": false - }, + "avoid_use": false, "begin_end_names": true, "begin_single_include": true, - "call_transaction_authority_check": true, - "chain_mainly_declarations": { - "exclude": [], - "severity": "Error", - "definitions": true, - "write": true, - "move": true, - "refresh": true, - "unassign": true, - "clear": true, - "hide": true, - "free": true, - "include": true, - "check": true - }, + "call_transaction_authority_check": false, + "chain_mainly_declarations": true, "check_abstract": true, "check_comments": false, - "check_ddic": true, + "check_ddic": false, "check_include": true, "check_no_handler_pragma": true, "check_subrc": false, "check_syntax": true, "check_text_elements": false, - "check_transformation_exists": true, + "check_transformation_exists": false, "class_attribute_names": false, "cloud_types": true, "colon_missing_space": true, - "commented_code": false, + "commented_code": true, "constructor_visibility_public": true, "contains_tab": false, - "cyclomatic_complexity": { - "exclude": [], - "severity": "Error", - "max": 20 - }, - "definitions_top": false, + "cyclomatic_complexity": true, + "dangerous_statement": true, + "db_operation_in_loop": false, + "definitions_top": true, "description_empty": true, - "double_space": false, + "double_space": { + "startParen": false + }, "downport": true, "empty_line_in_statement": false, "empty_statement": true, - "empty_structure": false, + "empty_structure": true, "exit_or_check": false, - "exporting": false, - "forbidden_identifier": { - "exclude": [], - "severity": "Error", - "check": [] - }, - "forbidden_pseudo_and_pragma": { - "exclude": [], - "severity": "Error", - "pseudo": [], - "pragmas": [], - "ignoreGlobalClassDefinition": false, - "ignoreGlobalInterface": false - }, - "forbidden_void_type": { - "exclude": [], - "severity": "Error", - "check": [] - }, + "exporting": true, + "forbidden_identifier": false, + "forbidden_pseudo_and_pragma": false, + "forbidden_void_type": false, "form_tables_obsolete": true, - "fully_type_constants": { - "exclude": [], - "severity": "Error", - "checkData": true - }, + "fully_type_constants": false, "function_module_recommendations": true, - "functional_writing": { - "exclude": [], - "severity": "Error", - "ignoreExceptions": true - }, + "functional_writing": true, "global_class": true, "identical_conditions": true, "identical_contents": true, "identical_form_names": true, + "identical_descriptions": false, "if_in_if": true, "implement_methods": true, "in_statement_indentation": false, "indentation": false, "inline_data_old_versions": true, - "keep_single_parameter_on_one_line": false, - "keyword_case": false, - "line_break_multiple_parameters": false, + "intf_referencing_clas": { + "allow": ["cl_ci_scan"] + }, + "keep_single_parameter_on_one_line": true, + "line_break_multiple_parameters": true, "line_break_style": true, "line_length": false, "line_only_punc": false, @@ -144,98 +89,76 @@ "local_testclass_location": true, "local_variable_names": false, "main_file_contents": true, - "many_parenthesis": false, + "many_parenthesis": true, + "max_one_method_parameter_per_line": true, + "method_implemented_twice": true, "max_one_statement": true, "message_exists": true, "method_length": false, - "method_overwrites_builtin": false, + "method_overwrites_builtin": true, "method_parameter_names": false, - "mix_returning": false, + "mix_returning": true, + "modify_only_own_db_tables": false, "msag_consistency": true, - "nesting": false, + "nesting": true, "names_no_dash": true, - "newline_between_methods": { - "exclude": [], - "severity": "Error", - "count": 3, - "logic": "less" - }, + "newline_between_methods": true, "no_public_attributes": false, + "no_yoda_conditions": false, "object_naming": false, - "obsolete_statement": { - "exclude": [], - "severity": "Error", - "refresh": true, - "compute": true, - "add": false, - "subtract": false, - "multiply": true, - "move": true, - "divide": true, - "requested": true, - "occurs": true, - "setExtended": true, - "withHeaderLine": true, - "fieldSymbolStructure": true, - "typePools": true, - "load": true - }, - "omit_parameter_name": false, + "obsolete_statement": true, + "omit_parameter_name": true, "omit_receiving": true, + "parser_702_chaining": false, "parser_error": true, "parser_missing_space": true, "prefer_inline": false, - "prefer_is_not": false, + "prefer_is_not": true, + "prefer_raise_exception_new": true, "prefer_returning_to_exporting": true, "prefer_xsdbool": true, - "preferred_compare_operator": false, - "prefix_is_current_class": false, + "preferred_compare_operator": true, + "prefix_is_current_class": true, "reduce_string_templates": true, "release_idoc": true, "remove_descriptions": false, - "rfc_error_handling": false, - "selection_screen_naming": { - "exclude": [], - "severity": "Error", - "patternKind": "required", - "ignoreNames": [], - "ignorePatterns": [], - "parameter": "^P_.+$", - "selectOption": "^S_.+$" - }, - "sequential_blank": false, - "short_case": { - "exclude": [], - "severity": "Error", - "length": 1, - "allow": [] + "rfc_error_handling": true, + "select_add_order_by": false, + "select_performance": { + "severity": "Warning" }, + "selection_screen_naming": false, + "sequential_blank": true, + "short_case": true, "sicf_consistency": true, "space_before_colon": true, - "space_before_dot": { - "exclude": [], - "severity": "Error", - "ignoreGlobalDefinition": true, - "ignoreExceptions": true + "space_before_dot": true, + "sql_escape_host_variables": { + "severity": "Warning" }, - "sql_escape_host_variables": false, - "start_at_tab": false, + "start_at_tab": true, "superclass_final": true, "sy_modification": true, "tabl_enhancement_category": true, "try_without_catch": true, "type_form_parameters": true, "types_naming": false, + "uncaught_exception": false, "unknown_types": true, "unreachable_code": true, - "unused_methods": false, + "unsecure_fae": false, + "unused_methods": true, "unused_types": true, - "unused_variables": false, + "unused_variables": { + "severity": "Warning" + }, "use_bool_expression": true, - "use_line_exists": false, + "use_class_based_exceptions": true, + "use_line_exists": true, "use_new": true, "when_others_last": true, "whitespace_end": true, - "xml_consistency": true + "xml_consistency": true, + "keyword_case": false } } diff --git a/changelog.txt b/changelog.txt index fd9a533c..9c1311fe 100644 --- a/changelog.txt +++ b/changelog.txt @@ -10,7 +10,18 @@ Legend Upgrade Note ------------------ -Whenever you upgrade code pal for ABAP, it is highly recommended to execute the Y_CI_CHECK_REGISTRATION report to activate/reactivate the Checks (SE38 transaction) and regenerate the respective code inspector variant (SCI transaction) +Whenever you upgrade code pal for ABAP, it is highly recommended to execute the Y_CI_CHECK_REGISTRATION report to activate/reactivate the Checks (SE38 transaction) and regenerate the respective Code Inspector Variant (SCI transaction) + +2021-04-23 v.1.14.0 +------------------ +! Notification as Default Severity (#368) ++ Prefer LINE_EXISTS or LINE_INDEX to READ TABLE or LOOP AT (#355) ++ Additional option to disable exceptions/pragmas (#329) +* Diffs for TABL (#359) ++ Unit Test Without/With Invalid Assert (#288) ++ Prefer NEW to CREATE OBJECT (#283) +* Standard functions in Prefer IS NOT to NOT IS (#338) +* In the profile feature, you can add all the missing checks (#346) 2021-04-08 v.1.13.2 ------------------ diff --git a/docs/check_documentation.md b/docs/check_documentation.md index 056659b6..07dad1c5 100644 --- a/docs/check_documentation.md +++ b/docs/check_documentation.md @@ -40,6 +40,8 @@ - [Number of Output Parameter](checks/number-output-parameter.md) - [Prefer CASE to ELSEIF](checks/prefer-case-to-elseif.md) - [Prefer IS NOT to NOT IS](checks/prefer-is-not-to-not-is.md) +- [Prefer LINE_EXISTS or LINE_INDEX to READ TABLE or LOOP AT](checks/prefer-line-exists.md) +- [Prefer NEW to CREATE OBJECT](checks/prefer-new-to-create-object.md) - [Pseudo Comment Usage](checks/pseudo-comment-usage.md) - [Omit Optional EXPORTING](checks/omit-optional-exporting.md) - [Optional Parameters](checks/optional-parameters.md) @@ -50,3 +52,4 @@ - [Self-Reference](checks/self-reference.md) - [TEST-SEAM Statement Usage](checks/test-seam-usage.md) - [Unit-Test Coverages (Statement, Branch and Procedure)](checks/unit-test-coverages.md) +- [Unit-Test Assert Validator](checks/unit_test_assert.md) diff --git a/docs/checks/prefer-line-exists.md b/docs/checks/prefer-line-exists.md new file mode 100644 index 00000000..c85633f5 --- /dev/null +++ b/docs/checks/prefer-line-exists.md @@ -0,0 +1,57 @@ +[code pal for ABAP](../../README.md) > [Documentation](../check_documentation.md) > [Prefer LINE_EXISTS or LINE_INDEX to READ TABLE or LOOP AT](prefer-line-exists.md) + +## Prefer LINE_EXISTS or LINE_INDEX to READ TABLE or LOOP AT + +### What is the Intent of the Check? + +Prefer `LINE_EXISTS` or `LINE_INDEX` over `READ TABLE` or `LOOP AT` as they avoid needlessly longer statements. + +### How to solve the issue? + +Preferably, use `LINE_EXISTS` to check whether the row of an internal table exists, and `LINE_INDEX` to check the row index. + +### What to do in case of exception? + +In exceptional cases, you can suppress this finding by using the pseudo comment `"#EC PREF_LINE_EX`: + +```abap + READ TABLE my_table TRANSPORTING NO FIELDS WITH KEY key = 'A'. "#EC PREF_LINE_EX +``` + +```abap + LOOP AT my_table REFERENCE INTO DATA(line) WHERE key = 'A'. "#EC PREF_LINE_EX + ... + ENDLOOP. +``` + +### Example + +Before the check: + +```abap + READ TABLE my_table TRANSPORTING NO FIELDS WITH KEY key = 'A'. + + IF sy-subrc = 0. + line_index = sy-tabix. + line_exists = abap_true. + ENDIF. +``` + +```abap + LOOP AT my_table REFERENCE INTO DATA(line) WHERE key = 'A'. + line_index = sy-tabix. + line_exists = abap_true. + EXIT. + ENDLOOP. +``` + +After the check: + +```abap + DATA(index) = line_index( my_table[ key = 'A' ] ). + DATA(exists) = xsdbool( line_exists( my_table[ key = 'A' ] ) ). +``` + +### Further Readings & Knowledge + +* [ABAP Styleguides on Clean Code](https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-line_exists-to-read-table-or-loop-at) diff --git a/docs/checks/prefer-new-to-create-object.md b/docs/checks/prefer-new-to-create-object.md new file mode 100644 index 00000000..e61e8c20 --- /dev/null +++ b/docs/checks/prefer-new-to-create-object.md @@ -0,0 +1,44 @@ +[code pal for ABAP](../../README.md) > [Documentation](../check_documentation.md) > [Prefer New to Create Object](prefer_new_to_create_object.md) + +## Prefer New to Create Object + +### What is the Intent of the Check? + +Prefer `NEW` over `CREATE OBJECT` as it avoids needlessly longer statements. + +### How to solve the issue? + +Preferably, use `NEW` for creating new objects/instances. + +### What to do in case of exception? + +In exceptional cases, you can suppress this finding by using the pseudo comment `"#EC PREF_NEW`: + +```abap + DATA prefer_new_to_crt_obj TYPE REF TO y_check_prefer_new_to_crt_obj. + CREATE OBJECT prefer_new_to_crt_obj. "#EC PREF_NEW +``` + +### Example + +Before the check: + +```abap + DATA prefer_new_to_create_object TYPE REF TO y_check_prefer_new_to_crt_obj. + CREATE OBJECT prefer_new_to_create_object. +``` + +After the check: + +```abap + DATA(prefer_new_to_create_object) = NEW y_check_prefer_new_to_crt_obj( ). +``` + +```abap + DATA prefer_new_to_create_object TYPE REF TO y_check_prefer_new_to_crt_obj. + prefer_new_to_create_object = NEW #( ). +``` + +### Further Readings & Knowledge + +* [ABAP Styleguides on Clean Code](https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-new-to-create-object) diff --git a/docs/checks/unit_test_assert.md b/docs/checks/unit_test_assert.md new file mode 100644 index 00000000..21924461 --- /dev/null +++ b/docs/checks/unit_test_assert.md @@ -0,0 +1,65 @@ +[code pal for ABAP](../../README.md) > [Documentation](../check_documentation.md) > [Unit-Test Assert Validator](unit_test_assert.md) + +## Unit-Test Assert Validator + +### What is the Intent of the Check? + +This check verifies invalid assertions in unit tests. +It supports the `CL_ABAP_UNIT_ASSERT=>ASSERT*` and `CL_AUNIT_ASSERT=>ASSERT*`. + +### How does the check work? + +It checks for actual (`act`) or expected (`exp`) invalid value(s), for instance: +- When both are using the same variable for the Assertion (which will always return TRUE); +- When both are hardcoded. + +### How to solve the issue? + +Fix the actual (`act`) or expected (`exp`) value(s) in the unit test assertion in order to achieve a meaningful and real Assertion. + +### What to do in case of exception? + +In exceptional cases (if any), you can suppress this finding by using the pseudo comment `"#EC UT_ASSERT` which has to be placed after the assertion statement: + +```abap +cl_abap_unit_assert=>assert_equals( act = sum + exp = sum ). "#EC UT_ASSERT +``` + +### Example + +Before the check: + +```abap +METHOD sum. + " given + DATA(first) = 10. + DATA(second) = 10. + " when + DATA(sum) = first + second. + " then + cl_abap_unit_assert=>assert_equals( act = sum + exp = sum ). +ENDMETHOD. +``` + +After the check: + +```abap +METHOD sum. + " given + DATA(first) = 10. + DATA(second) = 10. + " when + DATA(sum) = first + second. + " then + cl_abap_unit_assert=>assert_equals( act = sum + exp = 20 ). +ENDMETHOD. +``` + +### Further Readings & Knowledge + +* [Clean ABAP: Don't obsess about coverage](https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#dont-obsess-about-coverage) + + diff --git a/pages/how-to-configure.md b/pages/how-to-configure.md index 7f99c95e..b13f74f0 100644 --- a/pages/how-to-configure.md +++ b/pages/how-to-configure.md @@ -4,74 +4,81 @@ ## How to Configure -**The default customizing (initial values) is not an SAP delivered standard value.** +⚠️This documentation describes how to configure using the `Profile Management Tool` feature only. -The tool is 100% compatible with the SAP CI Framework (Code Inspector). That is, SAP Transactions: SCI and SCII. By means of these transactions, it is possible to create/run/save an inspection using our delivered CHECKS (the checks can be found under the "CODE PAL FOR ABAP" category). -It is also possible to create a CI-Variant and run the selected CHECKS using this variant at any time. This CI-Variant can be also used in SUT (ABAP CHECK REPORT), ATC or even using SAP-Workbench ABAP Editors (e.g.: SE80) or ADT (e.g.: Eclipse) with ATC/CI Integration directly (the CI-Variant will be asked). +💡Alternatively, you can use the SAP Code Inspector variants in the `SCI` transaction. -In summary, it is possible to use our tool directly in SCI/SCII, via ATC Integration, via API Call, via SUT, via CI-Variant or via Profile(s). -But keep in mind, one has to choose betweeen using CI-Variants (Code Inspector Variants) or Using Profile/s (via Transaction: Y_CODE_PAL_PROFILE, delivered along with the toolkit). Both features cannot be used in paralell in the same system for the same user. For more details on using CI-Variant/s and Profile/s, please check the section: [How to Execute](https://github.com/SAP/code-pal-for-abap/blob/master/pages/how-to-execute.md). +Table of Contents: -Furtheremore, every single CHECK can be configurable independenlty. +- [How to Configure](#how-to-configure) + - [Profiles](#1-profiles) + - [Delegates](#2-delegates) + - [Checks](#3-checks) +- [Further Features](#further-features) + - [Import / Export Profile](#import--export-profile) + - [Import via API](#import-via-api) + - [Add / Remove All Checks](#add--remove-all-checks) + - [Add Missing Checks](#add-missing-checks) -By the Check configuration: You can, +💡 The transaction `Y_CODE_PAL_PROFILE` provides access to the `Profile Management Tool`. -* Define check's validity period; -* Restrict to objects created since a specific date; -* Define check's severity; -* Define check's threshold (if applicable); -* Define if it is applicable in productive code (if applicable); -* Define if it is applicable in test code (if applicable). +### Profiles -Check behavior: +> Profiles are similar to Code Inspector Variants. -* If using a CI-Variant, just one variant can be executed per time. -* If using a profile, first, at least one profile should be assigned to your user. Then, all checks assigned to this profle will be executed. But if so, the usage of a CI-variant is no longer possible. The profile overrules a CI-variant! In order to use again a CI-variant, one has to unassign the profile(s) of his/her user; -* If multiple profiles are assigned to your user, all checks assigned to all profiles will be executed and the "strongest" or "sharpest" thresholds will be taken; -* If have no profile assigned to your user, the execution of the checks have to be made live in SCI/SCII or by means of a CI-Variant. +Behavior: -Profile behavior: +- (❗) If you assign a Profile to your user, **it overwrites the Code Inspector variant** (❗); +- If you assign multiple Profiles to your user, the tool will combine them in runtime; +- You can assign someone else Profile to your user; +- The Profile is deleted once it has no check and assigned to nobody. -* If you unassign a profile from your user, it will not delete it from the database. It means, you can reassign it to your user, and all the checks with respective customization will return; -* If you assign the `Y_CHECK_PROFILE_MESSAGE` check to the profile, you will receive an info message every time you execute the global check variant. It means, not all the checks from the variant were executed, but so the ones related to the active profile. +To create or assign it, click on the `+` button, and inform the Profile name: -Threshold behavior: - -* If you have multiple profiles, and the same check assigned to two or more profiles, it will use the check with the strongest threshold. - -### 1. Create or Assign a Profile +![create a profile](imgs/create-profile.png) -Start transaction `Y_CODE_PAL_PROFILE`, click on the `+` button, and inform the profile name. +### Delegates -![create a profile](imgs/create-profile.png) +> Delegates are the Profile owners who are allowed to configure it; +> Multiple delegates are allowed. -You can assign an already existing profile to your user. It is useful for working on a team based on the same checks. +Behavior: -### 2. Assign Delegates +- If you aren't a Delegate, you won't be able to add / change / remove a Delegate or Check. -Delegates are users which can maintain the checks. As you are creating a new check, you will be added automatically. In case you want to add someone else as an owner, click on the `+` button and inform his/her user name. +To add someone else, click on the `+` button and inform his / her user name: ![assign delegate](imgs/assign-delegate.png) -### 3. Assign Checks +### Checks -Click on the `+` button and assign the checks. +> Checks are the rules based on the [Clean ABAP](https://github.com/SAP/styleguides/blob/master/clean-abap/CleanABAP.md) style guide. -![assign check](imgs/assign-check.png) +Behavior: + +- You can define a Check threshold (if applicable); +- You can define a Check severity / priority (error / priority 1, warning / priority 2, or notification / priority 3) +- You can define a Check filter on productive code, test code, or both (if applicable); +- You can define a Check filter on object creation date; +- You can define a Check validity period; +- You can define if a Check can/cannot be exempt via pseudo-comments (if applicable). +- If you have multiple Profiles assigned to your user, the check with the"strongest" or "sharpest" thresholds will be taken; + +To assign them to your Profile, click on the `+` button: -If you want, you can change the default configuration: +![assign check](imgs/assign-check.png) ![customize check](imgs/customize-check.png) -If you do not understand the check meaning, you can check its documentation: +💡 You can use the documentation button to navigate to the Check documentation: ![check documentation](imgs/check-documentation.png) -## How to export and import customization +## Further Features -You can export and import profiles, with respective delegates and checks, using a `JSON` file. +### Import / Export Profile -It is useful when you work with multiple systems, and you want to sync the profiles between them. +You can import and export a Profile with its Delegates and Checks using a `JSON` file, here: ![import and export feature](imgs/import-export-feature.png) @@ -79,10 +86,22 @@ It is useful when you work with multiple systems, and you want to sync the profi Once you export a profile to a `JSON` file, you can import it using the service created in the [How To Install](how-to-install.md) guide. -To consume the API, you have to `POST` the `JSON` file to the service with the respective authentication you configured to the service (usually basic, user/pass) and with the header `Content-Type` as `application/json` and `action` as `import_profile`. +To consume the API, you have to `POST` the `JSON` file to the service with the respective authentication you configured to the service (usually basic, user/pass) and with the headers `Content-Type` as `application/json` and `action` as `import_profile`. + +Possible returns: + +- `HTTP 400 - Bad Request` if the file format is not valid, or if the request has a wrong `Content-Type`; +- `HTTP 403 - Forbidden` if the profile already exists in the system and the authentication user is not listed as a delegate; +- `HTTP 500 - Internal Server Error` if the functionality is not working as expected. + +### Add / Remove All Checks + +You can add all and remove all the Checks from a Profile, here: + +![add all and remove all](imgs/) -The API returns an `HTTP 400 - Bad Request` if the file format is not valid, or if the request has a wrong `Content-Type`. +### Add Missing Checks -The API returns an `HTTP 403 - Forbidden` if the profile already exists in the system and the authentication user is not listed as a delegate. +You can add all the missing checks, comparing your Profile and the available Checks, here: -The API returns an `HTTP 500 - Internal Server Error` if the functionality is not working as expected. +![missing checks](imgs/) diff --git a/src/categories/y_category_code_pal.clas.abap b/src/categories/y_category_code_pal.clas.abap index 1206d627..850b3614 100644 --- a/src/categories/y_category_code_pal.clas.abap +++ b/src/categories/y_category_code_pal.clas.abap @@ -22,7 +22,7 @@ CLASS Y_CATEGORY_CODE_PAL IMPLEMENTATION. METHOD constructor. super->constructor( ). - description = get_class_description( ). + description = get_class_description( ). category = 'CL_CI_CATEGORY_TOP'. position = '001'. ENDMETHOD. diff --git a/src/checks/y_check_branch_coverage.clas.abap b/src/checks/y_check_branch_coverage.clas.abap index fd4148c8..f1d551c1 100644 --- a/src/checks/y_check_branch_coverage.clas.abap +++ b/src/checks/y_check_branch_coverage.clas.abap @@ -5,7 +5,6 @@ CLASS y_check_branch_coverage DEFINITION PUBLIC INHERITING FROM y_check_base CRE PROTECTED SECTION. METHODS execute_check REDEFINITION. METHODS inspect_tokens REDEFINITION. - ENDCLASS. @@ -16,14 +15,14 @@ CLASS y_check_branch_coverage IMPLEMENTATION. METHOD constructor. super->constructor( ). - version = '0001'. + version = version + 1. - settings-prio = c_note. settings-threshold = 70. settings-is_threshold_reversed = abap_true. settings-disable_on_prodcode_selection = abap_true. settings-disable_on_testcode_selection = abap_true. settings-apply_on_test_code = abap_false. + settings-ignore_pseudo_comments = abap_true. settings-documentation = |{ c_docs_path-checks }unit-test-coverages.md|. set_check_message( 'Branch Coverage must be higher than &2%! (&1%<=&2%)' ). @@ -50,14 +49,14 @@ CLASS y_check_branch_coverage IMPLEMENTATION. RETURN. ENDIF. - raise_error( statement_level = 1 - statement_index = 1 - statement_from = 1 - error_priority = check_configuration-prio - parameter_01 = |{ branch }| - parameter_02 = |{ check_configuration-threshold }| - parameter_03 = |{ coverage->get_total( ) }| - parameter_04 = |{ coverage->get_executed( ) }| ). + raise_error( statement_level = 1 + statement_index = 1 + statement_from = 1 + error_priority = check_configuration-prio + parameter_01 = |{ branch }| + parameter_02 = |{ check_configuration-threshold }| + parameter_03 = |{ coverage->get_total( ) }| + parameter_04 = |{ coverage->get_executed( ) }| ). ENDMETHOD. @@ -65,6 +64,4 @@ CLASS y_check_branch_coverage IMPLEMENTATION. METHOD inspect_tokens. RETURN. ENDMETHOD. - - ENDCLASS. diff --git a/src/checks/y_check_chain_decl_usage.clas.abap b/src/checks/y_check_chain_decl_usage.clas.abap index 62da2178..3dccb262 100644 --- a/src/checks/y_check_chain_decl_usage.clas.abap +++ b/src/checks/y_check_chain_decl_usage.clas.abap @@ -23,7 +23,6 @@ CLASS Y_CHECK_CHAIN_DECL_USAGE IMPLEMENTATION. settings-pseudo_comment = '"#EC CHAIN_DECL_USAG' ##NO_TEXT. settings-disable_threshold_selection = abap_true. settings-threshold = 0. - settings-prio = c_warning. settings-documentation = |{ c_docs_path-checks }chain-declaration-usage.md|. set_check_message( 'Do not chain up-front declarations!' ). diff --git a/src/checks/y_check_check_stmnt_position.clas.abap b/src/checks/y_check_check_stmnt_position.clas.abap index dc3713c7..1d9bfbbe 100644 --- a/src/checks/y_check_check_stmnt_position.clas.abap +++ b/src/checks/y_check_check_stmnt_position.clas.abap @@ -59,15 +59,15 @@ CLASS y_check_check_stmnt_position IMPLEMENTATION. METHOD is_not_relevant_token. - result = xsdbool( token EQ 'METHOD' - OR token EQ 'FORM' - OR token EQ 'FUNCTION' - OR token EQ 'MODULE' - OR token EQ 'DATA' - OR token EQ 'TYPES' - OR token EQ 'CHECK' - OR token EQ 'FIELD-SYMBOLS' - OR token EQ 'CONSTANTS' ). + result = xsdbool( token = 'METHOD' + OR token = 'FORM' + OR token = 'FUNCTION' + OR token = 'MODULE' + OR token = 'DATA' + OR token = 'TYPES' + OR token = 'CHECK' + OR token = 'FIELD-SYMBOLS' + OR token = 'CONSTANTS' ). ENDMETHOD. diff --git a/src/checks/y_check_comment_position.clas.abap b/src/checks/y_check_comment_position.clas.abap index a3e57e3f..de741a63 100644 --- a/src/checks/y_check_comment_position.clas.abap +++ b/src/checks/y_check_comment_position.clas.abap @@ -9,9 +9,6 @@ CLASS y_check_comment_position DEFINITION PUBLIC INHERITING FROM y_check_base CR METHODS has_wrong_position IMPORTING statement TYPE sstmnt RETURNING VALUE(result) TYPE abap_bool. - METHODS get_first_character IMPORTING token TYPE stokesx - RETURNING VALUE(result) TYPE char1. - METHODS is_pseudo_comment IMPORTING token TYPE stokesx RETURNING VALUE(result) TYPE abap_bool. @@ -29,13 +26,14 @@ ENDCLASS. -CLASS Y_CHECK_COMMENT_POSITION IMPLEMENTATION. +CLASS y_check_comment_position IMPLEMENTATION. METHOD constructor. super->constructor( ). settings-disable_threshold_selection = abap_true. + settings-ignore_pseudo_comments = abap_true. settings-threshold = 0. settings-documentation = |{ c_docs_path-checks }comment-position.md|. @@ -44,7 +42,6 @@ CLASS Y_CHECK_COMMENT_POSITION IMPLEMENTATION. METHOD inspect_tokens. - CHECK statement-type = 'P'. CHECK has_wrong_position( statement ). @@ -56,8 +53,8 @@ CLASS Y_CHECK_COMMENT_POSITION IMPLEMENTATION. raise_error( statement_level = statement-level statement_index = index - statement_from = statement-from - error_priority = configuration-prio ). + statement_from = statement-from + error_priority = configuration-prio ). ENDMETHOD. @@ -102,15 +99,6 @@ CLASS Y_CHECK_COMMENT_POSITION IMPLEMENTATION. ENDMETHOD. - METHOD get_first_character. - TRY. - result = token-str(1). - CATCH cx_sy_range_out_of_bounds. - CLEAR result. - ENDTRY. - ENDMETHOD. - - METHOD is_pseudo_comment. TRY. result = xsdbool( token-str(4) = '"#EC' ). diff --git a/src/checks/y_check_comment_type.clas.abap b/src/checks/y_check_comment_type.clas.abap index 012dfd7b..5d5686e7 100644 --- a/src/checks/y_check_comment_type.clas.abap +++ b/src/checks/y_check_comment_type.clas.abap @@ -9,20 +9,24 @@ CLASS y_check_comment_type DEFINITION PUBLIC INHERITING FROM y_check_base CREATE METHODS get_second_character IMPORTING token TYPE stokesx RETURNING VALUE(result) TYPE char1. ENDCLASS. + + CLASS y_check_comment_type IMPLEMENTATION. + METHOD constructor. super->constructor( ). settings-disable_threshold_selection = abap_true. + settings-ignore_pseudo_comments = abap_true. settings-threshold = 0. settings-documentation = |{ c_docs_path-checks }comment-type.md|. set_check_message( 'Comment with ", not with *!' ). ENDMETHOD. - METHOD inspect_tokens. + METHOD inspect_tokens. CHECK statement-type = 'P'. CHECK has_wrong_comment_type( statement ). @@ -34,11 +38,12 @@ CLASS y_check_comment_type IMPLEMENTATION. raise_error( statement_level = statement-level statement_index = index - statement_from = statement-from - error_priority = configuration-prio ). + statement_from = statement-from + error_priority = configuration-prio ). ENDMETHOD. + METHOD has_wrong_comment_type. LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() FROM statement-from TO statement-to. @@ -50,6 +55,7 @@ CLASS y_check_comment_type IMPLEMENTATION. ENDLOOP. ENDMETHOD. + METHOD get_first_character. TRY. result = token-str(1). @@ -58,6 +64,7 @@ CLASS y_check_comment_type IMPLEMENTATION. ENDTRY. ENDMETHOD. + METHOD get_second_character. TRY. result = token-str(2). @@ -65,5 +72,4 @@ CLASS y_check_comment_type IMPLEMENTATION. result = ''. ENDTRY. ENDMETHOD. - ENDCLASS. diff --git a/src/checks/y_check_comment_usage.clas.abap b/src/checks/y_check_comment_usage.clas.abap index ab4472be..b5e0a23a 100644 --- a/src/checks/y_check_comment_usage.clas.abap +++ b/src/checks/y_check_comment_usage.clas.abap @@ -15,8 +15,8 @@ CLASS y_check_comment_usage DEFINITION PUBLIC INHERITING FROM y_check_base CREAT METHODS check_result IMPORTING structure TYPE sstruc. - METHODS is_code_disabled IMPORTING structure TYPE sstruc - statement TYPE sstmnt + METHODS is_code_disabled IMPORTING structure TYPE sstruc + statement TYPE sstmnt RETURNING VALUE(result) TYPE abap_bool. ENDCLASS. @@ -29,9 +29,9 @@ CLASS y_check_comment_usage IMPLEMENTATION. METHOD constructor. super->constructor( ). - settings-prio = c_note. settings-threshold = 10. settings-documentation = |{ c_docs_path-checks }comment-usage.md|. + settings-ignore_pseudo_comments = abap_true. relevant_statement_types = VALUE #( ( scan_struc_stmnt_type-class_definition ) ( scan_struc_stmnt_type-class_implementation ) @@ -57,12 +57,11 @@ CLASS y_check_comment_usage IMPLEMENTATION. METHOD inspect_tokens. DATA(code_disabled) = is_code_disabled( statement = statement structure = structure ). - IF code_disabled = abap_true. RETURN. ENDIF. - IF statement-to EQ statement-from. + IF statement-to = statement-from. abs_statement_number = abs_statement_number + 1. ELSE. abs_statement_number = abs_statement_number + ( statement-to - statement-from ). @@ -70,14 +69,14 @@ CLASS y_check_comment_usage IMPLEMENTATION. LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() FROM statement-from TO statement-to - WHERE type EQ scan_token_type-comment. - IF strlen( -str ) GE 2 AND NOT - ( -str+0(2) EQ |*"| OR - -str+0(2) EQ |"!| OR - -str+0(2) EQ |##| OR - -str+0(2) EQ |*?| OR - -str+0(2) EQ |"?| OR - ( strlen( -str ) GE 3 AND -str+0(3) EQ |"#E| ) OR + WHERE type = scan_token_type-comment. + IF strlen( -str ) >= 2 AND NOT + ( -str+0(2) = |*"| OR + -str+0(2) = |"!| OR + -str+0(2) = |##| OR + -str+0(2) = |*?| OR + -str+0(2) = |"?| OR + ( strlen( -str ) >= 3 AND -str+0(3) = |"#E| ) OR -str CP '"' && object_name && '*.' ). "#EC CI_MAGIC comment_number = comment_number + 1. ENDIF. @@ -97,13 +96,13 @@ CLASS y_check_comment_usage IMPLEMENTATION. RETURN. ENDIF. - raise_error( statement_level = statement_for_message-level - statement_index = structure-stmnt_from - statement_from = statement_for_message-from - error_priority = check_configuration-prio - parameter_01 = |{ comment_number }| - parameter_02 = |{ percentage_of_comments }| - parameter_03 = |{ check_configuration-threshold }| ). + raise_error( statement_level = statement_for_message-level + statement_index = structure-stmnt_from + statement_from = statement_for_message-from + error_priority = check_configuration-prio + parameter_01 = |{ comment_number }| + parameter_02 = |{ percentage_of_comments }| + parameter_03 = |{ check_configuration-threshold }| ). ENDMETHOD. @@ -119,16 +118,14 @@ CLASS y_check_comment_usage IMPLEMENTATION. METHOD is_code_disabled. - CHECK structure-stmnt_type EQ scan_struc_stmnt_type-function. + CHECK structure-stmnt_type = scan_struc_stmnt_type-function. - IF get_token_abs( statement-from ) EQ if_kaizen_keywords_c=>gc_function. + IF get_token_abs( statement-from ) = if_kaizen_keywords_c=>gc_function. is_function_module = abap_true. - ELSEIF get_token_abs( statement-from ) EQ if_kaizen_keywords_c=>gc_endfunction. + ELSEIF get_token_abs( statement-from ) = if_kaizen_keywords_c=>gc_endfunction. is_function_module = abap_false. ENDIF. - result = xsdbool( is_function_module EQ abap_false ). + result = xsdbool( is_function_module = abap_false ). ENDMETHOD. - - ENDCLASS. diff --git a/src/checks/y_check_cx_root_usage.clas.abap b/src/checks/y_check_cx_root_usage.clas.abap index 81b5cb8e..44dfebad 100644 --- a/src/checks/y_check_cx_root_usage.clas.abap +++ b/src/checks/y_check_cx_root_usage.clas.abap @@ -46,9 +46,9 @@ CLASS y_check_cx_root_usage IMPLEMENTATION. METHOD has_cx_root. - LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() + LOOP AT ref_scan_manager->tokens TRANSPORTING NO FIELDS FROM statement-from TO statement-to - WHERE str EQ 'CX_ROOT'. + WHERE str = 'CX_ROOT'. result = abap_true. ENDLOOP. ENDMETHOD. diff --git a/src/checks/y_check_cyclomatic_complexity.clas.abap b/src/checks/y_check_cyclomatic_complexity.clas.abap index 4bf92e31..978b0490 100644 --- a/src/checks/y_check_cyclomatic_complexity.clas.abap +++ b/src/checks/y_check_cyclomatic_complexity.clas.abap @@ -1,7 +1,6 @@ CLASS y_check_cyclomatic_complexity DEFINITION PUBLIC INHERITING FROM y_check_base CREATE PUBLIC. PUBLIC SECTION. CONSTANTS second_token TYPE i VALUE 2. - CONSTANTS third_token TYPE i VALUE 3. METHODS constructor. @@ -26,18 +25,27 @@ CLASS Y_CHECK_CYCLOMATIC_COMPLEXITY IMPLEMENTATION. METHOD compute_cyclomatic_complexity. CASE keyword( ). - WHEN 'IF' OR 'ELSEIF' OR 'WHILE' OR 'CHECK' OR - 'CATCH' OR 'CLEANUP' OR 'ASSERT' OR 'ENDAT' OR 'ENDSELECT' OR - 'LOOP' OR 'ON' OR 'PROVIDE'. - ADD 1 TO c_cyclo_comp. + WHEN 'IF' + OR 'ELSEIF' + OR 'WHILE' + OR 'CHECK' + OR 'CATCH' + OR 'CLEANUP' + OR 'ASSERT' + OR 'ENDAT' + OR 'ENDSELECT' + OR 'LOOP' + OR 'ON' + OR 'PROVIDE'. + c_cyclo_comp = c_cyclo_comp + 1. WHEN 'WHEN'. IF get_token_rel( second_token ) <> 'OTHERS'. - ADD 1 TO c_cyclo_comp. + c_cyclo_comp = c_cyclo_comp + 1. ENDIF. WHEN 'DO'. READ TABLE ref_scan_manager->tokens INDEX statement_wa-to INTO DATA(token). IF token-str = 'TIMES'. - ADD 1 TO c_cyclo_comp. + c_cyclo_comp = c_cyclo_comp + 1. ENDIF. ENDCASE. ENDMETHOD. @@ -70,9 +78,7 @@ CLASS Y_CHECK_CYCLOMATIC_COMPLEXITY IMPLEMENTATION. cyclo_comp = 0. ENDIF. - compute_cyclomatic_complexity( - CHANGING - c_cyclo_comp = cyclo_comp ). + compute_cyclomatic_complexity( CHANGING c_cyclo_comp = cyclo_comp ). IF index = structure-stmnt_to. DATA(check_configuration) = detect_check_configuration( error_count = cyclo_comp diff --git a/src/checks/y_check_db_access_in_ut.clas.abap b/src/checks/y_check_db_access_in_ut.clas.abap index 63b498f3..ff2bd5b3 100644 --- a/src/checks/y_check_db_access_in_ut.clas.abap +++ b/src/checks/y_check_db_access_in_ut.clas.abap @@ -54,6 +54,7 @@ CLASS y_check_db_access_in_ut DEFINITION PUBLIC INHERITING FROM y_check_base CRE METHODS add_line_to_defined_classes IMPORTING statement TYPE sstmnt structure TYPE sstruc. + METHODS check_class IMPORTING index TYPE i statement TYPE sstmnt structure TYPE sstruc. @@ -117,13 +118,13 @@ CLASS Y_CHECK_DB_ACCESS_IN_UT IMPLEMENTATION. METHOD is_persistent_object. DATA(upper_name) = to_upper( obj_name ). - SELECT * FROM tadir - WHERE obj_name = @upper_name - AND object = @keys-table - AND delflag = @space - INTO TABLE @DATA(tmp). - result = xsdbool( sy-subrc = 0 ). + SELECT SINGLE @abap_true + FROM tadir + INTO @result + WHERE obj_name = @upper_name + AND object = @keys-table + AND delflag = @space. ENDMETHOD. @@ -149,7 +150,11 @@ CLASS Y_CHECK_DB_ACCESS_IN_UT IMPLEMENTATION. METHOD add_line_to_defined_classes. - DATA(class_config) = VALUE properties( name = get_class_name( structure ) ). + TRY. + DATA(class_config) = VALUE properties( name = get_class_name( structure ) ). + CATCH cx_sy_itab_line_not_found. + RETURN. + ENDTRY. IF line_exists( defined_classes[ name = class_config-name ] ). RETURN. @@ -164,7 +169,12 @@ CLASS Y_CHECK_DB_ACCESS_IN_UT IMPLEMENTATION. METHOD check_class. - DATA(class_name) = get_class_name( structure ). + TRY. + DATA(class_name) = get_class_name( structure ). + CATCH cx_sy_itab_line_not_found. + RETURN. + ENDTRY. + IF NOT line_exists( defined_classes[ name = class_name ] ). RETURN. ENDIF. @@ -228,18 +238,16 @@ CLASS Y_CHECK_DB_ACCESS_IN_UT IMPLEMENTATION. METHOD is_part_of_framework. LOOP AT ref_scan_manager->statements ASSIGNING FIELD-SYMBOL() - FROM structure-stmnt_from TO structure-stmnt_to. - - LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() - FROM -from TO -to - WHERE str = framework-qsql_if OR - str = framework-qsql_cl OR - str = framework-cds_if OR - str = framework-cds_cl. + FROM structure-stmnt_from TO structure-stmnt_to. + LOOP AT ref_scan_manager->tokens TRANSPORTING NO FIELDS + FROM -from TO -to + WHERE str = framework-qsql_if + OR str = framework-qsql_cl + OR str = framework-cds_if + OR str = framework-cds_cl. result = abap_true. RETURN. ENDLOOP. - ENDLOOP. ENDMETHOD. @@ -254,10 +262,10 @@ CLASS Y_CHECK_DB_ACCESS_IN_UT IMPLEMENTATION. METHOD get_risk_level. LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() - FROM statement-from TO statement-to - WHERE str = risk_level-harmless - OR str = risk_level-dangerous - OR str = risk_level-critical. + FROM statement-from TO statement-to + WHERE str = risk_level-harmless + OR str = risk_level-dangerous + OR str = risk_level-critical. result = -str. ENDLOOP. ENDMETHOD. diff --git a/src/checks/y_check_empty_catches.clas.abap b/src/checks/y_check_empty_catches.clas.abap index 33694ed9..a64f5507 100644 --- a/src/checks/y_check_empty_catches.clas.abap +++ b/src/checks/y_check_empty_catches.clas.abap @@ -22,7 +22,6 @@ CLASS Y_CHECK_EMPTY_CATCHES IMPLEMENTATION. settings-pseudo_comment = '"#EC EMPTY_CATCH' ##NO_TEXT. settings-disable_threshold_selection = abap_true. settings-threshold = 0. - settings-prio = c_warning. settings-documentation = |{ c_docs_path-checks }empty-catch.md|. set_check_message( 'Empty catch should be removed!' ). @@ -31,7 +30,7 @@ CLASS Y_CHECK_EMPTY_CATCHES IMPLEMENTATION. METHOD get_next_token_from_index. LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() - FROM index WHERE type EQ 'I'. + FROM index WHERE type = 'I'. IF result IS INITIAL. result = . EXIT. @@ -41,9 +40,9 @@ CLASS Y_CHECK_EMPTY_CATCHES IMPLEMENTATION. METHOD inspect_tokens. - CHECK get_next_token_from_index( statement-from )-str EQ 'CATCH' AND - ( get_next_token_from_index( statement-to + 1 )-str EQ 'ENDTRY' OR - get_next_token_from_index( statement-to + 1 )-str EQ 'ENDCATCH' ). + CHECK get_next_token_from_index( statement-from )-str = 'CATCH' + AND ( get_next_token_from_index( statement-to + 1 )-str = 'ENDTRY' + OR get_next_token_from_index( statement-to + 1 )-str = 'ENDCATCH' ). DATA(check_configuration) = detect_check_configuration( statement ). diff --git a/src/checks/y_check_empty_if_branches.clas.abap b/src/checks/y_check_empty_if_branches.clas.abap index 43f38de5..fe2fe16b 100644 --- a/src/checks/y_check_empty_if_branches.clas.abap +++ b/src/checks/y_check_empty_if_branches.clas.abap @@ -94,7 +94,7 @@ CLASS y_check_empty_if_branches IMPLEMENTATION. METHOD get_first_token_from_index. LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() FROM index - WHERE type EQ 'I'. + WHERE type = 'I'. IF result IS INITIAL. result = . EXIT. @@ -116,22 +116,22 @@ CLASS y_check_empty_if_branches IMPLEMENTATION. METHOD is_statement_type_excluded. - result = xsdbool( statement-type EQ scan_stmnt_type-empty OR - statement-type EQ scan_stmnt_type-comment OR - statement-type EQ scan_stmnt_type-comment_in_stmnt OR - statement-type EQ scan_stmnt_type-pragma ). + result = xsdbool( statement-type = scan_stmnt_type-empty OR + statement-type = scan_stmnt_type-comment OR + statement-type = scan_stmnt_type-comment_in_stmnt OR + statement-type = scan_stmnt_type-pragma ). ENDMETHOD. METHOD set_found_statement_to_false. - IF branch_counter LT first_if. + IF branch_counter < first_if. found_statement = abap_false. ENDIF. ENDMETHOD. METHOD set_found_statement_to_true. - IF branch_counter GT first_if. + IF branch_counter > first_if. found_statement = abap_true. ENDIF. ENDMETHOD. diff --git a/src/checks/y_check_empty_procedures.clas.abap b/src/checks/y_check_empty_procedures.clas.abap index f05a9800..ad422602 100644 --- a/src/checks/y_check_empty_procedures.clas.abap +++ b/src/checks/y_check_empty_procedures.clas.abap @@ -28,7 +28,6 @@ CLASS y_check_empty_procedures IMPLEMENTATION. settings-pseudo_comment = '"#EC EMPTY_PROCEDURE' ##NO_TEXT. settings-disable_threshold_selection = abap_true. settings-threshold = 0. - settings-prio = c_warning. settings-documentation = |{ c_docs_path-checks }empty-procedure.md|. set_check_message( 'Empty Procedure should be removed!' ). @@ -37,7 +36,7 @@ CLASS y_check_empty_procedures IMPLEMENTATION. METHOD get_next_token_from_index. LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() - FROM index WHERE type EQ 'I'. + FROM index WHERE type = 'I'. IF result IS INITIAL. result = . EXIT. diff --git a/src/checks/y_check_equals_sign_chaining.clas.abap b/src/checks/y_check_equals_sign_chaining.clas.abap index bcd06ece..ea137ae7 100644 --- a/src/checks/y_check_equals_sign_chaining.clas.abap +++ b/src/checks/y_check_equals_sign_chaining.clas.abap @@ -33,8 +33,8 @@ CLASS y_check_equals_sign_chaining IMPLEMENTATION. METHOD inspect_tokens. - CHECK get_second_token( statement ) EQ '='. - CHECK get_fourth_token( statement ) EQ '='. + CHECK get_second_token( statement ) = '='. + CHECK get_fourth_token( statement ) = '='. DATA(check_configuration) = detect_check_configuration( statement ). diff --git a/src/checks/y_check_external_call_in_ut.clas.abap b/src/checks/y_check_external_call_in_ut.clas.abap index f32545cc..da6c59b4 100644 --- a/src/checks/y_check_external_call_in_ut.clas.abap +++ b/src/checks/y_check_external_call_in_ut.clas.abap @@ -17,20 +17,17 @@ CLASS y_check_external_call_in_ut IMPLEMENTATION. METHOD check_if_error. - DATA check_configuration TYPE y_if_clean_code_manager=>check_configuration. - DATA(key_word) = get_token_abs( statement-from ). - - check_configuration = detect_check_configuration( statement ). + DATA(check_configuration) = detect_check_configuration( statement ). IF check_configuration IS INITIAL. RETURN. ENDIF. - raise_error( statement_level = statement-level - statement_index = index - statement_from = statement-from - error_priority = check_configuration-prio - parameter_01 = |{ key_word }| ). + raise_error( statement_level = statement-level + statement_index = index + statement_from = statement-from + error_priority = check_configuration-prio + parameter_01 = get_token_abs( statement-from ) ). ENDMETHOD. @@ -54,6 +51,8 @@ CLASS y_check_external_call_in_ut IMPLEMENTATION. METHOD inspect_tokens. + DATA has_redirection TYPE abap_bool VALUE abap_false. + DATA(token1) = get_token_abs( statement-from ). DATA(token2) = get_token_abs( statement-from + 1 ). DATA(token3) = get_token_abs( statement-from + 2 ). @@ -62,19 +61,17 @@ CLASS y_check_external_call_in_ut IMPLEMENTATION. DATA(token6) = get_token_abs( statement-from + 5 ). DATA(token4to6) = |{ token4 } { token5 } { token6 }|. - DATA has_redirection TYPE abap_bool VALUE abap_false. - CASE token1. WHEN 'SUBMIT'. has_redirection = abap_true. WHEN 'CALL'. - IF ( token2 = 'FUNCTION' ) AND - ( ( token4 = 'DESTINATION' ) OR - ( ( token4to6 = 'STARTING NEW TASK' ) ) OR - ( ( token4to6 = 'IN UPDATE TASK' ) ) ). + IF token2 = 'FUNCTION' + AND ( token4 = 'DESTINATION' + OR token4to6 = 'STARTING NEW TASK' + OR token4to6 = 'IN UPDATE TASK' ). has_redirection = abap_true. - ELSEIF ( token2 = 'METHOD' ) AND - ( token3 CS 'CL_GUI_' ). + ELSEIF token2 = 'METHOD' + AND token3 CS 'CL_GUI_'. has_redirection = abap_true. ENDIF. WHEN OTHERS. diff --git a/src/checks/y_check_function.clas.abap b/src/checks/y_check_function.clas.abap index eb1d9792..e0908de2 100644 --- a/src/checks/y_check_function.clas.abap +++ b/src/checks/y_check_function.clas.abap @@ -41,10 +41,9 @@ CLASS Y_CHECK_FUNCTION IMPLEMENTATION. CHECK get_token_abs( statement-from ) = 'FUNCTION'. - DATA fm_name TYPE c LENGTH 30. - fm_name = get_token_abs( statement-from + 1 ). + DATA(fm_name) = get_token_abs( statement-from + 1 ). - IF db_reader->is_fm_rfc_enabled( fm_name ) EQ abap_false. + IF db_reader->is_fm_rfc_enabled( CONV #( fm_name ) ) = abap_false. DATA(check_configuration) = detect_check_configuration( statement ). diff --git a/src/checks/y_check_function.clas.locals_imp.abap b/src/checks/y_check_function.clas.locals_imp.abap index e93b11a9..be7d319e 100644 --- a/src/checks/y_check_function.clas.locals_imp.abap +++ b/src/checks/y_check_function.clas.locals_imp.abap @@ -1,9 +1,11 @@ CLASS lcl_db_reader IMPLEMENTATION. + METHOD lif_db_reader~is_fm_rfc_enabled. - SELECT SINGLE fmode FROM tfdir - WHERE funcname = @function - AND fmode EQ 'R' - INTO @DATA(mode). - result = xsdbool( sy-subrc EQ 0 ). + SELECT SINGLE @abap_true + FROM tfdir + INTO @result + WHERE funcname = @function + AND fmode = 'R'. ENDMETHOD. + ENDCLASS. diff --git a/src/checks/y_check_function.clas.testclasses.abap b/src/checks/y_check_function.clas.testclasses.abap index 70335711..da861a46 100644 --- a/src/checks/y_check_function.clas.testclasses.abap +++ b/src/checks/y_check_function.clas.testclasses.abap @@ -111,7 +111,7 @@ CLASS local_test_class DEFINITION FOR TESTING METHODS: setup, - assert_errors IMPORTING err_cnt TYPE i, + aseert_info IMPORTING count TYPE i, assert_pseudo_comments IMPORTING pc_cnt TYPE i, is_bound FOR TESTING, rfc_function_ok FOR TESTING, @@ -140,7 +140,7 @@ CLASS local_test_class IMPLEMENTATION. cut->db_reader = NEW ltd_rfc_function( ). ref_scan_manager_double->set_data_for_ok( ). cut->run( ). - assert_errors( 0 ). + aseert_info( 0 ). assert_pseudo_comments( 0 ). ENDMETHOD. @@ -148,7 +148,7 @@ CLASS local_test_class IMPLEMENTATION. cut->db_reader = NEW ltd_no_rfc_function( ). ref_scan_manager_double->set_data_for_error( ). cut->run( ). - assert_errors( 2 ). + aseert_info( 2 ). assert_pseudo_comments( 0 ). ENDMETHOD. @@ -156,7 +156,7 @@ CLASS local_test_class IMPLEMENTATION. cut->db_reader = NEW ltd_no_rfc_function( ). ref_scan_manager_double->set_pseudo_comment_ok( ). cut->run( ). - assert_errors( 0 ). + aseert_info( 0 ). assert_pseudo_comments( 1 ). ENDMETHOD. @@ -165,8 +165,8 @@ CLASS local_test_class IMPLEMENTATION. exp = pc_cnt ). ENDMETHOD. - METHOD assert_errors. - cl_abap_unit_assert=>assert_equals( act = cut->statistics->get_number_errors( ) - exp = err_cnt ). + METHOD aseert_info. + cl_abap_unit_assert=>assert_equals( act = cut->statistics->get_number_notes( ) + exp = count ). ENDMETHOD. ENDCLASS. diff --git a/src/checks/y_check_is_interface_in_class.clas.abap b/src/checks/y_check_is_interface_in_class.clas.abap index 0c3ba1b1..4d871f3f 100644 --- a/src/checks/y_check_is_interface_in_class.clas.abap +++ b/src/checks/y_check_is_interface_in_class.clas.abap @@ -36,7 +36,6 @@ CLASS Y_CHECK_IS_INTERFACE_IN_CLASS IMPLEMENTATION. settings-pseudo_comment = '"#EC INTF_IN_CLASS' ##NO_TEXT. settings-disable_threshold_selection = abap_true. settings-threshold = 1. - settings-prio = c_warning. settings-apply_on_test_code = abap_false. settings-documentation = |{ c_docs_path-checks }interface-in-class.md|. @@ -66,7 +65,7 @@ CLASS Y_CHECK_IS_INTERFACE_IN_CLASS IMPLEMENTATION. AND get_second_token( statement ) <> 'FOR' AND get_third_token( statement ) <> 'TESTING'. - ADD 1 TO public_method_counter. + public_method_counter = public_method_counter + 1. ENDMETHOD. diff --git a/src/checks/y_check_magic_number.clas.abap b/src/checks/y_check_magic_number.clas.abap index 5b0420b1..9783861f 100644 --- a/src/checks/y_check_magic_number.clas.abap +++ b/src/checks/y_check_magic_number.clas.abap @@ -39,13 +39,13 @@ CLASS Y_CHECK_MAGIC_NUMBER IMPLEMENTATION. METHOD is_exception. - IF token EQ 'ENDCASE' AND has_case_with_subrc EQ abap_true. + IF token = 'ENDCASE' AND has_case_with_subrc = abap_true. has_case_with_subrc = abap_false. ENDIF. - IF token EQ 'SY-SUBRC' OR has_case_with_subrc EQ abap_true. + IF token = 'SY-SUBRC' OR has_case_with_subrc = abap_true. result = abap_true. - ELSEIF token EQ 'CASE' AND get_token_rel( second_token ) = 'SY-SUBRC'. + ELSEIF token = 'CASE' AND get_token_rel( second_token ) = 'SY-SUBRC'. has_case_with_subrc = abap_true. ENDIF. ENDMETHOD. @@ -93,7 +93,7 @@ CLASS Y_CHECK_MAGIC_NUMBER IMPLEMENTATION. ENDIF. FIND REGEX `^(?!'?[01]'?$)'?\d+'?$` IN token_string. - IF sy-subrc EQ 0. + IF sy-subrc = 0. magic_number = token_string. result = abap_true. ENDIF. diff --git a/src/checks/y_check_max_nesting_depth.clas.abap b/src/checks/y_check_max_nesting_depth.clas.abap index 5df7b45b..d045c83f 100644 --- a/src/checks/y_check_max_nesting_depth.clas.abap +++ b/src/checks/y_check_max_nesting_depth.clas.abap @@ -25,14 +25,26 @@ CLASS y_check_max_nesting_depth IMPLEMENTATION. METHOD compute_nesting_level. CASE token_str. - WHEN 'IF' OR 'WHILE' OR 'LOOP' OR - 'DO' OR 'PROVIDE' OR 'TRY' OR 'CASE'. - ADD 1 TO curr_nesting. - WHEN 'ENDIF' OR 'ENDWHILE' OR 'ENDLOOP' OR - 'ENDDO' OR 'ENDPROVIDE' OR 'ENDTRY' OR 'ENDCASE'. - max_nesting = nmax( val1 = max_nesting val2 = curr_nesting ). - SUBTRACT 1 FROM curr_nesting. - WHEN 'ENDAT' OR 'ENDSELECT'. + WHEN 'IF' + OR 'WHILE' + OR 'LOOP' + OR 'DO' + OR 'PROVIDE' + OR 'TRY' + OR 'CASE'. + curr_nesting = curr_nesting + 1. + WHEN 'ENDIF' + OR 'ENDWHILE' + OR 'ENDLOOP' + OR 'ENDDO' + OR 'ENDPROVIDE' + OR 'ENDTRY' + OR 'ENDCASE'. + max_nesting = nmax( val1 = max_nesting + val2 = curr_nesting ). + curr_nesting = curr_nesting - 1. + WHEN 'ENDAT' + OR 'ENDSELECT'. IF curr_nesting >= max_nesting. max_nesting = curr_nesting + 1. ENDIF. diff --git a/src/checks/y_check_method_output_param.clas.abap b/src/checks/y_check_method_output_param.clas.abap index f9247080..7f9c3c1a 100644 --- a/src/checks/y_check_method_output_param.clas.abap +++ b/src/checks/y_check_method_output_param.clas.abap @@ -6,13 +6,10 @@ CLASS y_check_method_output_param DEFINITION PUBLIC INHERITING FROM y_check_bas METHODS inspect_tokens REDEFINITION. PRIVATE SECTION. - DATA has_found_methods TYPE abap_bool. DATA has_exporting_parameter TYPE abap_bool. DATA has_changing_parameter TYPE abap_bool. DATA has_returning_parameter TYPE abap_bool. - DATA has_pseudo_comment TYPE abap_bool. - METHODS check_token_content IMPORTING token TYPE stokesx. METHODS has_error RETURNING VALUE(result) TYPE abap_bool. ENDCLASS. @@ -25,13 +22,13 @@ CLASS Y_CHECK_METHOD_OUTPUT_PARAM IMPLEMENTATION. METHOD has_error. DATA(sum) = 0. IF has_exporting_parameter = abap_true. - ADD 1 TO sum. + sum = sum + 1. ENDIF. IF has_changing_parameter = abap_true. - ADD 1 TO sum. + sum = sum + 1. ENDIF. IF has_returning_parameter = abap_true. - ADD 1 TO sum. + sum = sum + 1. ENDIF. IF sum > 1. result = abap_true. @@ -39,19 +36,6 @@ CLASS Y_CHECK_METHOD_OUTPUT_PARAM IMPLEMENTATION. ENDMETHOD. - METHOD check_token_content. - IF token-str EQ 'EXPORTING'. - has_exporting_parameter = abap_true. - ENDIF. - IF token-str EQ 'CHANGING'. - has_changing_parameter = abap_true. - ENDIF. - IF token-str EQ 'RETURNING'. - has_returning_parameter = abap_true. - ENDIF. - ENDMETHOD. - - METHOD constructor. super->constructor( ). diff --git a/src/checks/y_check_method_return_bool.clas.abap b/src/checks/y_check_method_return_bool.clas.abap index 1dacd995..17b38224 100644 --- a/src/checks/y_check_method_return_bool.clas.abap +++ b/src/checks/y_check_method_return_bool.clas.abap @@ -26,7 +26,6 @@ CLASS Y_CHECK_METHOD_RETURN_BOOL IMPLEMENTATION. settings-pseudo_comment = '"#EC METH_RET_BOOL' ##NO_TEXT. settings-disable_threshold_selection = abap_true. settings-threshold = 0. - settings-prio = c_warning. settings-documentation = |{ c_docs_path-checks }method-return-bool.md|. relevant_statement_types = VALUE #( ( scan_struc_stmnt_type-class_definition ) @@ -59,15 +58,19 @@ CLASS Y_CHECK_METHOD_RETURN_BOOL IMPLEMENTATION. method_name = get_token_abs( stmnt_index + 1 ). LOOP AT good_method_names_beginning ASSIGNING FIELD-SYMBOL(). - IF strlen( method_name ) GE strlen( ) - AND substring( val = method_name len = strlen( ) ) EQ . - result = abap_true. - RETURN. + IF strlen( method_name ) >= strlen( ). + DATA(prefix) = substring( val = method_name + len = strlen( ) ). + + IF prefix = . + result = abap_true. + RETURN. + ENDIF. ENDIF. ENDLOOP. LOOP AT good_method_names_containing ASSIGNING FIELD-SYMBOL(). - IF strlen( method_name ) GE strlen( ) + IF strlen( method_name ) >= strlen( ) AND method_name CS . result = abap_true. RETURN. @@ -84,8 +87,8 @@ CLASS Y_CHECK_METHOD_RETURN_BOOL IMPLEMENTATION. LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() FROM statement-from TO statement-to. - IF -str EQ 'ABAP_BOOL' - AND get_token_abs( token_index - 3 ) EQ 'RETURNING'. "#EC CI_MAGIC + IF -str = 'ABAP_BOOL' + AND get_token_abs( token_index - 3 ) = 'RETURNING'. "#EC CI_MAGIC has_found_bool = abap_true. ENDIF. token_index = token_index + 1. diff --git a/src/checks/y_check_non_class_exception.clas.abap b/src/checks/y_check_non_class_exception.clas.abap index 2c5e42ca..422ca134 100644 --- a/src/checks/y_check_non_class_exception.clas.abap +++ b/src/checks/y_check_non_class_exception.clas.abap @@ -61,7 +61,7 @@ CLASS Y_CHECK_NON_CLASS_EXCEPTION IMPLEMENTATION. LOOP AT ref_scan_manager->tokens TRANSPORTING NO FIELDS FROM statement-from TO statement-to - WHERE str = 'RAISING' AND type EQ 'I'. + WHERE str = 'RAISING' AND type = 'I'. checkif_error( index = index statement = statement ). diff --git a/src/checks/y_check_num_exec_statements.clas.abap b/src/checks/y_check_num_exec_statements.clas.abap index 04612c0a..8573a831 100644 --- a/src/checks/y_check_num_exec_statements.clas.abap +++ b/src/checks/y_check_num_exec_statements.clas.abap @@ -48,7 +48,7 @@ CLASS Y_CHECK_NUM_EXEC_STATEMENTS IMPLEMENTATION. RETURN. ENDIF. IF token_wa-type <> scan_token_type-comment AND token_wa-type <> scan_token_type-pragma. - ADD 1 TO no_exec_statements. + no_exec_statements = no_exec_statements + 1. ENDIF. ENDMETHOD. diff --git a/src/checks/y_check_num_public_attributes.clas.abap b/src/checks/y_check_num_public_attributes.clas.abap index cf29fd1f..7be75f4b 100644 --- a/src/checks/y_check_num_public_attributes.clas.abap +++ b/src/checks/y_check_num_public_attributes.clas.abap @@ -62,10 +62,12 @@ CLASS y_check_num_public_attributes IMPLEMENTATION. METHOD checkif_attribute_in_structure. - IF ( second_token = 'BEGIN' AND third_token = 'OF' ). - ADD 1 TO structure_depth. - ELSEIF ( second_token = 'END' AND third_token = 'OF' ). - SUBTRACT 1 FROM structure_depth. + IF second_token = 'BEGIN' + AND third_token = 'OF'. + structure_depth = structure_depth + 1. + ELSEIF second_token = 'END' + AND third_token = 'OF'. + structure_depth = structure_depth - 1. ENDIF. ENDMETHOD. @@ -78,7 +80,7 @@ CLASS y_check_num_public_attributes IMPLEMENTATION. CHECK last_token <> 'READ-ONLY'. - ADD 1 TO public_attribute_counter. + public_attribute_counter = public_attribute_counter + 1. ENDMETHOD. diff --git a/src/checks/y_check_number_attributes.clas.abap b/src/checks/y_check_number_attributes.clas.abap index ac7dadcf..cd3c6fa4 100644 --- a/src/checks/y_check_number_attributes.clas.abap +++ b/src/checks/y_check_number_attributes.clas.abap @@ -52,7 +52,7 @@ CLASS y_check_number_attributes IMPLEMENTATION. METHOD inspect_tokens. - checkif_attribute_found( first_token = get_token_abs( statement-from ) ). + checkif_attribute_found( get_token_abs( statement-from ) ). checkif_attribute_in_structure( second_token = get_token_abs( statement-from + 1 ) third_token = get_token_abs( statement-from + 2 ) ). @@ -63,17 +63,19 @@ CLASS y_check_number_attributes IMPLEMENTATION. CASE first_token. WHEN 'DATA' OR 'CLASS-DATA'. IF structure_depth <= structure_depth_threshold. - ADD 1 TO attribute_counter. + attribute_counter = attribute_counter + 1. ENDIF. ENDCASE. ENDMETHOD. METHOD checkif_attribute_in_structure. - IF ( second_token = 'BEGIN' AND third_token = 'OF' ). - ADD 1 TO structure_depth. - ELSEIF ( second_token = 'END' AND third_token = 'OF' ). - SUBTRACT 1 FROM structure_depth. + IF second_token = 'BEGIN' + AND third_token = 'OF'. + structure_depth = structure_depth + 1. + ELSEIF second_token = 'END' + AND third_token = 'OF'. + structure_depth = structure_depth - 1. ENDIF. ENDMETHOD. diff --git a/src/checks/y_check_number_events.clas.abap b/src/checks/y_check_number_events.clas.abap index f49cf36d..b1bac668 100644 --- a/src/checks/y_check_number_events.clas.abap +++ b/src/checks/y_check_number_events.clas.abap @@ -45,7 +45,7 @@ CLASS Y_CHECK_NUMBER_EVENTS IMPLEMENTATION. METHOD inspect_tokens. CASE get_token_abs( statement-from ). WHEN 'EVENTS' OR 'CLASS-EVENTS'. - ADD 1 TO event_counter. + event_counter = event_counter + 1. ENDCASE. ENDMETHOD. diff --git a/src/checks/y_check_number_interfaces.clas.abap b/src/checks/y_check_number_interfaces.clas.abap index adc4ea60..eb15e635 100644 --- a/src/checks/y_check_number_interfaces.clas.abap +++ b/src/checks/y_check_number_interfaces.clas.abap @@ -45,7 +45,7 @@ CLASS y_check_number_interfaces IMPLEMENTATION. METHOD inspect_tokens. IF get_token_abs( statement-from ) = 'INTERFACES'. - ADD 1 TO interface_counter. + interface_counter = interface_counter + 1. ENDIF. ENDMETHOD. diff --git a/src/checks/y_check_number_methods.clas.abap b/src/checks/y_check_number_methods.clas.abap index e8d8eca3..141181b3 100644 --- a/src/checks/y_check_number_methods.clas.abap +++ b/src/checks/y_check_number_methods.clas.abap @@ -47,7 +47,7 @@ CLASS Y_CHECK_NUMBER_METHODS IMPLEMENTATION. METHOD inspect_tokens. CASE get_token_abs( statement-from ). WHEN 'METHODS' OR 'CLASS-METHODS'. - ADD 1 TO method_counter. + method_counter = method_counter + 1. ENDCASE. ENDMETHOD. diff --git a/src/checks/y_check_optional_parameters.clas.abap b/src/checks/y_check_optional_parameters.clas.abap index 6a8d352e..3d8f15e1 100644 --- a/src/checks/y_check_optional_parameters.clas.abap +++ b/src/checks/y_check_optional_parameters.clas.abap @@ -46,7 +46,7 @@ CLASS Y_CHECK_OPTIONAL_PARAMETERS IMPLEMENTATION. ENDMETHOD. METHOD has_optional_parameter. - LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() + LOOP AT ref_scan_manager->tokens TRANSPORTING NO FIELDS FROM statement-from TO statement-to WHERE str = 'OPTIONAL'. result = abap_true. diff --git a/src/checks/y_check_prefer_case_to_elseif.clas.abap b/src/checks/y_check_prefer_case_to_elseif.clas.abap index 34ce8b4f..4ef1e23e 100644 --- a/src/checks/y_check_prefer_case_to_elseif.clas.abap +++ b/src/checks/y_check_prefer_case_to_elseif.clas.abap @@ -109,7 +109,7 @@ CLASS y_check_prefer_case_to_elseif IMPLEMENTATION. METHOD has_multiple_conditions. - LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() + LOOP AT ref_scan_manager->tokens TRANSPORTING NO FIELDS FROM statement-from TO statement-to WHERE str = 'AND' OR str = 'OR'. result = abap_true. diff --git a/src/checks/y_check_prefer_is_not.clas.abap b/src/checks/y_check_prefer_is_not.clas.abap index ea4b6bf9..f0ab421f 100644 --- a/src/checks/y_check_prefer_is_not.clas.abap +++ b/src/checks/y_check_prefer_is_not.clas.abap @@ -5,6 +5,9 @@ CLASS y_check_prefer_is_not DEFINITION PUBLIC INHERITING FROM y_check_base CREAT PROTECTED SECTION. METHODS inspect_tokens REDEFINITION. + METHODS is_standard_function IMPORTING token TYPE stokesx + RETURNING VALUE(result) TYPE abap_bool. + ENDCLASS. @@ -28,12 +31,13 @@ CLASS y_check_prefer_is_not IMPLEMENTATION. METHOD inspect_tokens. - LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() + LOOP AT ref_scan_manager->tokens TRANSPORTING NO FIELDS FROM statement-from TO statement-to WHERE str = 'IF' OR str = 'ELSEIF' OR str = 'AND' - OR str = 'OR'. + OR str = 'OR' + OR str = 'ASSERT'. DATA(position) = sy-tabix. @@ -46,7 +50,7 @@ CLASS y_check_prefer_is_not IMPLEMENTATION. ENDTRY. TRY. - IF ref_scan_manager->tokens[ position + 2 ]-str = 'LINE_EXISTS('. + IF is_standard_function( ref_scan_manager->tokens[ position + 2 ] ) = abap_true. CONTINUE. ENDIF. CATCH cx_sy_itab_line_not_found. @@ -67,4 +71,12 @@ CLASS y_check_prefer_is_not IMPLEMENTATION. ENDLOOP. ENDMETHOD. + + METHOD is_standard_function. + result = xsdbool( token-str CP 'CONTAINS*' + OR token-str CP 'LINE_EXISTS*' + OR token-str CP 'MATCHES*' ). + ENDMETHOD. + + ENDCLASS. diff --git a/src/checks/y_check_prefer_is_not.clas.testclasses.abap b/src/checks/y_check_prefer_is_not.clas.testclasses.abap index f9bdb0aa..4b1e42eb 100644 --- a/src/checks/y_check_prefer_is_not.clas.testclasses.abap +++ b/src/checks/y_check_prefer_is_not.clas.testclasses.abap @@ -342,8 +342,84 @@ CLASS ltc_line_exists IMPLEMENTATION. ( ' START-OF-SELECTION. ' ) ( ' DATA itab TYPE TABLE OF tadir. ' ) - ( ' IF NOT line_exists( itab[ 0 ] ). ' ) - ( ' ENDIF. ' ) + ( ' ASSERT NOT line_exists( itab[ 0 ] ). ' ) + ). + ENDMETHOD. + +ENDCLASS. + + + +CLASS ltc_contains DEFINITION INHERITING FROM ltc_not_value FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_code_without_issue REDEFINITION. +ENDCLASS. + +CLASS ltc_contains IMPLEMENTATION. + + METHOD get_code_without_issue. + result = VALUE #( + ( 'REPORT y_example. ' ) + + ( ' START-OF-SELECTION. ' ) + ( | ASSERT NOT contains( val = 'code pal for ABAP' sub = 'ABAP' ). | ) + ). + ENDMETHOD. + +ENDCLASS. + + +CLASS ltc_matches DEFINITION INHERITING FROM ltc_not_value FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_code_without_issue REDEFINITION. +ENDCLASS. + +CLASS ltc_matches IMPLEMENTATION. + + METHOD get_code_without_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' START-OF-SELECTION. ' ) + ( | ASSERT NOT matches( val = 'a123e' regex = '[[:alpha:]]*' ). | ) + ). + ENDMETHOD. + +ENDCLASS. + + +CLASS ltc_contains_any_not_of DEFINITION INHERITING FROM ltc_not_value FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_code_without_issue REDEFINITION. +ENDCLASS. + +CLASS ltc_contains_any_not_of IMPLEMENTATION. + + METHOD get_code_without_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' START-OF-SELECTION. ' ) + ( | ASSERT NOT contains_any_not_of( val = 'a123e' sub = '123' ). | ) + ). + ENDMETHOD. + +ENDCLASS. + + +CLASS ltc_contains_any_of DEFINITION INHERITING FROM ltc_not_value FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_code_without_issue REDEFINITION. +ENDCLASS. + +CLASS ltc_contains_any_of IMPLEMENTATION. + + METHOD get_code_without_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' START-OF-SELECTION. ' ) + ( | ASSERT NOT contains_any_of( val = 'a123e' sub = '123' ). | ) ). ENDMETHOD. diff --git a/src/checks/y_check_prefer_line_exists.clas.abap b/src/checks/y_check_prefer_line_exists.clas.abap new file mode 100644 index 00000000..f26c6310 --- /dev/null +++ b/src/checks/y_check_prefer_line_exists.clas.abap @@ -0,0 +1,65 @@ +CLASS y_check_prefer_line_exists DEFINITION PUBLIC INHERITING FROM y_check_base CREATE PUBLIC. + PUBLIC SECTION. + METHODS constructor. + + PROTECTED SECTION. + METHODS inspect_tokens REDEFINITION. + + METHODS get_statement_inline IMPORTING statement TYPE sstmnt + RETURNING VALUE(result) TYPE string. + +ENDCLASS. + + + +CLASS y_check_prefer_line_exists IMPLEMENTATION. + + + METHOD constructor. + super->constructor( ). + + settings-pseudo_comment = '"#EC PREF_LINE_EX' ##NO_TEXT. + settings-disable_threshold_selection = abap_true. + settings-threshold = 0. + settings-documentation = |{ c_docs_path-checks }prefer-line-exists.md|. + + set_check_message( 'Prefer LINE_EXISTS or LINE_INDEX to READ TABLE or LOOP AT!' ). + ENDMETHOD. + + + METHOD inspect_tokens. + CHECK get_token_abs( statement-from ) = 'READ' + OR get_token_abs( statement-from ) = 'LOOP'. + + DATA(inline) = get_statement_inline( statement ). + + IF inline NP '* TRANSPORTING NO FIELDS *'. + RETURN. + ENDIF. + + IF inline CP '* FROM *' + OR inline CP '* TO *'. + RETURN. + ENDIF. + + DATA(configuration) = detect_check_configuration( statement ). + + IF configuration IS INITIAL. + RETURN. + ENDIF. + + raise_error( statement_level = statement-level + statement_index = index + statement_from = statement-from + error_priority = configuration-prio ). + ENDMETHOD. + + + METHOD get_statement_inline. + LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() + FROM statement-from TO statement-to. + result = |{ result } { -str }|. + ENDLOOP. + ENDMETHOD. + +ENDCLASS. diff --git a/src/checks/y_check_prefer_line_exists.clas.testclasses.abap b/src/checks/y_check_prefer_line_exists.clas.testclasses.abap new file mode 100644 index 00000000..cc53e9f7 --- /dev/null +++ b/src/checks/y_check_prefer_line_exists.clas.testclasses.abap @@ -0,0 +1,141 @@ +*"* use this source file for your ABAP unit test classes +CLASS ltc_read_table DEFINITION INHERITING FROM y_unit_test_base FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_cut REDEFINITION. + METHODS get_code_with_issue REDEFINITION. + METHODS get_code_without_issue REDEFINITION. + METHODS get_code_with_exemption REDEFINITION. +ENDCLASS. + +CLASS ltc_read_table IMPLEMENTATION. + + METHOD get_cut. + result ?= NEW y_check_prefer_line_exists( ). + ENDMETHOD. + + METHOD get_code_with_issue. + result = VALUE #( + ( 'REPORT y_example. ' ) + + ( ' START-OF-SELECTION. ' ) + ( ' DATA tadir TYPE TABLE OF tadir. ' ) + ( ' DATA exists TYPE abap_bool. ' ) + + ( | READ TABLE tadir TRANSPORTING NO FIELDS WITH KEY object = 'y_check_prefer_line_exists'. | ) + + ( ' IF sy-subrc = 0. ' ) + ( ' exists = abap_true. ' ) + ( ' ENDIF. ' ) + ). + ENDMETHOD. + + METHOD get_code_without_issue. + result = VALUE #( + ( 'REPORT y_example. ' ) + + ( ' START-OF-SELECTION. ' ) + ( ' DATA tadir TYPE TABLE OF tadir. ' ) + ( | DATA(exists) = xsdbool( line_exists( tadir[ object = 'y_check_prefer_line_exists' ] ) ). | ) + ( | DATA(index) = line_index( tadir[ object = 'y_check_prefer_line_exists' ] ). | ) + ). + ENDMETHOD. + + METHOD get_code_with_exemption. + result = VALUE #( + ( 'REPORT y_example. ' ) + + ( ' START-OF-SELECTION. ' ) + ( ' DATA tadir TYPE TABLE OF tadir. ' ) + ( ' DATA exists TYPE abap_bool. ' ) + + ( | READ TABLE tadir TRANSPORTING NO FIELDS WITH KEY object = 'y_check_prefer_line_exists'. "#EC PREF_LINE_EX | ) + + ( ' IF sy-subrc = 0. ' ) + ( ' exists = abap_true. ' ) + ( ' ENDIF. ' ) + ). + ENDMETHOD. + +ENDCLASS. + + + +CLASS ltc_loop_at DEFINITION INHERITING FROM ltc_read_table FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_code_with_issue REDEFINITION. + METHODS get_code_with_exemption REDEFINITION. +ENDCLASS. + +CLASS ltc_loop_at IMPLEMENTATION. + + METHOD get_code_with_issue. + result = VALUE #( + ( 'REPORT y_example. ' ) + + ( ' START-OF-SELECTION. ' ) + ( ' DATA tadir TYPE TABLE OF tadir. ' ) + ( ' DATA exists TYPE abap_bool. ' ) + + ( | LOOP AT tadir TRANSPORTING NO FIELDS WHERE object = 'y_check_prefer_line_exists'. | ) + ( ' exists = abap_true. ' ) + ( ' ENDLOOP. ' ) + ). + ENDMETHOD. + + METHOD get_code_with_exemption. + result = VALUE #( + ( 'REPORT y_example. ' ) + + ( ' START-OF-SELECTION. ' ) + ( ' DATA tadir TYPE TABLE OF tadir. ' ) + ( ' DATA exists TYPE abap_bool. ' ) + + ( | LOOP AT tadir TRANSPORTING NO FIELDS WHERE object = 'y_check_prefer_line_exists'. "#EC PREF_LINE_EX | ) + ( ' exists = abap_true. ' ) + ( ' ENDLOOP. ' ) + ). + ENDMETHOD. + +ENDCLASS. + + + +CLASS ltc_loop_at_from_to DEFINITION INHERITING FROM ltc_loop_at FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_code_with_issue REDEFINITION. + METHODS get_code_without_issue REDEFINITION. +ENDCLASS. + +CLASS ltc_loop_at_from_to IMPLEMENTATION. + + METHOD get_code_with_issue. + result = VALUE #( + ( 'REPORT y_example. ' ) + + ( ' START-OF-SELECTION. ' ) + ( ' DATA from_list TYPE TABLE OF tadir. ' ) + ( ' DATA exists TYPE abap_bool. ' ) + + ( | LOOP AT from_list TRANSPORTING NO FIELDS WHERE object = 'y_check_prefer_line_exists'. | ) + ( ' exists = abap_true. ' ) + ( ' ENDLOOP. ' ) + ). + ENDMETHOD. + + METHOD get_code_without_issue. + result = VALUE #( + ( 'REPORT y_example. ' ) + + ( ' START-OF-SELECTION. ' ) + ( ' DATA tadir TYPE TABLE OF tadir. ' ) + ( ' DATA exists TYPE abap_bool. ' ) + + ( ' LOOP AT tadir TRANSPORTING NO FIELDS ' ) + ( ' FROM 1 TO 50 ' ) + ( | WHERE object = 'y_check_prefer_line_exists'. | ) + ( ' exists = abap_true. ' ) + ( ' ENDLOOP. ' ) + ). + ENDMETHOD. + +ENDCLASS. diff --git a/src/checks/y_check_prefer_line_exists.clas.xml b/src/checks/y_check_prefer_line_exists.clas.xml new file mode 100644 index 00000000..86b7a26d --- /dev/null +++ b/src/checks/y_check_prefer_line_exists.clas.xml @@ -0,0 +1,17 @@ + + + + + + Y_CHECK_PREFER_LINE_EXISTS + E + Prefer LINE_EXISTS or LINE_INDEX to READ TABLE or LOOP AT + 1 + X + X + X + X + + + + diff --git a/src/checks/y_check_prefer_new_to_crt_obj.clas.abap b/src/checks/y_check_prefer_new_to_crt_obj.clas.abap new file mode 100644 index 00000000..f84f7ed4 --- /dev/null +++ b/src/checks/y_check_prefer_new_to_crt_obj.clas.abap @@ -0,0 +1,44 @@ +CLASS y_check_prefer_new_to_crt_obj DEFINITION PUBLIC INHERITING FROM y_check_base CREATE PUBLIC . + PUBLIC SECTION. + METHODS constructor . + + PROTECTED SECTION. + METHODS inspect_tokens REDEFINITION. + +ENDCLASS. + + + +CLASS y_check_prefer_new_to_crt_obj IMPLEMENTATION. + + + METHOD constructor. + super->constructor( ). + + settings-pseudo_comment = '"#EC PREF_NEW' ##NO_TEXT. + settings-disable_threshold_selection = abap_true. + settings-threshold = 0. + settings-documentation = |{ c_docs_path-checks }prefer-new-to-create-object.md|. + + set_check_message( 'Prefer NEW to CREATE OBJECT!' ). + ENDMETHOD. + + + METHOD inspect_tokens. + CHECK get_token_abs( statement-from ) = 'CREATE' + AND get_token_abs( statement-from + 1 ) = 'OBJECT'. + + DATA(check_configuration) = detect_check_configuration( statement ). + + IF check_configuration IS INITIAL. + RETURN. + ENDIF. + + raise_error( statement_level = statement-level + statement_index = index + statement_from = statement-from + error_priority = check_configuration-prio ). + ENDMETHOD. + + +ENDCLASS. diff --git a/src/checks/y_check_prefer_new_to_crt_obj.clas.testclasses.abap b/src/checks/y_check_prefer_new_to_crt_obj.clas.testclasses.abap new file mode 100644 index 00000000..da741938 --- /dev/null +++ b/src/checks/y_check_prefer_new_to_crt_obj.clas.testclasses.abap @@ -0,0 +1,68 @@ +CLASS ltc_create_object DEFINITION INHERITING FROM y_unit_test_base FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_cut REDEFINITION. + METHODS get_code_with_issue REDEFINITION. + METHODS get_code_without_issue REDEFINITION. + METHODS get_code_with_exemption REDEFINITION. +ENDCLASS. + +CLASS ltc_create_object IMPLEMENTATION. + + METHOD get_cut. + result ?= NEW y_check_prefer_new_to_crt_obj( ). + ENDMETHOD. + + METHOD get_code_with_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS example. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD example.' ) + ( ' DATA prefer_new_to_crt_obj TYPE REF TO y_check_prefer_new_to_crt_obj. ' ) + ( ' CREATE OBJECT prefer_new_to_crt_obj. ' ) + ( ' ENDMETHOD.' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + + METHOD get_code_without_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS example. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD example.' ) + ( ' DATA(prefer_new_to_crt_obj) = NEW y_check_prefer_new_to_crt_obj( ). ' ) + ( ' ENDMETHOD.' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + + METHOD get_code_with_exemption. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS example. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD example.' ) + ( ' DATA prefer_new_to_crt_obj TYPE REF TO y_check_prefer_new_to_crt_obj. ' ) + ( ' CREATE OBJECT prefer_new_to_crt_obj. "#EC PREF_NEW' ) + ( ' ENDMETHOD.' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + +ENDCLASS. diff --git a/src/checks/y_check_prefer_new_to_crt_obj.clas.xml b/src/checks/y_check_prefer_new_to_crt_obj.clas.xml new file mode 100644 index 00000000..ea4a0e74 --- /dev/null +++ b/src/checks/y_check_prefer_new_to_crt_obj.clas.xml @@ -0,0 +1,17 @@ + + + + + + Y_CHECK_PREFER_NEW_TO_CRT_OBJ + E + Prefer New to Create Object + 1 + X + X + X + X + + + + diff --git a/src/checks/y_check_procedure_coverage.clas.abap b/src/checks/y_check_procedure_coverage.clas.abap index 60ed2e4a..d7178ae4 100644 --- a/src/checks/y_check_procedure_coverage.clas.abap +++ b/src/checks/y_check_procedure_coverage.clas.abap @@ -5,7 +5,6 @@ CLASS y_check_procedure_coverage DEFINITION PUBLIC INHERITING FROM y_check_base PROTECTED SECTION. METHODS execute_check REDEFINITION. METHODS inspect_tokens REDEFINITION. - ENDCLASS. @@ -16,14 +15,14 @@ CLASS y_check_procedure_coverage IMPLEMENTATION. METHOD constructor. super->constructor( ). - version = '0001'. + version = version + 1. - settings-prio = c_note. settings-threshold = 30. settings-is_threshold_reversed = abap_true. settings-disable_on_prodcode_selection = abap_true. settings-disable_on_testcode_selection = abap_true. settings-apply_on_test_code = abap_false. + settings-ignore_pseudo_comments = abap_true. settings-documentation = |{ c_docs_path-checks }unit-test-coverages.md|. set_check_message( 'Procedure Coverage must be higher than &2%! (&1%<=&2%)' ). @@ -50,14 +49,14 @@ CLASS y_check_procedure_coverage IMPLEMENTATION. RETURN. ENDIF. - raise_error( statement_level = 1 - statement_index = 1 - statement_from = 1 - error_priority = check_configuration-prio - parameter_01 = |{ procedure }| - parameter_02 = |{ check_configuration-threshold }| - parameter_03 = |{ coverage->get_total( ) }| - parameter_04 = |{ coverage->get_executed( ) }| ). + raise_error( statement_level = 1 + statement_index = 1 + statement_from = 1 + error_priority = check_configuration-prio + parameter_01 = |{ procedure }| + parameter_02 = |{ check_configuration-threshold }| + parameter_03 = |{ coverage->get_total( ) }| + parameter_04 = |{ coverage->get_executed( ) }| ). ENDMETHOD. @@ -65,6 +64,4 @@ CLASS y_check_procedure_coverage IMPLEMENTATION. METHOD inspect_tokens. RETURN. ENDMETHOD. - - ENDCLASS. diff --git a/src/checks/y_check_profile_message.clas.abap b/src/checks/y_check_profile_message.clas.abap index 313ac194..c87cdcc6 100644 --- a/src/checks/y_check_profile_message.clas.abap +++ b/src/checks/y_check_profile_message.clas.abap @@ -11,9 +11,11 @@ CLASS y_check_profile_message DEFINITION PUBLIC INHERITING FROM y_check_base CRE CLASS-DATA ran TYPE abap_bool. METHODS get_profiles RETURNING VALUE(result) TYPE y_if_profile_manager=>profile_assignments. METHODS list_profiles IMPORTING profiles TYPE y_if_profile_manager=>profile_assignments - RETURNING value(result) TYPE string. + RETURNING VALUE(result) TYPE string. ENDCLASS. + + CLASS y_check_profile_message IMPLEMENTATION. @@ -28,7 +30,7 @@ CLASS y_check_profile_message IMPLEMENTATION. settings-threshold = 0. settings-apply_on_test_code = abap_true. settings-apply_on_productive_code = abap_true. - settings-prio = c_note. + settings-ignore_pseudo_comments = abap_true. set_check_message( '&1 Profile(s) in use: &2.' ). ENDMETHOD. @@ -46,12 +48,12 @@ CLASS y_check_profile_message IMPLEMENTATION. DATA(profiles) = get_profiles( ). - raise_error( statement_level = 1 - statement_index = 1 - statement_from = 1 - error_priority = check_configuration-prio - parameter_01 = |{ lines( profiles ) }| - parameter_02 = |{ list_profiles( profiles ) }| ). + raise_error( statement_level = 1 + statement_index = 1 + statement_from = 1 + error_priority = check_configuration-prio + parameter_01 = |{ lines( profiles ) }| + parameter_02 = |{ list_profiles( profiles ) }| ). ran = abap_true. ENDMETHOD. @@ -63,24 +65,24 @@ CLASS y_check_profile_message IMPLEMENTATION. METHOD inform. - super->inform( p_sub_obj_type = 'TRAN' - p_sub_obj_name = 'Y_CODE_PAL_PROFILE' - p_position = '' - p_line = '' - p_column = '' - p_errcnt = p_errcnt - p_kind = p_kind - p_test = p_test - p_code = p_code - p_suppress = p_suppress - p_param_1 = p_param_1 - p_param_2 = p_param_2 - p_param_3 = p_param_3 - p_param_4 = p_param_4 - p_inclspec = p_inclspec - p_detail = p_detail - p_checksum_1 = p_checksum_1 - p_comments = p_comments ). + super->inform( p_sub_obj_type = 'TRAN' + p_sub_obj_name = 'Y_CODE_PAL_PROFILE' + p_position = '' + p_line = '' + p_column = '' + p_errcnt = p_errcnt + p_kind = p_kind + p_test = p_test + p_code = p_code + p_suppress = p_suppress + p_param_1 = p_param_1 + p_param_2 = p_param_2 + p_param_3 = p_param_3 + p_param_4 = p_param_4 + p_inclspec = p_inclspec + p_detail = p_detail + p_checksum_1 = p_checksum_1 + p_comments = p_comments ). ENDMETHOD. @@ -99,6 +101,4 @@ CLASS y_check_profile_message IMPLEMENTATION. ELSE |{ result }, { -profile }| ). ENDLOOP. ENDMETHOD. - - ENDCLASS. diff --git a/src/checks/y_check_pseudo_comment_usage.clas.abap b/src/checks/y_check_pseudo_comment_usage.clas.abap index b645a7ea..849e0700 100644 --- a/src/checks/y_check_pseudo_comment_usage.clas.abap +++ b/src/checks/y_check_pseudo_comment_usage.clas.abap @@ -18,11 +18,11 @@ CLASS y_check_pseudo_comment_usage DEFINITION PUBLIC INHERITING FROM y_check_bas METHODS check_result. METHODS select_object_list RETURNING VALUE(result) LIKE name_tab - RAISING cx_failed. + RAISING cx_failed. - METHODS call_get_pseudo_comment IMPORTING obj_name TYPE stokesx-str + METHODS call_get_pseudo_comment IMPORTING obj_name TYPE stokesx-str RETURNING VALUE(result) TYPE stokesx-str - RAISING cx_sy_create_object_error. + RAISING cx_sy_create_object_error. ENDCLASS. @@ -52,7 +52,7 @@ CLASS y_check_pseudo_comment_usage IMPLEMENTATION. settings-threshold = 0. settings-apply_on_test_code = abap_true. settings-apply_on_productive_code = abap_true. - settings-prio = c_note. + settings-ignore_pseudo_comments = abap_true. relevant_statement_types = VALUE #( BASE relevant_statement_types ( scan_struc_stmnt_type-class_definition ) @@ -72,7 +72,7 @@ CLASS y_check_pseudo_comment_usage IMPLEMENTATION. LOOP AT class_names ASSIGNING FIELD-SYMBOL(). TRY. IF token-str CS call_get_pseudo_comment( ). - ADD 1 TO pseudo_comment_counter. + pseudo_comment_counter = pseudo_comment_counter + 1. ENDIF. CATCH cx_sy_create_object_error. CONTINUE. @@ -93,8 +93,8 @@ CLASS y_check_pseudo_comment_usage IMPLEMENTATION. METHOD inspect_tokens. LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() FROM statement-from TO statement-to - WHERE type EQ 'C' - OR type EQ 'P'. + WHERE type = 'C' + OR type = 'P'. count_cc_pseudo_comments( ). ENDLOOP. ENDMETHOD. @@ -112,27 +112,29 @@ CLASS y_check_pseudo_comment_usage IMPLEMENTATION. raise_error( statement_level = 1 statement_index = 1 statement_from = 1 - error_priority = check_configuration-prio - parameter_01 = |{ pseudo_comment_counter }| ). + error_priority = check_configuration-prio + parameter_01 = |{ pseudo_comment_counter }| ). ENDMETHOD. METHOD select_object_list. - SELECT SINGLE devclass FROM tadir - WHERE obj_name EQ @myname - INTO @DATA(packagename). + SELECT SINGLE devclass + FROM tadir + WHERE obj_name = @myname + INTO @DATA(packagename). + IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_failed. ENDIF. - SELECT obj_name FROM tadir - WHERE devclass EQ @packagename AND - obj_name NE @check_base_name - INTO TABLE @result. + SELECT obj_name + FROM tadir + WHERE devclass = @packagename + AND obj_name <> @check_base_name + INTO TABLE @result. + IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_failed. ENDIF. ENDMETHOD. - - ENDCLASS. diff --git a/src/checks/y_check_receiving_usage.clas.abap b/src/checks/y_check_receiving_usage.clas.abap index 2cde6c6c..9d7a7b30 100644 --- a/src/checks/y_check_receiving_usage.clas.abap +++ b/src/checks/y_check_receiving_usage.clas.abap @@ -25,7 +25,7 @@ CLASS Y_CHECK_RECEIVING_USAGE IMPLEMENTATION. METHOD inspect_tokens. CHECK get_token_abs( statement-from ) CP '*(*'. - CHECK get_token_abs( statement-from ) NE 'BADI'. + CHECK get_token_abs( statement-from ) <> 'BADI'. DATA(has_receiving) = abap_false. DATA(has_classic_exception) = abap_false. @@ -35,12 +35,12 @@ CLASS Y_CHECK_RECEIVING_USAGE IMPLEMENTATION. LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() FROM statement-from TO statement-to. IF has_receiving = abap_false. - has_receiving = xsdbool( -str EQ 'RECEIVING' AND - get_token_abs( statement-from + token_index + 1 ) NE '=' ). + has_receiving = xsdbool( -str = 'RECEIVING' AND + get_token_abs( statement-from + token_index + 1 ) <> '=' ). ENDIF. IF has_classic_exception = abap_false. - has_classic_exception = xsdbool( -str EQ 'EXCEPTIONS' AND - get_token_abs( statement-from + token_index + 1 ) NE '=' ). + has_classic_exception = xsdbool( -str = 'EXCEPTIONS' AND + get_token_abs( statement-from + token_index + 1 ) <> '=' ). ENDIF. token_index = token_index + 1. diff --git a/src/checks/y_check_returning_name.clas.abap b/src/checks/y_check_returning_name.clas.abap index ed9089aa..1b99092c 100644 --- a/src/checks/y_check_returning_name.clas.abap +++ b/src/checks/y_check_returning_name.clas.abap @@ -20,10 +20,9 @@ CLASS y_check_returning_name IMPLEMENTATION. settings-pseudo_comment = '"#EC RET_NAME' ##NO_TEXT. settings-disable_threshold_selection = abap_true. settings-threshold = 0. - settings-prio = c_warning. settings-documentation = |{ c_docs_path-checks }returning-name.md|. - version = '001'. + version = version + 1. relevant_statement_types = VALUE #( ( scan_struc_stmnt_type-class_definition ) ). relevant_structure_types = VALUE #( ). diff --git a/src/checks/y_check_scope_of_variable.clas.abap b/src/checks/y_check_scope_of_variable.clas.abap index b6b3a600..ae0bef25 100644 --- a/src/checks/y_check_scope_of_variable.clas.abap +++ b/src/checks/y_check_scope_of_variable.clas.abap @@ -28,7 +28,6 @@ CLASS y_check_scope_of_variable IMPLEMENTATION. settings-pseudo_comment = '"#EC SCOPE_OF_VAR' ##NO_TEXT. settings-disable_threshold_selection = abap_true. settings-threshold = 0. - settings-prio = c_warning. settings-documentation = |{ c_docs_path-checks }scope-of-variable.md|. set_check_message( 'Variable in use out of its scope!' ). @@ -62,7 +61,7 @@ CLASS y_check_scope_of_variable IMPLEMENTATION. CONTINUE. ENDIF. - LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() + LOOP AT ref_scan_manager->tokens TRANSPORTING NO FIELDS FROM -from TO -to WHERE str = variable. diff --git a/src/checks/y_check_self_reference.clas.abap b/src/checks/y_check_self_reference.clas.abap index b546b3d0..e59603ef 100644 --- a/src/checks/y_check_self_reference.clas.abap +++ b/src/checks/y_check_self_reference.clas.abap @@ -49,7 +49,7 @@ CLASS y_check_self_reference IMPLEMENTATION. METHOD has_self_reference. - LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() + LOOP AT ref_scan_manager->tokens TRANSPORTING NO FIELDS FROM statement-from TO statement-to WHERE str CP 'ME->*'. result = abap_true. diff --git a/src/checks/y_check_statement_coverage.clas.abap b/src/checks/y_check_statement_coverage.clas.abap index 120e061e..c004fd09 100644 --- a/src/checks/y_check_statement_coverage.clas.abap +++ b/src/checks/y_check_statement_coverage.clas.abap @@ -5,7 +5,6 @@ CLASS y_check_statement_coverage DEFINITION PUBLIC INHERITING FROM y_check_base PROTECTED SECTION. METHODS execute_check REDEFINITION. METHODS inspect_tokens REDEFINITION. - ENDCLASS. @@ -16,14 +15,14 @@ CLASS y_check_statement_coverage IMPLEMENTATION. METHOD constructor. super->constructor( ). - version = '0001'. + version = version + 1. - settings-prio = c_note. settings-threshold = 60. settings-is_threshold_reversed = abap_true. settings-disable_on_prodcode_selection = abap_true. settings-disable_on_testcode_selection = abap_true. settings-apply_on_test_code = abap_false. + settings-ignore_pseudo_comments = abap_true. settings-documentation = |{ c_docs_path-checks }unit-test-coverages.md|. set_check_message( 'Statement Coverage must be higher than &2%! (&1%<=&2%)' ). @@ -50,14 +49,14 @@ CLASS y_check_statement_coverage IMPLEMENTATION. RETURN. ENDIF. - raise_error( statement_level = 1 - statement_index = 1 - statement_from = 1 - error_priority = check_configuration-prio - parameter_01 = |{ statement }| - parameter_02 = |{ check_configuration-threshold }| - parameter_03 = |{ coverage->get_total( ) }| - parameter_04 = |{ coverage->get_executed( ) }| ). + raise_error( statement_level = 1 + statement_index = 1 + statement_from = 1 + error_priority = check_configuration-prio + parameter_01 = |{ statement }| + parameter_02 = |{ check_configuration-threshold }| + parameter_03 = |{ coverage->get_total( ) }| + parameter_04 = |{ coverage->get_executed( ) }| ). ENDMETHOD. @@ -65,6 +64,4 @@ CLASS y_check_statement_coverage IMPLEMENTATION. METHOD inspect_tokens. RETURN. ENDMETHOD. - - ENDCLASS. diff --git a/src/checks/y_check_test_seam_usage.clas.abap b/src/checks/y_check_test_seam_usage.clas.abap index aef9e4b1..2bbae65c 100644 --- a/src/checks/y_check_test_seam_usage.clas.abap +++ b/src/checks/y_check_test_seam_usage.clas.abap @@ -25,7 +25,7 @@ CLASS Y_CHECK_TEST_SEAM_USAGE IMPLEMENTATION. METHOD inspect_tokens. - CHECK get_token_abs( statement-from ) EQ 'TEST-SEAM'. + CHECK get_token_abs( statement-from ) = 'TEST-SEAM'. DATA(check_configuration) = detect_check_configuration( statement ). @@ -33,9 +33,9 @@ CLASS Y_CHECK_TEST_SEAM_USAGE IMPLEMENTATION. RETURN. ENDIF. - raise_error( statement_level = statement-level - statement_index = index - statement_from = statement-from - error_priority = check_configuration-prio ). + raise_error( statement_level = statement-level + statement_index = index + statement_from = statement-from + error_priority = check_configuration-prio ). ENDMETHOD. ENDCLASS. diff --git a/src/checks/y_check_unit_test_assert.clas.abap b/src/checks/y_check_unit_test_assert.clas.abap new file mode 100644 index 00000000..cd6b6134 --- /dev/null +++ b/src/checks/y_check_unit_test_assert.clas.abap @@ -0,0 +1,92 @@ +CLASS y_check_unit_test_assert DEFINITION PUBLIC INHERITING FROM y_check_base CREATE PUBLIC . + PUBLIC SECTION. + METHODS constructor. + + PROTECTED SECTION. + METHODS inspect_tokens REDEFINITION. + + PRIVATE SECTION. + METHODS get_act_and_exp IMPORTING statement TYPE sstmnt + EXPORTING act TYPE stokesx + exp TYPE stokesx. + + METHODS is_variable IMPORTING token TYPE stokesx + RETURNING VALUE(result) TYPE abap_bool. + +ENDCLASS. + + +CLASS y_check_unit_test_assert IMPLEMENTATION. + + + METHOD constructor. + super->constructor( ). + + settings-pseudo_comment = '"#EC UT_ASSERT' ##NO_TEXT. + settings-disable_threshold_selection = abap_true. + settings-apply_on_productive_code = abap_false. + settings-apply_on_test_code = abap_true. + settings-threshold = 0. + settings-documentation = |{ c_docs_path-checks }unit_test_assert.md|. + + relevant_statement_types = VALUE #( ( scan_struc_stmnt_type-method ) ). + relevant_structure_types = VALUE #( ). + + set_check_message( 'Invalid Unit Test Assertion!' ). + ENDMETHOD. + + + METHOD inspect_tokens. + CHECK get_token_abs( statement-from ) CP 'CL_ABAP_UNIT_ASSERT=>ASSERT*' + OR get_token_abs( statement-from ) CP 'CL_AUNIT_ASSERT=>ASSERT*'. + + get_act_and_exp( EXPORTING statement = statement + IMPORTING act = DATA(act) + exp = DATA(exp) ). + + IF act IS INITIAL + OR exp IS INITIAL. + RETURN. + ENDIF. + + IF act-str <> exp-str + AND ( is_variable( act ) = abap_true OR is_variable( exp ) = abap_true ). + RETURN. + ENDIF. + + DATA(check_configuration) = detect_check_configuration( statement ). + + IF check_configuration IS INITIAL. + RETURN. + ENDIF. + + raise_error( statement_level = statement-level + statement_index = index + statement_from = statement-from + error_priority = check_configuration-prio ). + ENDMETHOD. + + + METHOD get_act_and_exp. + LOOP AT ref_scan_manager->tokens ASSIGNING FIELD-SYMBOL() + FROM statement-from TO statement-to. + DATA(tabix) = sy-tabix. + CASE -str. + WHEN 'ACT'. + act = ref_scan_manager->tokens[ tabix + 2 ]. + WHEN 'EXP'. + exp = ref_scan_manager->tokens[ tabix + 2 ]. + WHEN OTHERS. + CONTINUE. + ENDCASE. + ENDLOOP. + ENDMETHOD. + + + METHOD is_variable. + result = COND #( WHEN token-type = scan_token_type-literal THEN abap_false + WHEN token-type = scan_token_type-identifier THEN xsdbool( token-str CN '0123456789' ) ). + ENDMETHOD. + + +ENDCLASS. diff --git a/src/checks/y_check_unit_test_assert.clas.testclasses.abap b/src/checks/y_check_unit_test_assert.clas.testclasses.abap new file mode 100644 index 00000000..15fd6890 --- /dev/null +++ b/src/checks/y_check_unit_test_assert.clas.testclasses.abap @@ -0,0 +1,307 @@ +CLASS ltc_same_variable DEFINITION INHERITING FROM y_unit_test_base FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_cut REDEFINITION. + METHODS get_code_with_issue REDEFINITION. + METHODS get_code_without_issue REDEFINITION. + METHODS get_code_with_exemption REDEFINITION. +ENDCLASS. + +CLASS ltc_same_variable IMPLEMENTATION. + + METHOD get_cut. + result ?= NEW y_check_unit_test_assert( ). + ENDMETHOD. + + METHOD get_code_with_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS sum FOR TESTING. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD sum. ' ) + ( ' " given ' ) + ( ' DATA(first) = 10. ' ) + ( ' DATA(second) = 10. ' ) + ( ' " when ' ) + ( ' DATA(sum) = first + second. ' ) + ( ' " then ' ) + ( ' cl_abap_unit_assert=>assert_equals( act = sum ' ) + ( ' exp = sum ). ' ) + ( ' ENDMETHOD. ' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + + METHOD get_code_without_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS sum FOR TESTING. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD sum. ' ) + ( ' " given ' ) + ( ' DATA(first) = 10. ' ) + ( ' DATA(second) = 10. ' ) + ( ' " when ' ) + ( ' DATA(sum) = first + second. ' ) + ( ' " then ' ) + ( ' cl_abap_unit_assert=>assert_equals( act = sum ' ) + ( ' exp = 20 ). ' ) + ( ' ENDMETHOD. ' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + + METHOD get_code_with_exemption. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS sum FOR TESTING. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD sum. ' ) + ( ' " given ' ) + ( ' DATA(first) = 10. ' ) + ( ' DATA(second) = 10. ' ) + ( ' " when ' ) + ( ' DATA(sum) = first + second. ' ) + ( ' " then ' ) + ( ' cl_abap_unit_assert=>assert_equals( act = sum ' ) + ( ' exp = sum ). "#EC UT_ASSERT ' ) + ( ' ENDMETHOD. ' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + +ENDCLASS. + + +CLASS ltc_hardcoded_number DEFINITION INHERITING FROM y_unit_test_base FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_cut REDEFINITION. + METHODS get_code_with_issue REDEFINITION. + METHODS get_code_without_issue REDEFINITION. + METHODS get_code_with_exemption REDEFINITION. +ENDCLASS. + +CLASS ltc_hardcoded_number IMPLEMENTATION. + + METHOD get_cut. + result ?= NEW y_check_unit_test_assert( ). + ENDMETHOD. + + METHOD get_code_with_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS sum FOR TESTING. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD sum. ' ) + ( ' " given ' ) + ( ' DATA(first) = 10. ' ) + ( ' DATA(second) = 10. ' ) + ( ' " when ' ) + ( ' DATA(sum) = first + second. ' ) + ( ' " then ' ) + ( ' cl_aunit_assert=>assert_differs( act = 10 ' ) + ( ' exp = 20 ). ' ) + ( ' ENDMETHOD. ' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + + METHOD get_code_without_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS sum FOR TESTING. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD sum. ' ) + ( ' " given ' ) + ( ' DATA(first) = 10. ' ) + ( ' DATA(second) = 10. ' ) + ( ' " when ' ) + ( ' DATA(sum) = first + second. ' ) + ( ' " then ' ) + ( ' cl_aunit_assert=>assert_differs( act = 10 ' ) + ( ' exp = sum ). ' ) + ( ' ENDMETHOD. ' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + + METHOD get_code_with_exemption. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS sum FOR TESTING. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD sum. ' ) + ( ' " given ' ) + ( ' DATA(first) = 10. ' ) + ( ' DATA(second) = 10. ' ) + ( ' " when ' ) + ( ' DATA(sum) = first + second. ' ) + ( ' " then ' ) + ( ' cl_aunit_assert=>assert_differs( act = 10 ' ) + ( ' exp = 20 ). "#EC UT_ASSERT ' ) + ( ' ENDMETHOD. ' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + +ENDCLASS. + + +CLASS ltc_hardcoded_string DEFINITION INHERITING FROM y_unit_test_base FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_cut REDEFINITION. + METHODS get_code_with_issue REDEFINITION. + METHODS get_code_without_issue REDEFINITION. + METHODS get_code_with_exemption REDEFINITION. +ENDCLASS. + +CLASS ltc_hardcoded_string IMPLEMENTATION. + + METHOD get_cut. + result ?= NEW y_check_unit_test_assert( ). + ENDMETHOD. + + METHOD get_code_with_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS example FOR TESTING. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD example. ' ) + ( | cl_aunit_assert=>assert_differs( act = 'A' | ) + ( | exp = 'B' ). | ) + ( ' ENDMETHOD. ' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + + METHOD get_code_without_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS example FOR TESTING. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD example. ' ) + ( ' DATA(system) = sy-sysid. ' ) + ( | cl_aunit_assert=>assert_differs( act = system | ) + ( | exp = 'B' ). | ) + ( ' ENDMETHOD. ' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + + METHOD get_code_with_exemption. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS example FOR TESTING. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD example. ' ) + ( | cl_aunit_assert=>assert_differs( act = 'A' | ) + ( | exp = 'B' ). "#EC UT_ASSERT | ) + ( ' ENDMETHOD. ' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + +ENDCLASS. + + +CLASS ltc_public_classdata DEFINITION INHERITING FROM ltc_hardcoded_string FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_code_without_issue REDEFINITION. +ENDCLASS. + +CLASS ltc_public_classdata IMPLEMENTATION. + + METHOD get_code_without_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS example FOR TESTING. ' ) + ( ' CLASS-DATA system TYPE string. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD example. ' ) + ( | cl_aunit_assert=>assert_differs( act = system | ) + ( | exp = 'B' ). | ) + ( ' ENDMETHOD. ' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + +ENDCLASS. + + +CLASS ltc_protected_data DEFINITION INHERITING FROM ltc_hardcoded_string FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. + PROTECTED SECTION. + METHODS get_code_without_issue REDEFINITION. +ENDCLASS. + +CLASS ltc_protected_data IMPLEMENTATION. + + METHOD get_code_without_issue. + result = VALUE #( + ( ' REPORT y_example. ' ) + + ( ' CLASS y_example DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. ' ) + ( ' PUBLIC SECTION. ' ) + ( ' METHODS example FOR TESTING. ' ) + ( ' PROTECTED SECTION. ' ) + ( ' DATA system TYPE string. ' ) + ( ' ENDCLASS. ' ) + + ( ' CLASS y_example IMPLEMENTATION. ' ) + ( ' METHOD example. ' ) + ( | cl_aunit_assert=>assert_differs( act = system | ) + ( | exp = 'system' ). | ) + ( ' ENDMETHOD. ' ) + ( ' ENDCLASS. ' ) + ). + ENDMETHOD. + +ENDCLASS. diff --git a/src/checks/y_check_unit_test_assert.clas.xml b/src/checks/y_check_unit_test_assert.clas.xml new file mode 100644 index 00000000..394c176d --- /dev/null +++ b/src/checks/y_check_unit_test_assert.clas.xml @@ -0,0 +1,17 @@ + + + + + + Y_CHECK_UNIT_TEST_ASSERT + E + Unit Test Assert Validator + 1 + X + X + X + X + + + + diff --git a/src/examples/y_demo_failures.clas.abap b/src/examples/y_demo_failures.clas.abap index 2c3d2447..4e2363e4 100644 --- a/src/examples/y_demo_failures.clas.abap +++ b/src/examples/y_demo_failures.clas.abap @@ -114,6 +114,8 @@ CLASS y_demo_failures DEFINITION PUBLIC FINAL CREATE PUBLIC. VALUE(age) TYPE i. "#EC RET_NAME #EC BOOL_PARAM "#EC OPTL_PARAM METHODS prefer_is_not_to_not_is. METHODS prefer_case_to_elseif. + METHODS prefer_new_to_create_object. + METHODS prefer_line_exists. METHODS deprecated_classes. METHODS scope_of_variable. @@ -402,6 +404,12 @@ CLASS Y_DEMO_FAILURES IMPLEMENTATION. ENDMETHOD. + METHOD prefer_new_to_create_object. + DATA demo_failures TYPE REF TO y_demo_failures. + CREATE OBJECT demo_failures. + ENDMETHOD. + + METHOD prefer_is_not_to_not_is. IF NOT attribute_1 IS INITIAL. attribute_1 = attribute_2. @@ -409,6 +417,16 @@ CLASS Y_DEMO_FAILURES IMPLEMENTATION. ENDMETHOD. + METHOD prefer_line_exists. + DATA tadir TYPE TABLE OF tadir. + DATA exists TYPE abap_bool. + READ TABLE tadir TRANSPORTING NO FIELDS WITH KEY object = 'y_demo_failures'. + IF sy-subrc = 0. + exists = abap_true. + ENDIF. + ENDMETHOD. + + METHOD pseudo_comment_usage. ENDMETHOD. "#EC EMPTY_PROCEDURE diff --git a/src/examples/y_demo_failures.clas.testclasses.abap b/src/examples/y_demo_failures.clas.testclasses.abap index 7bc29e73..e0734b39 100644 --- a/src/examples/y_demo_failures.clas.testclasses.abap +++ b/src/examples/y_demo_failures.clas.testclasses.abap @@ -3,6 +3,7 @@ CLASS local_test_class DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT PRIVATE SECTION. METHODS db_access_in_ut FOR TESTING. METHODS external_call_in_ut FOR TESTING. + METHODS unit_test_assert FOR TESTING. ENDCLASS. CLASS local_test_class IMPLEMENTATION. @@ -10,10 +11,24 @@ CLASS local_test_class IMPLEMENTATION. METHOD db_access_in_ut. SELECT SINGLE * FROM t100 INTO @DATA(entry). + + cl_abap_unit_assert=>assert_not_initial( entry ). ENDMETHOD. METHOD external_call_in_ut. DATA alv TYPE REF TO cl_gui_alv_grid. + cl_abap_unit_assert=>fail( 'No Gui Allowed' ). + ENDMETHOD. + + METHOD unit_test_assert. + "Given + DATA(first) = 10. + DATA(second) = 20. + "When + DATA(sum) = first + second. + "Then + cl_abap_unit_assert=>assert_equals( act = sum + exp = sum ). ENDMETHOD. ENDCLASS. diff --git a/src/foundation/y_check_base.clas.abap b/src/foundation/y_check_base.clas.abap index 3b0f3e3b..3307562f 100644 --- a/src/foundation/y_check_base.clas.abap +++ b/src/foundation/y_check_base.clas.abap @@ -30,6 +30,7 @@ CLASS y_check_base DEFINITION PUBLIC ABSTRACT apply_on_test_code TYPE ycicc_testcode, documentation TYPE c LENGTH 1000, is_threshold_reversed TYPE abap_bool, + ignore_pseudo_comments TYPE abap_bool, END OF settings. METHODS constructor. @@ -44,7 +45,6 @@ CLASS y_check_base DEFINITION PUBLIC ABSTRACT CONSTANTS initial_date TYPE datum VALUE '19000101'. DATA check_configurations TYPE y_if_clean_code_manager=>check_configurations. - DATA check_name TYPE seoclsname. DATA clean_code_exemption_handler TYPE REF TO y_if_exemption. DATA clean_code_manager TYPE REF TO y_if_clean_code_manager. DATA is_testcode TYPE abap_bool. @@ -104,8 +104,7 @@ CLASS y_check_base DEFINITION PUBLIC ABSTRACT parameter_04 TYPE csequence OPTIONAL is_include_specific TYPE sci_inclspec DEFAULT ' ' additional_information TYPE xstring OPTIONAL - checksum TYPE int4 OPTIONAL - pseudo_comments TYPE t_comments OPTIONAL. "#EC OPTL_PARAM + checksum TYPE int4 OPTIONAL. "#EC OPTL_PARAM METHODS get_column_abs REDEFINITION. METHODS get_column_rel REDEFINITION. @@ -149,14 +148,17 @@ CLASS y_check_base DEFINITION PUBLIC ABSTRACT METHODS is_structure_type_relevant IMPORTING structure TYPE sstruc RETURNING VALUE(result) TYPE abap_bool. - METHODS is_app_comp_in_scope IMPORTING level TYPE stmnt_levl - RETURNING value(result) TYPE abap_bool. + METHODS is_app_comp_in_scope IMPORTING level TYPE stmnt_levl + RETURNING VALUE(result) TYPE abap_bool. + + METHODS switch_bool IMPORTING boolean TYPE abap_bool + RETURNING VALUE(result) TYPE abap_bool. ENDCLASS. -CLASS y_check_base IMPLEMENTATION. +CLASS Y_CHECK_BASE IMPLEMENTATION. METHOD check_start_conditions. @@ -176,11 +178,12 @@ CLASS y_check_base IMPLEMENTATION. has_documentation = abap_true. settings-object_created_on = '20190101'. - settings-prio = c_error. + settings-prio = c_note. settings-threshold = 5. settings-apply_on_productive_code = abap_true. settings-apply_on_test_code = abap_true. settings-documentation = |{ c_docs_path-main }check_documentation.md|. + settings-ignore_pseudo_comments = abap_false. has_attributes = do_attributes_exist( ). @@ -220,10 +223,12 @@ CLASS y_check_base IMPLEMENTATION. CONTINUE. ENDIF. - IF result IS INITIAL OR is_config_setup_valid( previous_config = result - config = ) = abap_true. + IF result IS INITIAL + OR is_config_setup_valid( previous_config = result + config = ) = abap_true. result = . ENDIF. + ENDLOOP. IF result IS INITIAL. @@ -290,15 +295,14 @@ CLASS y_check_base IMPLEMENTATION. METHOD get_attributes. - DATA check_configuration TYPE y_if_clean_code_manager=>check_configuration. - READ TABLE check_configurations INTO check_configuration INDEX 1. + READ TABLE check_configurations INTO DATA(check_configuration) INDEX 1. IF sy-subrc <> 0. check_configuration-apply_on_productive_code = settings-apply_on_productive_code. check_configuration-apply_on_testcode = settings-apply_on_test_code. check_configuration-object_creation_date = settings-object_created_on. check_configuration-prio = settings-prio. check_configuration-threshold = settings-threshold. - + check_configuration-ignore_pseudo_comments = settings-ignore_pseudo_comments. APPEND check_configuration TO check_configurations. ENDIF. EXPORT @@ -307,6 +311,7 @@ CLASS y_check_base IMPLEMENTATION. threshold = check_configuration-threshold apply_on_productive_code = check_configuration-apply_on_productive_code apply_on_testcode = check_configuration-apply_on_testcode + ignore_pseudo_comments = check_configuration-ignore_pseudo_comments TO DATA BUFFER p_attributes. ENDMETHOD. @@ -333,11 +338,11 @@ CLASS y_check_base IMPLEMENTATION. DO. READ TABLE tokens INDEX p_n ASSIGNING FIELD-SYMBOL(). - IF sy-subrc EQ 0 AND -row <> 0. + IF sy-subrc = 0 AND -row <> 0. p_result = -col. RETURN. ENDIF. - SUBTRACT 1 FROM p_n. + p_n = p_n - 1. ENDDO. ENDMETHOD. @@ -353,27 +358,22 @@ CLASS y_check_base IMPLEMENTATION. DO. READ TABLE tokens INDEX index ASSIGNING FIELD-SYMBOL(). - IF sy-subrc EQ 0 AND -row <> 0. + IF sy-subrc = 0 AND -row <> 0. p_result = -col. RETURN. ENDIF. - SUBTRACT 1 FROM index. + index = index - 1. ENDDO. ENDMETHOD. METHOD get_include. - DATA l_levels_wa LIKE LINE OF ref_scan->levels. - DATA l_level TYPE i. + DATA(l_level) = COND #( WHEN p_level IS SUPPLIED THEN p_level + ELSE statement_wa-level ). - IF p_level IS SUPPLIED. - l_level = p_level. - ELSE. - l_level = statement_wa-level. - ENDIF. DO. - READ TABLE ref_scan_manager->levels INDEX l_level INTO l_levels_wa. - IF sy-subrc NE 0. + READ TABLE ref_scan_manager->levels INDEX l_level INTO DATA(l_levels_wa). + IF sy-subrc <> 0. RETURN. ENDIF. IF l_levels_wa-type = 'P'. @@ -393,11 +393,11 @@ CLASS y_check_base IMPLEMENTATION. DO. READ TABLE tokens INDEX p_n ASSIGNING FIELD-SYMBOL(). - IF sy-subrc EQ 0 AND -row <> 0. + IF sy-subrc = 0 AND -row <> 0. p_result = -row. RETURN. ENDIF. - SUBTRACT 1 FROM p_n. + p_n = p_n - 1. ENDDO. ENDMETHOD. @@ -410,12 +410,12 @@ CLASS y_check_base IMPLEMENTATION. DO. READ TABLE tokens INDEX p_n ASSIGNING FIELD-SYMBOL(). - IF sy-subrc EQ 0 AND -row <> 0. + IF sy-subrc = 0 AND -row <> 0. p_column = -col. p_line = -row. RETURN. ENDIF. - SUBTRACT 1 FROM p_n. + p_n = p_n - 1. ENDDO. ENDMETHOD. @@ -430,12 +430,12 @@ CLASS y_check_base IMPLEMENTATION. DO. READ TABLE tokens INDEX p_n ASSIGNING FIELD-SYMBOL(). - IF sy-subrc EQ 0 AND -row <> 0. + IF sy-subrc = 0 AND -row <> 0. p_column = -col. p_line = -row. RETURN. ENDIF. - SUBTRACT 1 FROM p_n. + p_n = p_n - 1. ENDDO. ENDMETHOD. @@ -451,27 +451,25 @@ CLASS y_check_base IMPLEMENTATION. DO. READ TABLE tokens INDEX index ASSIGNING FIELD-SYMBOL(). - IF sy-subrc EQ 0 AND -row <> 0. + IF sy-subrc = 0 AND -row <> 0. p_result = -row. RETURN. ENDIF. - SUBTRACT 1 FROM index. + index = index - 1. ENDDO. ENDMETHOD. METHOD get_token_abs. READ TABLE ref_scan_manager->tokens INDEX p_n INTO token_wa. - IF sy-subrc EQ 0. + IF sy-subrc = 0. p_result = token_wa-str. ENDIF. ENDMETHOD. METHOD get_token_rel. - DATA l_index TYPE i. - - l_index = statement_wa-from + p_n - 1. + DATA(l_index) = statement_wa-from + p_n - 1. IF l_index > statement_wa-to. RETURN. ENDIF. @@ -512,6 +510,7 @@ CLASS y_check_base IMPLEMENTATION. check_configuration-apply_on_productive_code = settings-apply_on_productive_code. check_configuration-apply_on_testcode = settings-apply_on_test_code. check_configuration-threshold = settings-threshold. + check_configuration-ignore_pseudo_comments = settings-ignore_pseudo_comments. ENDIF. INSERT VALUE #( @@ -550,6 +549,16 @@ CLASS y_check_base IMPLEMENTATION. ) INTO TABLE sci_attributes. ENDIF. + check_configuration-ignore_pseudo_comments = switch_bool( check_configuration-ignore_pseudo_comments ). + + IF settings-pseudo_comment IS NOT INITIAL. + INSERT VALUE #( + kind = '' + ref = REF #( check_configuration-ignore_pseudo_comments ) + text = |Allow { settings-pseudo_comment }| + ) INTO TABLE sci_attributes. + ENDIF. + title = description. attributes_ok = abap_false. @@ -561,8 +570,10 @@ CLASS y_check_base IMPLEMENTATION. p_message = message p_display = p_display ) = abap_true. attributes_ok = abap_true. + check_configuration-ignore_pseudo_comments = switch_bool( check_configuration-ignore_pseudo_comments ). RETURN. ENDIF. + IF check_configuration-apply_on_productive_code = abap_false AND check_configuration-apply_on_testcode = abap_false. message = 'Choose the Type of Code to be checked'(300). @@ -577,6 +588,8 @@ CLASS y_check_base IMPLEMENTATION. ENDIF. ENDWHILE. + check_configuration-ignore_pseudo_comments = switch_bool( check_configuration-ignore_pseudo_comments ). + CLEAR check_configurations. APPEND check_configuration TO check_configurations. use_default_attributes = abap_false. @@ -597,7 +610,7 @@ CLASS y_check_base IMPLEMENTATION. ENDIF. IF clean_code_exemption_handler IS NOT BOUND. - clean_code_exemption_handler = new y_exemption_handler( ). + clean_code_exemption_handler = NEW y_exemption_handler( ). ENDIF. IF test_code_detector IS NOT BOUND. @@ -638,6 +651,7 @@ CLASS y_check_base IMPLEMENTATION. threshold = check_configuration-threshold apply_on_productive_code = check_configuration-apply_on_productive_code apply_on_testcode = check_configuration-apply_on_testcode + ignore_pseudo_comments = check_configuration-ignore_pseudo_comments FROM DATA BUFFER p_attributes. APPEND check_configuration TO check_configurations. CATCH cx_root. "#EC NEED_CX_ROOT @@ -647,15 +661,17 @@ CLASS y_check_base IMPLEMENTATION. METHOD raise_error. + DATA(pseudo_comment) = COND #( WHEN settings-ignore_pseudo_comments = abap_false THEN settings-pseudo_comment ). + DATA(pcom_detector) = NEW y_pseudo_comment_detector( )->is_pseudo_comment( ref_scan_manager = ref_scan_manager + scimessages = scimessages + test = myname + code = get_code( error_priority ) + suppress = pseudo_comment + position = statement_index ). statistics->collect( kind = error_priority - pc = NEW y_pseudo_comment_detector( )->is_pseudo_comment( ref_scan_manager = ref_scan_manager - scimessages = scimessages - test = myname - code = get_code( error_priority ) - suppress = settings-pseudo_comment - position = statement_index ) ). - - IF cl_abap_typedescr=>describe_by_object_ref( ref_scan_manager )->get_relative_name( ) EQ 'Y_REF_SCAN_MANAGER'. + pc = pcom_detector ). + + IF cl_abap_typedescr=>describe_by_object_ref( ref_scan_manager )->get_relative_name( ) = 'Y_REF_SCAN_MANAGER'. inform( p_sub_obj_type = object_type p_sub_obj_name = get_include( p_level = statement_level ) p_position = statement_index @@ -665,21 +681,21 @@ CLASS y_check_base IMPLEMENTATION. p_kind = error_priority p_test = myname p_code = get_code( error_priority ) - p_suppress = settings-pseudo_comment + p_suppress = pseudo_comment p_param_1 = parameter_01 p_param_2 = parameter_02 p_param_3 = parameter_03 p_param_4 = parameter_04 p_inclspec = is_include_specific p_detail = additional_information - p_checksum_1 = checksum - p_comments = pseudo_comments ). + p_checksum_1 = checksum ). ENDIF. - ENDMETHOD. METHOD run. + DATA profile_configurations TYPE y_if_clean_code_manager=>check_configurations. + instantiate_objects( ). IF attributes_maintained = abap_false AND has_attributes = abap_true. @@ -691,13 +707,11 @@ CLASS y_check_base IMPLEMENTATION. RETURN. ENDIF. - DATA profile_configurations TYPE y_if_clean_code_manager=>check_configurations. - TRY. check_start_conditions( ). profile_configurations = clean_code_manager->read_check_customizing( myname ). CATCH ycx_no_check_customizing. - IF profile_configurations IS INITIAL AND attributes_ok = abap_false. + IF profile_configurations IS INITIAL AND attributes_ok = abap_false. FREE ref_scan_manager. RETURN. ELSEIF attributes_ok = abap_true. @@ -739,24 +753,27 @@ CLASS y_check_base IMPLEMENTATION. METHOD is_config_setup_valid. - result = xsdbool( ( previous_config-prio = config-prio AND is_treshold_config_valid( config_threshold = config-threshold - previous_threshold = previous_config-threshold ) = abap_true ) OR - ( previous_config-prio <> c_error AND config-prio = c_error ) OR - ( previous_config-prio = c_note AND config-prio = c_warning ) ). + result = xsdbool( ( previous_config-prio = config-prio + AND is_treshold_config_valid( config_threshold = config-threshold + previous_threshold = previous_config-threshold ) = abap_true ) + OR ( previous_config-prio <> c_error AND config-prio = c_error ) + OR ( previous_config-prio = c_note AND config-prio = c_warning ) + OR ( previous_config-ignore_pseudo_comments = abap_false + AND config-ignore_pseudo_comments = abap_true ) ). ENDMETHOD. METHOD is_skipped. - result = xsdbool( ( config-threshold < error_count AND settings-is_threshold_reversed = abap_true ) OR - ( config-threshold > error_count AND settings-is_threshold_reversed = abap_false ) OR - ( is_testcode = abap_true AND config-apply_on_testcode = abap_false ) OR - ( is_testcode = abap_false AND config-apply_on_productive_code = abap_false ) ). + result = xsdbool( ( config-threshold < error_count AND settings-is_threshold_reversed = abap_true ) + OR ( config-threshold > error_count AND settings-is_threshold_reversed = abap_false ) + OR ( is_testcode = abap_true AND config-apply_on_testcode = abap_false ) + OR ( is_testcode = abap_false AND config-apply_on_productive_code = abap_false ) ). ENDMETHOD. METHOD is_treshold_config_valid. - result = xsdbool( ( previous_threshold >= config_threshold AND settings-is_threshold_reversed = abap_false ) OR - ( previous_threshold < config_threshold AND settings-is_threshold_reversed = abap_true ) ). + result = xsdbool( ( previous_threshold >= config_threshold AND settings-is_threshold_reversed = abap_false ) + OR ( previous_threshold < config_threshold AND settings-is_threshold_reversed = abap_true ) ). ENDMETHOD. @@ -799,4 +816,7 @@ CLASS y_check_base IMPLEMENTATION. ENDMETHOD. + METHOD switch_bool. + result = xsdbool( boolean = abap_false ). + ENDMETHOD. ENDCLASS. diff --git a/src/foundation/y_ci_check_registration.prog.abap b/src/foundation/y_ci_check_registration.prog.abap index b097c24e..d112f962 100644 --- a/src/foundation/y_ci_check_registration.prog.abap +++ b/src/foundation/y_ci_check_registration.prog.abap @@ -59,17 +59,17 @@ CLASS lcl_check_registration IMPLEMENTATION. ENDMETHOD. METHOD is_check_compatible. - IF name NE get_category_name( ). - DATA code_pal_check TYPE REF TO y_check_base. "#EC DECL_IN_IF + DATA code_pal_check TYPE REF TO y_check_base. + IF name <> get_category_name( ). CREATE OBJECT code_pal_check TYPE (name). ENDIF. ENDMETHOD. METHOD select_object_list. SELECT SINGLE devclass FROM tadir - WHERE obj_name EQ @reference-check_base - AND object EQ @reference-class - AND delflag EQ @abap_false + WHERE obj_name = @reference-check_base + AND object = @reference-class + AND delflag = @abap_false INTO @DATA(packagename). IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_failed. @@ -78,9 +78,9 @@ CLASS lcl_check_registration IMPLEMENTATION. REPLACE reference-foundation IN packagename WITH reference-checks. SELECT obj_name FROM tadir - WHERE devclass EQ @packagename - AND object EQ @reference-class - AND delflag EQ @abap_false + WHERE devclass = @packagename + AND object = @reference-class + AND delflag = @abap_false INTO TABLE @result. IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_failed. @@ -93,7 +93,7 @@ CLASS lcl_check_registration IMPLEMENTATION. METHOD activate_check. is_check_compatible( name ). - INSERT scitests FROM name. + INSERT scitests FROM @name. IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_failed. ENDIF. @@ -102,7 +102,7 @@ CLASS lcl_check_registration IMPLEMENTATION. METHOD deactivate_check. is_check_compatible( name ). - DELETE FROM scitests WHERE name = name. + DELETE FROM scitests WHERE name = @name. IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_failed. ENDIF. @@ -140,12 +140,9 @@ CLASS lcl_util IMPLEMENTATION. TRY. lcl_check_registration=>activate_check( ). count_successes = count_successes + 1. - CATCH cx_failed. + CATCH cx_failed + cx_sy_create_object_error. count_errors = count_errors + 1. - - - DATA dta TYPE REF TO cl_ci_tests. - ENDTRY. ENDLOOP. WRITE: / |{ count_successes } { messages-successfully_activated }|. @@ -159,7 +156,8 @@ CLASS lcl_util IMPLEMENTATION. TRY. lcl_check_registration=>deactivate_check( ). count_successes = count_successes + 1. - CATCH cx_failed. + CATCH cx_failed + cx_sy_create_object_error. count_faults = count_faults + 1. ENDTRY. ENDLOOP. diff --git a/src/foundation/y_clean_code_manager.clas.abap b/src/foundation/y_clean_code_manager.clas.abap index 2cda64ef..ea4086d7 100644 --- a/src/foundation/y_clean_code_manager.clas.abap +++ b/src/foundation/y_clean_code_manager.clas.abap @@ -6,16 +6,17 @@ CLASS y_clean_code_manager DEFINITION PUBLIC CREATE PUBLIC. PRIVATE SECTION. METHODS determine_profiles RETURNING VALUE(result) TYPE string_table - RAISING ycx_no_check_customizing. + RAISING ycx_no_check_customizing. - METHODS determine_checks IMPORTING profile TYPE ycicc_profile - checkid TYPE seoclsname + METHODS determine_checks IMPORTING profile TYPE ycicc_profile + checkid TYPE seoclsname RETURNING VALUE(result) TYPE y_if_clean_code_manager=>check_configurations - RAISING ycx_no_check_customizing . + RAISING ycx_no_check_customizing . ENDCLASS. -CLASS y_clean_code_manager IMPLEMENTATION. + +CLASS Y_CLEAN_CODE_MANAGER IMPLEMENTATION. METHOD determine_checks. @@ -33,7 +34,8 @@ CLASS y_clean_code_manager IMPLEMENTATION. threshold = -threshold prio = -prio apply_on_productive_code = -apply_on_productive_code - apply_on_testcode = -apply_on_testcode ). + apply_on_testcode = -apply_on_testcode + ignore_pseudo_comments = -ignore_pseudo_comments ). result = VALUE #( BASE result ( CORRESPONDING #( check_configuration ) ) ). ENDLOOP. ENDMETHOD. @@ -50,12 +52,18 @@ CLASS y_clean_code_manager IMPLEMENTATION. FIND FIRST OCCURRENCE OF `Y_CLEAN_CODE_REPORTING` IN TABLE callstack. IF sy-subrc = 0. - SELECT SINGLE obj_name FROM tadir INTO obj_name - WHERE pgmid = 'R3TR' AND - object = 'TABL' AND - obj_name = profile_db. + SELECT SINGLE obj_name + FROM tadir + INTO @obj_name + WHERE pgmid = 'R3TR' + AND object = 'TABL' + AND obj_name = @profile_db. + IF sy-subrc = 0. - SELECT profile FROM (profile_db) INTO TABLE result. + SELECT profile + FROM (profile_db) + INTO TABLE @result. + IF sy-subrc = 0. RETURN. ENDIF. diff --git a/src/foundation/y_code_pal_pseudo_comments.dtel.xml b/src/foundation/y_code_pal_pseudo_comments.dtel.xml new file mode 100644 index 00000000..e815916c --- /dev/null +++ b/src/foundation/y_code_pal_pseudo_comments.dtel.xml @@ -0,0 +1,23 @@ + + + + + + Y_CODE_PAL_PSEUDO_COMMENTS + E + BOOLE + 55 + 10 + 20 + 40 + Ignore Pseudo Comments + Ignore Pseudo Comments + Ign Ps Com + IgnorePseudoComments + Ignore Pseudo Comments + E + D + + + + diff --git a/src/foundation/y_code_pal_service.clas.abap b/src/foundation/y_code_pal_service.clas.abap index caab0bae..0eebbcd4 100644 --- a/src/foundation/y_code_pal_service.clas.abap +++ b/src/foundation/y_code_pal_service.clas.abap @@ -195,8 +195,7 @@ CLASS y_code_pal_service IMPLEMENTATION. ENDTRY. TRY. - result_access->get_findings( IMPORTING e_findings = DATA(findings) - e_findings_extension = DATA(findings_extension) ). + result_access->get_findings( IMPORTING e_findings = DATA(findings) ). CATCH cx_satc_failure. raise_internal_server_error( ). response->set_cdata( 'Result access failed (no authorization, etc.)' ). diff --git a/src/foundation/y_exemption_general.clas.abap b/src/foundation/y_exemption_general.clas.abap index 0f737f35..d569f503 100644 --- a/src/foundation/y_exemption_general.clas.abap +++ b/src/foundation/y_exemption_general.clas.abap @@ -19,8 +19,13 @@ CLASS y_exemption_general IMPLEMENTATION. METHOD y_if_exemption~is_object_exempted. - result = xsdbool( ( is_object_existing( object_type = object_type object_name = object_name ) = abap_true ) OR - ( is_tadir_generated( object_type = object_type object_name = object_name ) = abap_true ) ). + DATA(object_exists) = is_object_existing( object_type = object_type + object_name = object_name ). + + DATA(tadir_generated) = is_tadir_generated( object_type = object_type + object_name = object_name ). + + result = xsdbool( object_exists = abap_true OR tadir_generated = abap_true ). ENDMETHOD. diff --git a/src/foundation/y_exemption_of_class.clas.abap b/src/foundation/y_exemption_of_class.clas.abap index 8765fd6a..ffdaaebd 100644 --- a/src/foundation/y_exemption_of_class.clas.abap +++ b/src/foundation/y_exemption_of_class.clas.abap @@ -10,14 +10,12 @@ CLASS y_exemption_of_class DEFINITION PUBLIC CREATE PUBLIC. CLASS-METHODS is_odata_generate RETURNING VALUE(result) TYPE abap_bool. CLASS-METHODS is_ecatt_odata_test_generate RETURNING VALUE(result) TYPE abap_bool. CLASS-METHODS is_fin_infotype_generate RETURNING VALUE(result) TYPE abap_bool. - CLASS-METHODS is_amdp_class RETURNING VALUE(result) TYPE abap_bool. CLASS-METHODS is_extensibility_generate RETURNING VALUE(result) TYPE abap_bool. CLASS-METHODS is_shma_generate RETURNING VALUE(result) TYPE abap_bool. CLASS-METHODS is_proxy_generate RETURNING VALUE(result) TYPE abap_bool. CLASS-METHODS is_sadl_generate RETURNING VALUE(result) TYPE abap_bool. CLASS-METHODS is_exit_class RETURNING VALUE(result) TYPE abap_bool. CLASS-METHODS is_exception_class RETURNING VALUE(result) TYPE abap_bool. - CLASS-METHODS is_xlca_generate RETURNING VALUE(result) TYPE abap_bool. CLASS-METHODS is_bcp_application RETURNING VALUE(result) TYPE abap_bool. ENDCLASS. @@ -51,34 +49,6 @@ CLASS y_exemption_of_class IMPLEMENTATION. ENDMETHOD. - METHOD is_amdp_class. - DATA: lt_interfaces TYPE seor_implementing_keys. - DATA: lv_seoclskey TYPE seoclskey. - - lv_seoclskey = class_header_data-clsname. - - CALL FUNCTION 'SEO_CLASS_ALL_IMPLEMENTG_GET' - EXPORTING - clskey = lv_seoclskey - IMPORTING - set = lt_interfaces - EXCEPTIONS - not_existing = 1 - is_interface = 2 - model_only = 3 - OTHERS = 4. - IF sy-subrc <> 0. - RETURN. - ENDIF. - - LOOP AT lt_interfaces TRANSPORTING NO FIELDS - WHERE refclsname = 'IF_AMDP_MARKER_HDB'. - result = abap_true. - RETURN. - ENDLOOP. - ENDMETHOD. - - METHOD is_bcp_application. DATA it_bsp_classes TYPE STANDARD TABLE OF seoclsname. @@ -94,7 +64,7 @@ CLASS y_exemption_of_class IMPLEMENTATION. SELECT SINGLE refclsname FROM seometarel WHERE clsname = @class_header_data-clsname AND refclsname IS NOT NULL INTO @DATA(inherited_by). - IF sy-subrc NE 0. + IF sy-subrc <> 0. RETURN. ENDIF. @@ -116,11 +86,11 @@ CLASS y_exemption_of_class IMPLEMENTATION. METHOD is_ecatt_odata_test_generate. - SELECT SINGLE s~clsname FROM seoclassdf AS s INTO @DATA(lv_odata_class) - WHERE clsname = @class_header_data-clsname AND s~author = 'eCATTClassGe'. - IF sy-subrc = 0. - result = abap_true. - ENDIF. + SELECT SINGLE @abap_true + FROM seoclassdf + INTO @result + WHERE clsname = @class_header_data-clsname + AND author = 'eCATTClassGe'. ENDMETHOD. @@ -169,32 +139,22 @@ CLASS y_exemption_of_class IMPLEMENTATION. METHOD is_fin_infotype_generate. - SELECT SINGLE idclass FROM t777ditclass INTO @DATA(lv_inftype_cl) WHERE idclass = @class_header_data-clsname. - IF sy-subrc = 0. - result = abap_true. - RETURN. - ENDIF. - - SELECT SINGLE cont_db FROM t777ditclass INTO @DATA(lv_inftype1_cl) WHERE cont_db = @class_header_data-clsname. - IF sy-subrc = 0. - result = abap_true. - RETURN. - ENDIF. - - SELECT SINGLE bl_class FROM t777ditclass INTO @DATA(lv_inftype2_cl) WHERE bl_class = @class_header_data-clsname. - IF sy-subrc = 0. - result = abap_true. - RETURN. - ENDIF. + SELECT SINGLE @abap_true + FROM t777ditclass + INTO @result + WHERE idclass = @class_header_data-clsname + OR cont_db = @class_header_data-clsname + OR bl_class = @class_header_data-clsname. ENDMETHOD. METHOD is_odata_generate. - SELECT SINGLE trobj_name FROM /iwbep/i_sbd_ga INTO @DATA(l_name) - WHERE ( gen_art_type = 'DPCB' OR gen_art_type = 'MPCB' ) AND trobj_type = 'CLAS' AND trobj_name = @class_header_data-clsname. "#EC CI_NOFIELD - IF sy-subrc = 0. - result = abap_true. - ENDIF. + SELECT SINGLE @abap_true + FROM /iwbep/i_sbd_ga + INTO @result + WHERE ( gen_art_type = 'DPCB' OR gen_art_type = 'MPCB' ) + AND trobj_type = 'CLAS' + AND trobj_name = @class_header_data-clsname. "#EC CI_NOFIELD ENDMETHOD. @@ -204,20 +164,21 @@ CLASS y_exemption_of_class IMPLEMENTATION. METHOD is_sadl_generate. - SELECT SINGLE langu FROM seoclasstx INTO @DATA(l_category) - WHERE clsname = @class_header_data-clsname AND descript = 'Generated by SADL Generation Toolkit' ##NO_TEXT. - IF sy-subrc = 0. - result = abap_true. - ENDIF. + SELECT SINGLE @abap_true + FROM seoclasstx + INTO @result + WHERE clsname = @class_header_data-clsname + AND descript = 'Generated by SADL Generation Toolkit' ##NO_TEXT. ENDMETHOD. METHOD is_shma_generate. - SELECT SINGLE obj_name FROM tadir INTO @DATA(shma_clas) - WHERE pgmid = 'R3TR' AND object = 'SHMA' AND obj_name = @class_header_data-clsname. - IF sy-subrc = 0. - result = abap_true. - ENDIF. + SELECT SINGLE @abap_true + FROM tadir + INTO @result + WHERE pgmid = 'R3TR' + AND object = 'SHMA' + AND obj_name = @class_header_data-clsname. ENDMETHOD. @@ -247,32 +208,4 @@ CLASS y_exemption_of_class IMPLEMENTATION. ENDMETHOD. - METHOD is_xlca_generate. - DATA: lt_interfaces TYPE seor_implementing_keys. - DATA: lv_seoclskey TYPE seoclskey. - - lv_seoclskey = class_header_data-clsname. - - CALL FUNCTION 'SEO_CLASS_ALL_IMPLEMENTG_GET' - EXPORTING - clskey = lv_seoclskey - IMPORTING - set = lt_interfaces - EXCEPTIONS - not_existing = 1 - is_interface = 2 - model_only = 3 - OTHERS = 4. - IF sy-subrc <> 0. - RETURN. - ENDIF. - - LOOP AT lt_interfaces TRANSPORTING NO FIELDS - WHERE refclsname = 'IF_CTS_TABLE_CONVERSION'. - result = abap_true. - RETURN. - ENDLOOP. - ENDMETHOD. - - ENDCLASS. diff --git a/src/foundation/y_exemption_of_function_group.clas.abap b/src/foundation/y_exemption_of_function_group.clas.abap index 43f274d6..d1b27004 100644 --- a/src/foundation/y_exemption_of_function_group.clas.abap +++ b/src/foundation/y_exemption_of_function_group.clas.abap @@ -35,21 +35,32 @@ CLASS y_exemption_of_function_group IMPLEMENTATION. IF name(1) = '/'. FIND FIRST OCCURRENCE OF '/' IN name+1 MATCH OFFSET DATA(l_offset). l_offset = l_offset + 2. - fugr_name = insert( val = name sub = 'SAPL' off = l_offset ). + fugr_name = insert( val = name + sub = 'SAPL' + off = l_offset ). ELSE. fugr_name = 'SAPL' && name. ENDIF. - SELECT SINGLE COUNT(*) FROM tfdir INTO fugr_func_viewframe - WHERE pname = fugr_name AND ( funcname LIKE 'VIEWFRAME%' OR funcname LIKE 'VIEWPROC%' OR funcname LIKE 'TABLEPROC%' OR funcname LIKE 'TABLEFRAME%' ). "#EC CI_BYPASS "#EC CI_GENBUFF + SELECT SINGLE COUNT(*) + FROM tfdir + INTO @fugr_func_viewframe + WHERE pname = @fugr_name + AND ( funcname LIKE 'VIEWFRAME%' + OR funcname LIKE 'VIEWPROC%' + OR funcname LIKE 'TABLEPROC%' + OR funcname LIKE 'TABLEFRAME%' ). "#EC CI_BYPASS "#EC CI_GENBUFF IF fugr_func_viewframe = 0 OR sy-subrc = 4. RETURN. ENDIF. - SELECT SINGLE COUNT(*) FROM tfdir INTO fugr_func - WHERE pname = fugr_name. "#EC CI_BYPASS. "#EC CI_GENBUFF - IF ( fugr_func = fugr_func_viewframe ). + SELECT SINGLE COUNT(*) + FROM tfdir + INTO @fugr_func + WHERE pname = @fugr_name. "#EC CI_BYPASS. "#EC CI_GENBUFF + + IF fugr_func = fugr_func_viewframe. result = abap_true. ENDIF. ENDMETHOD. @@ -60,24 +71,30 @@ CLASS y_exemption_of_function_group IMPLEMENTATION. FIND FIRST OCCURRENCE OF '/' IN name+1 MATCH OFFSET DATA(l_offset). l_offset = l_offset + 2. - DATA(fugr_name) = insert( val = name sub = 'SAPL' off = l_offset ). - - SELECT SINGLE funcname FROM tfdir INTO @DATA(rai_fugr_func) - WHERE pname = @fugr_name - AND NOT ( ( funcname LIKE '%_UPDATE' ) OR ( funcname LIKE '%_INSERT' ) OR ( funcname LIKE '%_RAI_CREATE_API' ) ). "#EC CI_GENBUFF. - - IF sy-subrc = 4. + DATA(fugr_name) = insert( val = name + sub = 'SAPL' + off = l_offset ). + + SELECT SINGLE funcname + FROM tfdir + INTO @DATA(rai_fugr_func) + WHERE pname = @fugr_name + AND NOT ( ( funcname LIKE '%_UPDATE' ) + OR ( funcname LIKE '%_INSERT' ) + OR ( funcname LIKE '%_RAI_CREATE_API' ) ). "#EC CI_GENBUFF. + + IF rai_fugr_func IS INITIAL. result = abap_true. ENDIF. ENDMETHOD. METHOD is_table_maintenance_generate. - SELECT SINGLE area AS object FROM tlibt INTO @DATA(l_area) - WHERE area = @name AND ( areat = 'Extended Table Maintenance (Generated)' ) ##NO_TEXT. "#EC CI_GENBUFF - IF sy-subrc = 0. - result = abap_true. - ENDIF. + SELECT SINGLE @abap_true + FROM tlibt + INTO @result + WHERE area = @name + AND areat = 'Extended Table Maintenance (Generated)' ##NO_TEXT. "#EC CI_GENBUFF ENDMETHOD. diff --git a/src/foundation/y_exemption_of_program.clas.abap b/src/foundation/y_exemption_of_program.clas.abap index 593b952b..8640570b 100644 --- a/src/foundation/y_exemption_of_program.clas.abap +++ b/src/foundation/y_exemption_of_program.clas.abap @@ -43,31 +43,22 @@ CLASS y_exemption_of_program IMPLEMENTATION. METHOD is_enterprise_search_generate. - SELECT * FROM trdir INTO TABLE @DATA(genprog) - WHERE name LIKE '%\_001' ESCAPE '\' - AND ( secu = 'ESH' OR name LIKE 'ESHS%' ) - AND ( subc = 'S' OR subc = '1' ) "include programs ('I') are not supported - AND name = @name. - IF sy-subrc EQ 0. - result = abap_true. - ENDIF. + SELECT SINGLE @abap_true + FROM trdir + INTO @result + WHERE name LIKE '%\_001' ESCAPE '\' + AND ( secu = 'ESH' OR name LIKE 'ESHS%' ) + AND ( subc = 'S' OR subc = '1' ) "include programs ('I') are not supported + AND name = @name. ENDMETHOD. METHOD is_fin_infotyp_generate. - SELECT SINGLE repid FROM t777d INTO @DATA(lv_inftype1_progs) - WHERE repid = @name. - IF sy-subrc = 0. - result = abap_true. - RETURN. - ENDIF. - - SELECT SINGLE btci_prog FROM t777d INTO @DATA(lv_inftype2_progs) - WHERE btci_prog = @name. - IF sy-subrc = 0. - result = abap_true. - RETURN. - ENDIF. + SELECT SINGLE @abap_true + FROM t777d + INTO @result + WHERE repid = @name + OR btci_prog = @name. ENDMETHOD. @@ -113,11 +104,10 @@ CLASS y_exemption_of_program IMPLEMENTATION. METHOD is_object_sw01_generate. - SELECT SINGLE progname FROM tojtb INTO @DATA(l_prog) - WHERE progname = @name. "#EC CI_GENBUFF - IF sy-subrc = 0. - result = abap_true. - ENDIF. + SELECT SINGLE @abap_true + FROM tojtb + INTO @result + WHERE progname = @name. "#EC CI_GENBUFF ENDMETHOD. diff --git a/src/foundation/y_if_clean_code_manager.intf.abap b/src/foundation/y_if_clean_code_manager.intf.abap index 845bba56..09ac7080 100644 --- a/src/foundation/y_if_clean_code_manager.intf.abap +++ b/src/foundation/y_if_clean_code_manager.intf.abap @@ -1,29 +1,30 @@ -interface Y_IF_CLEAN_CODE_MANAGER - public . +INTERFACE y_if_clean_code_manager + PUBLIC . - types: + TYPES: BEGIN OF check_configuration, object_creation_date TYPE datum, threshold TYPE ycicc_threshold, prio TYPE ycicc_message_kind, apply_on_productive_code TYPE ycicc_productive_code, apply_on_testcode TYPE ycicc_testcode, + ignore_pseudo_comments TYPE y_code_pal_pseudo_comments, END OF check_configuration . - types: + TYPES: check_configurations TYPE STANDARD TABLE OF check_configuration WITH DEFAULT KEY . - methods READ_CHECK_CUSTOMIZING - importing - CHECKID type SEOCLSNAME - returning - value(RESULT) type CHECK_CONFIGURATIONS - raising - YCX_NO_CHECK_CUSTOMIZING . - methods CALCULATE_OBJ_CREATION_DATE - importing - OBJECT_NAME type SOBJ_NAME - OBJECT_TYPE type TROBJTYPE - returning - value(RESULT) type CREATIONDT . -endinterface. + METHODS read_check_customizing + IMPORTING + checkid TYPE seoclsname + RETURNING + VALUE(result) TYPE check_configurations + RAISING + ycx_no_check_customizing . + METHODS calculate_obj_creation_date + IMPORTING + object_name TYPE sobj_name + object_type TYPE trobjtype + RETURNING + VALUE(result) TYPE creationdt . +ENDINTERFACE. diff --git a/src/foundation/y_object_creation_date.clas.abap b/src/foundation/y_object_creation_date.clas.abap index 88e4c128..754d9d88 100644 --- a/src/foundation/y_object_creation_date.clas.abap +++ b/src/foundation/y_object_creation_date.clas.abap @@ -86,7 +86,10 @@ CLASS y_object_creation_date IMPLEMENTATION. DELETE buffer FROM 1 TO max_entries / 2. ENDIF. - APPEND get_db_tadir_data( object_type = object_type object_name = object_name ) TO created_on_dates. + DATA(taidr) = get_db_tadir_data( object_type = object_type + object_name = object_name ). + + APPEND taidr TO created_on_dates. DATA(repo_access) = COND #( WHEN object_type = 'FUGR' THEN convert_fugr_for_db_access( object_name ) WHEN object_type = 'CLAS' THEN convert_class_for_repos_access( object_name ) @@ -178,7 +181,7 @@ CLASS y_object_creation_date IMPLEMENTATION. DATA(search_pattern) = convert_fugr_for_db_access( fugr_name ). SELECT funcname INTO TABLE @DATA(functions) FROM tfdir WHERE pname = @search_pattern. "#EC CI_GENBUFF - IF sy-subrc NE 0. + IF sy-subrc <> 0. RETURN. ENDIF. @@ -193,7 +196,7 @@ CLASS y_object_creation_date IMPLEMENTATION. objtype = 'FUNC' AND objname IN @function_search_table AND datum IS NOT NULL AND "only in HRI - datum NE '00000000' + datum <> '00000000' INTO @result. ENDMETHOD. diff --git a/src/foundation/y_pseudo_comment_detector.clas.abap b/src/foundation/y_pseudo_comment_detector.clas.abap index 31ad1b55..f65fbe8f 100644 --- a/src/foundation/y_pseudo_comment_detector.clas.abap +++ b/src/foundation/y_pseudo_comment_detector.clas.abap @@ -135,10 +135,12 @@ CLASS y_pseudo_comment_detector IMPLEMENTATION. RETURN. ENDIF. - result = has_comment( ref_scan_manager = ref_scan_manager position = position ). + result = has_comment( ref_scan_manager = ref_scan_manager + position = position ). IF result <> cl_ci_test_root=>c_pc_exceptn_exists. - result = has_inline_comment( ref_scan_manager = ref_scan_manager position = position ). + result = has_inline_comment( ref_scan_manager = ref_scan_manager + position = position ). ENDIF. ENDMETHOD. diff --git a/src/foundation/y_test_code_detector.clas.abap b/src/foundation/y_test_code_detector.clas.abap index ee11cc3f..cafc2ae2 100644 --- a/src/foundation/y_test_code_detector.clas.abap +++ b/src/foundation/y_test_code_detector.clas.abap @@ -18,7 +18,6 @@ CLASS y_test_code_detector DEFINITION PUBLIC CREATE PUBLIC. IMPORTING token TYPE stokesx RETURNING VALUE(result) TYPE abap_bool, try_testmethod - IMPORTING token TYPE stokesx RETURNING VALUE(result) TYPE abap_bool, keyword RETURNING VALUE(result) TYPE string, @@ -41,7 +40,7 @@ CLASS Y_TEST_CODE_DETECTOR IMPLEMENTATION. ENDIF. LOOP AT ref_scan_manager->structures ASSIGNING FIELD-SYMBOL() - WHERE stmnt_type EQ scan_struc_stmnt_type-class_definition. + WHERE stmnt_type = scan_struc_stmnt_type-class_definition. process_statements( ). ENDLOOP. @@ -61,10 +60,7 @@ CLASS Y_TEST_CODE_DETECTOR IMPLEMENTATION. METHOD is_test_class. IF keyword( ) = 'CLASS'. DATA(class) = get_token_rel( 2 ). "#EC DECL_IN_IF - READ TABLE test_codes TRANSPORTING NO FIELDS WITH KEY class = class. - IF sy-subrc EQ 0. - result = abap_true. - ENDIF. + result = xsdbool( line_exists( test_codes[ class = class ] ) ). ENDIF. ENDMETHOD. @@ -99,7 +95,7 @@ CLASS Y_TEST_CODE_DETECTOR IMPLEMENTATION. EXIT. ENDIF. - IF try_testmethod( ). + IF try_testmethod( ). EXIT. ENDIF. ENDLOOP. @@ -107,7 +103,7 @@ CLASS Y_TEST_CODE_DETECTOR IMPLEMENTATION. METHOD try_testclass. - IF token-str EQ 'TESTING' AND + IF token-str = 'TESTING' AND keyword( ) = 'CLASS'. test_code-class = get_token_rel( 2 ). result = abap_true. @@ -116,18 +112,16 @@ CLASS Y_TEST_CODE_DETECTOR IMPLEMENTATION. METHOD try_testmethod. - IF test_code-class IS NOT INITIAL AND ( - keyword( ) = 'METHODS' OR - keyword( ) = 'CLASS-METHODS' ). - + IF test_code-class IS NOT INITIAL + AND ( keyword( ) = 'METHODS' OR keyword( ) = 'CLASS-METHODS' ). test_code-method = get_token_rel( 2 ). APPEND test_code TO test_codes. result = abap_true. ENDIF. - IF test_code-class IS NOT INITIAL AND - test_code-method IS INITIAL AND - keyword( ) = 'ENDCLASS'. + IF test_code-class IS NOT INITIAL + AND test_code-method IS INITIAL + AND keyword( ) = 'ENDCLASS'. APPEND test_code TO test_codes. result = abap_true. ENDIF. @@ -158,7 +152,7 @@ CLASS Y_TEST_CODE_DETECTOR IMPLEMENTATION. DO. DATA(low_level_structure) = high_level_structure. "#EC DECL_IN_IF READ TABLE ref_scan_manager->structures INTO high_level_structure INDEX low_level_structure-back. - IF sy-subrc NE 0. + IF sy-subrc <> 0. EXIT. ENDIF. @@ -167,7 +161,7 @@ CLASS Y_TEST_CODE_DETECTOR IMPLEMENTATION. result = abap_true. EXIT. ENDIF. - IF low_level_structure-back EQ 0. + IF low_level_structure-back = 0. EXIT. ENDIF. ENDDO. diff --git a/src/foundation/y_test_code_detector.clas.testclasses.abap b/src/foundation/y_test_code_detector.clas.testclasses.abap index 5a3f47e5..06776146 100644 --- a/src/foundation/y_test_code_detector.clas.testclasses.abap +++ b/src/foundation/y_test_code_detector.clas.testclasses.abap @@ -76,7 +76,7 @@ CLASS ltc_test_code_detector IMPLEMENTATION. ref_scan_manager_double->set_data_without_test( ). LOOP AT ref_scan_manager_double->y_if_scan_manager~structures ASSIGNING FIELD-SYMBOL() - FROM 2 WHERE stmnt_type EQ scan_struc_stmnt_type-class_definition. + FROM 2 WHERE stmnt_type = scan_struc_stmnt_type-class_definition. cl_abap_unit_assert=>assert_equals( act = cut->y_if_testcode_detector~is_testcode( ) @@ -89,7 +89,7 @@ CLASS ltc_test_code_detector IMPLEMENTATION. ref_scan_manager_double->set_data_with_test( ). LOOP AT ref_scan_manager_double->y_if_scan_manager~structures ASSIGNING FIELD-SYMBOL() - FROM 2 WHERE stmnt_type EQ scan_struc_stmnt_type-class_definition. + FROM 2 WHERE stmnt_type = scan_struc_stmnt_type-class_definition. cl_abap_unit_assert=>assert_equals( act = cut->y_if_testcode_detector~is_testcode( ) @@ -102,7 +102,7 @@ CLASS ltc_test_code_detector IMPLEMENTATION. ref_scan_manager_double->set_data_without_test( ). LOOP AT ref_scan_manager_double->y_if_scan_manager~structures ASSIGNING FIELD-SYMBOL() - FROM 2 WHERE stmnt_type EQ scan_struc_stmnt_type-method. + FROM 2 WHERE stmnt_type = scan_struc_stmnt_type-method. cl_abap_unit_assert=>assert_equals( act = cut->y_if_testcode_detector~is_testcode( ) @@ -115,7 +115,7 @@ CLASS ltc_test_code_detector IMPLEMENTATION. ref_scan_manager_double->set_data_with_test( ). LOOP AT ref_scan_manager_double->y_if_scan_manager~structures ASSIGNING FIELD-SYMBOL() - FROM 2 WHERE stmnt_type EQ scan_struc_stmnt_type-method. + FROM 2 WHERE stmnt_type = scan_struc_stmnt_type-method. cl_abap_unit_assert=>assert_equals( act = cut->y_if_testcode_detector~is_testcode( ) @@ -128,7 +128,7 @@ CLASS ltc_test_code_detector IMPLEMENTATION. ref_scan_manager_double->set_data_with_test( ). LOOP AT ref_scan_manager_double->y_if_scan_manager~structures ASSIGNING FIELD-SYMBOL() - FROM 2 WHERE stmnt_type EQ scan_struc_stmnt_type-class_definition. + FROM 2 WHERE stmnt_type = scan_struc_stmnt_type-class_definition. cl_abap_unit_assert=>assert_equals( act = cut->y_if_testcode_detector~is_testcode( ) @@ -141,7 +141,7 @@ CLASS ltc_test_code_detector IMPLEMENTATION. ref_scan_manager_double->set_data_without_test( ). LOOP AT ref_scan_manager_double->y_if_scan_manager~structures ASSIGNING FIELD-SYMBOL() - FROM 2 WHERE stmnt_type EQ scan_struc_stmnt_type-class_definition. + FROM 2 WHERE stmnt_type = scan_struc_stmnt_type-class_definition. cl_abap_unit_assert=>assert_equals( act = cut->y_if_testcode_detector~is_testcode( ) @@ -154,7 +154,7 @@ CLASS ltc_test_code_detector IMPLEMENTATION. ref_scan_manager_double->set_data_with_test( ). LOOP AT ref_scan_manager_double->y_if_scan_manager~structures ASSIGNING FIELD-SYMBOL() - FROM 2 WHERE stmnt_type EQ scan_struc_stmnt_type-class_definition. + FROM 2 WHERE stmnt_type = scan_struc_stmnt_type-class_definition. cl_abap_unit_assert=>assert_equals( act = cut->y_if_testcode_detector~is_testcode( ) diff --git a/src/profiles/y_alv_events.clas.abap b/src/profiles/y_alv_events.clas.abap index c97f3eef..35651613 100644 --- a/src/profiles/y_alv_events.clas.abap +++ b/src/profiles/y_alv_events.clas.abap @@ -15,10 +15,10 @@ CLASS y_alv_events IMPLEMENTATION. METHOD y_if_alv_events~get_events. - IF mode EQ y_if_alv_events~mode_double_click. + IF mode = y_if_alv_events~mode_double_click. result = VALUE y_if_alv_events=>simple_events( ( eventid = cl_gui_column_tree=>eventid_node_double_click appl_event = abap_true ) ). - ELSEIF mode EQ y_if_alv_events~mode_selection_changed. + ELSEIF mode = y_if_alv_events~mode_selection_changed. result = VALUE y_if_alv_events=>simple_events( ( eventid = cl_gui_column_tree=>eventid_selection_changed appl_event = abap_true ) ). ENDIF. diff --git a/src/profiles/y_alv_tree_control.clas.abap b/src/profiles/y_alv_tree_control.clas.abap index c8872987..727162be 100644 --- a/src/profiles/y_alv_tree_control.clas.abap +++ b/src/profiles/y_alv_tree_control.clas.abap @@ -25,7 +25,6 @@ CLASS y_alv_tree_control DEFINITION PUBLIC CREATE PUBLIC. IMPORTING type_name TYPE string sort_table TYPE lvc_t_sort - events TYPE REF TO y_if_alv_events alv_tree TYPE REF TO cl_gui_alv_tree_simple alv_header TYPE slis_t_listheader RAISING @@ -55,7 +54,7 @@ CLASS Y_ALV_TREE_CONTROL IMPLEMENTATION. METHOD autosize_all_fields. DATA filler TYPE i VALUE 7. LOOP AT fieldcats ASSIGNING FIELD-SYMBOL(). - IF -dd_outlen GE strlen( -coltext ). + IF -dd_outlen >= strlen( -coltext ). -outputlen = -dd_outlen + filler. ELSE. -outputlen = strlen( -coltext ) + filler. @@ -95,7 +94,6 @@ CLASS Y_ALV_TREE_CONTROL IMPLEMENTATION. result = NEW y_alv_tree_control( type_name = type_name sort_table = sort_table - events = events alv_tree = alv_tree alv_header = alv_header ). ENDMETHOD. @@ -130,7 +128,7 @@ CLASS Y_ALV_TREE_CONTROL IMPLEMENTATION. METHOD y_if_alv_tree_control~get_selected_index. DATA index_table TYPE lvc_t_indx. CHECK y_if_alv_tree_control~list_control( )->get_line_at( 1 ) IS NOT INITIAL. - IF sy-subrc EQ 0. + IF sy-subrc = 0. alv_tree->get_selected_nodes( CHANGING ct_index_outtab = index_table ). TRY. result = index_table[ 1 ]. @@ -142,9 +140,12 @@ CLASS Y_ALV_TREE_CONTROL IMPLEMENTATION. METHOD y_if_alv_tree_control~set_selected_index. - CHECK y_if_alv_tree_control~list_control( )->get_line_at( 1 ) IS NOT INITIAL. DATA index_table TYPE lvc_t_indx. + + CHECK y_if_alv_tree_control~list_control( )->get_line_at( 1 ) IS NOT INITIAL. + APPEND index TO index_table. + alv_tree->set_selected_nodes( EXPORTING it_index_outtab = index_table @@ -196,7 +197,7 @@ CLASS Y_ALV_TREE_CONTROL IMPLEMENTATION. METHOD y_if_alv_tree_control~set_field_header_text. - LOOP AT fieldcats ASSIGNING FIELD-SYMBOL() WHERE fieldname EQ to_upper( fieldname ). + LOOP AT fieldcats ASSIGNING FIELD-SYMBOL() WHERE fieldname = to_upper( fieldname ). -coltext = header_text. ENDLOOP. UNASSIGN . @@ -204,8 +205,8 @@ CLASS Y_ALV_TREE_CONTROL IMPLEMENTATION. METHOD y_if_alv_tree_control~set_field_visibility. - LOOP AT fieldcats ASSIGNING FIELD-SYMBOL() WHERE fieldname EQ to_upper( fieldname ). - -no_out = xsdbool( is_visible EQ abap_false ). + LOOP AT fieldcats ASSIGNING FIELD-SYMBOL() WHERE fieldname = to_upper( fieldname ). + -no_out = xsdbool( is_visible = abap_false ). ENDLOOP. UNASSIGN . ENDMETHOD. @@ -213,7 +214,7 @@ CLASS Y_ALV_TREE_CONTROL IMPLEMENTATION. METHOD y_if_alv_tree_control~toolbar_control. alv_tree->get_toolbar_object( IMPORTING er_toolbar = result EXCEPTIONS OTHERS = 4 ). - IF sy-subrc NE 0. + IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_failed. ENDIF. ENDMETHOD. @@ -229,7 +230,7 @@ CLASS Y_ALV_TREE_CONTROL IMPLEMENTATION. y_if_alv_tree_control~toolbar_control( )->set_button_state( EXPORTING enabled = abap_true fcode =