├── src ├── zif_i_a2cc_aggregator.intf.abap ├── zcx_i_a2cc_metrics_impl_error.clas.abap ├── package.devc.xml ├── zif_i_a2cc_metrics_2_json.intf.abap ├── zif_i_a2cc_dependency_analyzer.intf.abap ├── zif_i_a2cc_where_used_provider.intf.abap ├── zif_i_a2cc_package_analyzer.intf.abap ├── zif_i_a2cc_where_used.intf.xml ├── zif_i_a2cc_aggregator.intf.xml ├── zif_i_a2cc_metrics_2_json.intf.xml ├── zif_i_a2cc_package_analyzer.intf.xml ├── zcl_i_a2cc_factory.clas.xml ├── zif_i_a2cc_dependency_analyzer.intf.xml ├── zif_i_a2cc_where_used_provider.intf.xml ├── zcl_i_a2cc_metrics_2_json.clas.xml ├── zcl_i_a2cc_metrics_runner.clas.xml ├── zcl_i_a2cc_aggregator_class.clas.xml ├── zcl_i_a2cc_metrics_file_writer.clas.xml ├── zcl_i_a2cc_package_analyzer.clas.xml ├── zcl_i_a2cc_where_used_clas.clas.xml ├── zcl_i_a2cc_where_used_func.clas.xml ├── zcl_i_a2cc_aggregator_package.clas.xml ├── zcl_i_a2cc_dpndncy_anlyzr_clas.clas.xml ├── zcl_i_a2cc_dpndncy_anlyzr_devc.clas.xml ├── zcl_i_a2cc_where_used_abstract.clas.xml ├── zcx_i_a2cc_metrics_impl_error.clas.xml ├── zcl_i_a2cc_where_used_provider.clas.xml ├── ztti_a2cc_packages.ttyp.xml ├── ztti_a2cc_code_metrics.ttyp.xml ├── zcl_i_a2cc_where_used_clas.clas.abap ├── zcl_i_a2cc_where_used_func.clas.abap ├── zei_a2cc_object_id.dtel.xml ├── zsi_a2cc_packages.tabl.xml ├── zif_i_a2cc_where_used.intf.abap ├── zcl_i_a2cc_metrics_runner.clas.abap ├── zcl_i_a2cc_metrics_file_writer.clas.abap ├── zcl_i_a2cc_factory.clas.abap ├── zi_abap_to_codecharta.prog.xml ├── zcl_i_a2cc_where_used_provider.clas.testclasses.abap ├── zcl_i_a2cc_package_analyzer.clas.abap ├── zcl_i_a2cc_where_used_provider.clas.abap ├── zcl_i_a2cc_dpndncy_anlyzr_devc.clas.abap ├── zcl_i_a2cc_dpndncy_anlyzr_clas.clas.abap ├── zcl_i_a2cc_aggregator_package.clas.abap ├── zcl_i_a2cc_aggregator_class.clas.abap ├── zcl_i_a2cc_where_used_abstract.clas.abap ├── zi_abap_to_codecharta.prog.abap ├── zsi_a2cc_code_metrics.tabl.xml └── zcl_i_a2cc_metrics_2_json.clas.abap ├── README.md ├── .abapgit.xml └── LICENSE /src/zif_i_a2cc_aggregator.intf.abap: -------------------------------------------------------------------------------- 1 | INTERFACE zif_i_a2cc_aggregator 2 | PUBLIC . 3 | METHODS aggregate_metrics 4 | IMPORTING 5 | metrics TYPE ztti_a2cc_code_metrics 6 | RETURNING 7 | VALUE(result) TYPE ztti_a2cc_code_metrics. 8 | ENDINTERFACE. 9 | -------------------------------------------------------------------------------- /src/zcx_i_a2cc_metrics_impl_error.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcx_i_a2cc_metrics_impl_error DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC INHERITING FROM cx_static_check. 5 | 6 | PUBLIC SECTION. 7 | PROTECTED SECTION. 8 | PRIVATE SECTION. 9 | ENDCLASS. 10 | 11 | 12 | 13 | CLASS zcx_i_a2cc_metrics_impl_error IMPLEMENTATION. 14 | ENDCLASS. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ABAP-2-CODE-CHARTA 2 | Covert ABAP Metrics to Code Charta 3 | 4 | Visualize your ABAP Code with Code Charta (https://github.com/MaibornWolff/codecharta). 5 | 6 | This code creates a json file that can be imported into Code Charta 7 | 8 | More information: 9 | https://blogs.sap.com/2021/06/25/code-cities-visualizing-abap-code-metrics-with-abap2codecharta/ 10 | -------------------------------------------------------------------------------- /src/package.devc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Visualize ABAP in Code Charta 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/zif_i_a2cc_metrics_2_json.intf.abap: -------------------------------------------------------------------------------- 1 | INTERFACE zif_i_a2cc_metrics_2_json 2 | PUBLIC . 3 | METHODS 4 | to_json 5 | IMPORTING 6 | VALUE(metrics) TYPE ztti_a2cc_code_metrics 7 | analyze_dependecies TYPE abap_bool 8 | analyze_direct_cycles TYPE abap_bool 9 | RETURNING 10 | VALUE(result) TYPE string. 11 | 12 | endinterface. 13 | -------------------------------------------------------------------------------- /src/zif_i_a2cc_dependency_analyzer.intf.abap: -------------------------------------------------------------------------------- 1 | INTERFACE zif_i_a2cc_dependency_analyzer 2 | PUBLIC . 3 | METHODS find_object_usages 4 | IMPORTING 5 | metrics TYPE ztti_a2cc_code_metrics 6 | analyze_dependecies TYPE abap_bool 7 | analyze_direct_cycles TYPE abap_bool 8 | RETURNING 9 | VALUE(result) TYPE zif_i_a2cc_where_used=>where_used_list. 10 | ENDINTERFACE. 11 | -------------------------------------------------------------------------------- /src/zif_i_a2cc_where_used_provider.intf.abap: -------------------------------------------------------------------------------- 1 | interface ZIF_I_A2CC_WHERE_USED_PROVIDER 2 | public . 3 | TYPES objecttype TYPE c LENGTH 4. 4 | TYPES subtype TYPE c LENGTH 4. 5 | METHODS get IMPORTING objecttype TYPE zif_i_a2cc_where_used_provider=>objecttype subtype TYPE zif_i_a2cc_where_used_provider=>subtype RETURNING VALUE(result) TYPE REF TO zif_i_A2CC_where_used 6 | RAISING zcx_i_A2CC_metrics_impl_error. 7 | 8 | endinterface. 9 | -------------------------------------------------------------------------------- /src/zif_i_a2cc_package_analyzer.intf.abap: -------------------------------------------------------------------------------- 1 | interface ZIF_I_A2CC_PACKAGE_ANALYZER 2 | public . 3 | 4 | METHODS aggregate_packages 5 | IMPORTING 6 | aggregated_metrics type ztti_a2cc_code_metrics 7 | RETURNING 8 | VALUE(result) type ztti_a2cc_packages. 9 | 10 | METHODS get_parent_packages 11 | IMPORTING 12 | package TYPE zsi_a2cc_code_metrics-package 13 | RETURNING 14 | VALUE(result) TYPE string. 15 | endinterface. 16 | -------------------------------------------------------------------------------- /src/zif_i_a2cc_where_used.intf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZIF_I_A2CC_WHERE_USED 7 | E 8 | Get Where Used 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/zif_i_a2cc_aggregator.intf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZIF_I_A2CC_AGGREGATOR 7 | E 8 | Metrics agggregator 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/zif_i_a2cc_metrics_2_json.intf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZIF_I_A2CC_METRICS_2_JSON 7 | E 8 | Metrics to json 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/zif_i_a2cc_package_analyzer.intf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZIF_I_A2CC_PACKAGE_ANALYZER 7 | E 8 | Package_analyzer 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_factory.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_FACTORY 7 | E 8 | Component factory 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zif_i_a2cc_dependency_analyzer.intf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZIF_I_A2CC_DEPENDENCY_ANALYZER 7 | E 8 | Dependency analyzer 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/zif_i_a2cc_where_used_provider.intf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZIF_I_A2CC_WHERE_USED_PROVIDER 7 | E 8 | Where used provider 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_metrics_2_json.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_METRICS_2_JSON 7 | D 8 | Metrics to JSON 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_metrics_runner.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_METRICS_RUNNER 7 | E 8 | Metrics runner 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_aggregator_class.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_AGGREGATOR_CLASS 7 | E 8 | Metrics aggregator 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_metrics_file_writer.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_METRICS_FILE_WRITER 7 | E 8 | File Writer 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_package_analyzer.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_PACKAGE_ANALYZER 7 | E 8 | Package analyzer 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_where_used_clas.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_WHERE_USED_CLAS 7 | E 8 | Where used of Methods 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_where_used_func.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_WHERE_USED_FUNC 7 | E 8 | Where used of Methods 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_aggregator_package.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_AGGREGATOR_PACKAGE 7 | E 8 | Metrics aggregator 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_dpndncy_anlyzr_clas.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_DPNDNCY_ANLYZR_CLAS 7 | E 8 | Dependency analyzer 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_dpndncy_anlyzr_devc.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_DPNDNCY_ANLYZR_DEVC 7 | E 8 | Dependency analyzer 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_where_used_abstract.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_WHERE_USED_ABSTRACT 7 | D 8 | Where used of Methods 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zcx_i_a2cc_metrics_impl_error.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCX_I_A2CC_METRICS_IMPL_ERROR 7 | E 8 | Implementation error 9 | 40 10 | 1 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_where_used_provider.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_I_A2CC_WHERE_USED_PROVIDER 7 | E 8 | Usage Provider 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/ztti_a2cc_packages.ttyp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZTTI_A2CC_PACKAGES 7 | D 8 | ZSI_A2CC_PACKAGES 9 | S 10 | STRU 11 | T 12 | D 13 | N 14 | Devclass Packages 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/ztti_a2cc_code_metrics.ttyp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZTTI_A2CC_CODE_METRICS 7 | D 8 | ZSI_A2CC_CODE_METRICS 9 | S 10 | STRU 11 | T 12 | D 13 | N 14 | Code Metrics 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.abapgit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | D 6 | /src/ 7 | FULL 8 | 9 | /.gitignore 10 | /LICENSE 11 | /README.md 12 | /package.json 13 | /.travis.yml 14 | /.gitlab-ci.yml 15 | /abaplint.json 16 | /azure-pipelines.yml 17 | /.devcontainer.json 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_where_used_clas.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_i_a2cc_where_used_clas DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC INHERITING FROM zcl_i_a2cc_where_used_abstract. 5 | 6 | PUBLIC SECTION. 7 | METHODS constructor 8 | IMPORTING objecttype TYPE zif_i_a2cc_where_used_provider=>objecttype. 9 | METHODS zif_i_a2cc_where_used~get_cross_references REDEFINITION. 10 | ENDCLASS. 11 | 12 | CLASS zcl_i_a2cc_where_used_clas IMPLEMENTATION. 13 | METHOD zif_i_a2cc_where_used~get_cross_references. 14 | result = get_where_used_list_from_cross( CONV #( object-object ) ) . 15 | ENDMETHOD. 16 | 17 | METHOD constructor. 18 | super->constructor( objecttype ). 19 | ENDMETHOD. 20 | ENDCLASS. 21 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_where_used_func.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_i_a2cc_where_used_func DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC INHERITING FROM zcl_i_a2cc_where_used_abstract. 5 | 6 | PUBLIC SECTION. 7 | METHODS constructor 8 | IMPORTING objecttype TYPE zif_i_a2cc_where_used_provider=>objecttype. 9 | METHODS zif_i_a2cc_where_used~get_cross_references REDEFINITION. 10 | ENDCLASS. 11 | 12 | CLASS zcl_i_a2cc_where_used_func IMPLEMENTATION. 13 | METHOD zif_i_a2cc_where_used~get_cross_references. 14 | result = get_where_used_list_from_cross( CONV #( object-subobject ) ) . 15 | ENDMETHOD. 16 | 17 | METHOD constructor. 18 | super->constructor( objecttype ). 19 | ENDMETHOD. 20 | ENDCLASS. 21 | -------------------------------------------------------------------------------- /src/zei_a2cc_object_id.dtel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZEI_A2CC_OBJECT_ID 7 | D 8 | CHAR61 9 | 16 10 | 08 11 | 08 12 | 16 13 | Zeichenfeld Länge 61 14 | Zeichenfeld 15 | Zeich61 16 | Zeich61 17 | Zeichenfeld 18 | E 19 | D 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/zsi_a2cc_packages.tabl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZSI_A2CC_PACKAGES 7 | INTTAB 8 | E 9 | 1 10 | 11 | 12 | 13 | ZSI_A2CC_PACKAGES 14 | PACKAGE 15 | 0001 16 | DEVCLASS 17 | 0 18 | D 19 | E 20 | 21 | 22 | ZSI_A2CC_PACKAGES 23 | PARENT 24 | 0002 25 | DEVCLASS 26 | 0 27 | D 28 | E 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 BenjaminWeisheit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/zif_i_a2cc_where_used.intf.abap: -------------------------------------------------------------------------------- 1 | INTERFACE zif_i_a2cc_where_used 2 | PUBLIC . 3 | TYPES object_identifier TYPE string. 4 | 5 | TYPES: BEGIN OF depending_object, 6 | depending_object TYPE object_identifier, 7 | depending_type TYPE trobjtype, 8 | number_of_usages TYPE i, 9 | cycle TYPE i, 10 | END OF depending_object. 11 | 12 | TYPES object_list TYPE HASHED TABLE OF depending_object WITH UNIQUE KEY depending_object depending_type. 13 | TYPES: BEGIN OF object_usages, 14 | object_identifier TYPE object_identifier, 15 | object_type TYPE trobjtype, 16 | references TYPE object_list, 17 | END OF object_usages. 18 | 19 | TYPES: BEGIN OF object_id, 20 | object TYPE zei_a2cc_object_id, 21 | subobject TYPE zei_a2cc_object_id, 22 | END OF object_id. 23 | 24 | TYPES where_used_list TYPE HASHED TABLE OF object_usages WITH UNIQUE KEY object_identifier object_type. 25 | 26 | METHODS get_cross_references 27 | IMPORTING 28 | object TYPE object_id 29 | RETURNING 30 | VALUE(result) TYPE REF TO object_list. 31 | ENDINTERFACE. 32 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_metrics_runner.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_i_a2cc_metrics_runner DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | PUBLIC SECTION. 6 | METHODS run_quality_metrics_report 7 | IMPORTING 8 | selection_variant TYPE variant 9 | RETURNING 10 | VALUE(result) TYPE ztti_a2cc_code_metrics 11 | RAISING 12 | cx_salv_bs_sc_runtime_info. 13 | PRIVATE SECTION. 14 | METHODS set_alv_runtime_info. 15 | METHODS submit_code_metrics_report 16 | IMPORTING 17 | selection_variant TYPE variant. 18 | METHODS get_alv_list_from_report 19 | RETURNING 20 | VALUE(result) TYPE ztti_a2cc_code_metrics 21 | RAISING 22 | cx_salv_bs_sc_runtime_info. 23 | ENDCLASS. 24 | 25 | CLASS zcl_i_a2cc_metrics_runner IMPLEMENTATION. 26 | METHOD run_quality_metrics_report. 27 | set_alv_runtime_info( ). 28 | submit_code_metrics_report( selection_variant ). 29 | result = get_alv_list_from_report( ). 30 | ENDMETHOD. 31 | 32 | METHOD get_alv_list_from_report. 33 | FIELD-SYMBOLS TYPE STANDARD TABLE. 34 | DATA alv_list TYPE REF TO data. 35 | cl_salv_bs_runtime_info=>get_data_ref( IMPORTING r_data = alv_list ). 36 | ASSIGN alv_list->* TO . 37 | MOVE-CORRESPONDING TO result. 38 | ENDMETHOD. 39 | 40 | METHOD submit_code_metrics_report. 41 | SUBMIT /sdf/cd_custom_code_metric 42 | USING SELECTION-SET selection_variant 43 | EXPORTING LIST TO MEMORY 44 | AND RETURN. 45 | ENDMETHOD. 46 | 47 | METHOD set_alv_runtime_info. 48 | cl_salv_bs_runtime_info=>set( 49 | EXPORTING display = abap_false 50 | metadata = abap_false 51 | data = abap_true ). 52 | ENDMETHOD. 53 | ENDCLASS. 54 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_metrics_file_writer.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_i_a2cc_metrics_file_writer DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. 7 | METHODS write_json_2_file 8 | IMPORTING 9 | file_name TYPE localfile 10 | json TYPE string. 11 | PRIVATE SECTION. 12 | CONSTANTS utf_8 TYPE string VALUE `UTF-8`. 13 | METHODS convert_string_to_xstring 14 | IMPORTING 15 | string TYPE string 16 | RETURNING 17 | VALUE(result) TYPE xstring. 18 | METHODS write_xstring_to_file 19 | IMPORTING 20 | file_name TYPE localfile 21 | xstring TYPE xstring. 22 | METHODS rplce_placeholders_in_filename 23 | IMPORTING 24 | file_name TYPE localfile 25 | RETURNING 26 | VALUE(result) TYPE localfile. 27 | ENDCLASS. 28 | 29 | CLASS zcl_i_a2cc_metrics_file_writer IMPLEMENTATION. 30 | METHOD write_json_2_file. 31 | write_xstring_to_file( 32 | file_name = rplce_placeholders_in_filename( file_name ) 33 | xstring = convert_string_to_xstring( json ) ). 34 | ENDMETHOD. 35 | 36 | METHOD write_xstring_to_file. 37 | OPEN DATASET file_name FOR OUTPUT IN BINARY MODE. 38 | IF sy-subrc NE 0. 39 | WRITE : |Error opening the server filepath: { file_name }|. 40 | ELSE. 41 | TRANSFER xstring TO file_name. 42 | CLOSE DATASET file_name. 43 | WRITE : |File downloaded to the server at: { file_name }|. 44 | ENDIF. 45 | ENDMETHOD. 46 | 47 | METHOD convert_string_to_xstring. 48 | result = cl_abap_codepage=>convert_to( source = string codepage = utf_8 ). 49 | ENDMETHOD. 50 | 51 | METHOD rplce_placeholders_in_filename. 52 | result = file_name. 53 | REPLACE ALL OCCURRENCES OF '' IN result WITH sy-datum. 54 | ENDMETHOD. 55 | ENDCLASS. 56 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_factory.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_i_a2cc_factory DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. 7 | CONSTANTS: BEGIN OF aggregation_levels, 8 | package TYPE char1 VALUE 'P', 9 | class TYPE char1 VALUE 'C', 10 | END OF aggregation_levels. 11 | CLASS-METHODS create 12 | IMPORTING 13 | aggregation_level TYPE char1 14 | RETURNING 15 | VALUE(result) TYPE REF TO Zif_I_A2CC_METRICS_2_JSON. 16 | PRIVATE SECTION. 17 | class-METHODS create_json_writer 18 | RETURNING 19 | VALUE(result) TYPE REF TO if_sxml_writer. 20 | 21 | ENDCLASS. 22 | 23 | CLASS zcl_i_a2cc_factory IMPLEMENTATION. 24 | METHOD create. 25 | DATA: dependency_analyzer TYPE REF TO zif_i_a2cc_dependency_analyzer, 26 | metric_aggregator TYPE REF TO zif_i_a2cc_aggregator. 27 | 28 | dependency_analyzer = COND #( WHEN aggregation_level = aggregation_levels-package 29 | THEN NEW zcl_i_a2cc_dpndncy_anlyzr_devc( ) 30 | ELSE NEW zcl_i_a2cc_dpndncy_anlyzr_Clas( ) ). 31 | 32 | metric_aggregator = COND #( WHEN aggregation_level = aggregation_levels-package 33 | THEN NEW zcl_i_a2cc_aggregator_package( ) 34 | ELSE NEW zcl_i_a2cc_aggregator_class( ) ). 35 | 36 | result = NEW zcl_i_a2cc_metrics_2_json( 37 | json_writer = create_json_writer( ) 38 | dependency_analyzer = dependency_analyzer 39 | package_analyzer = NEW zcl_i_a2cc_package_analyzer( ) 40 | metric_aggregator = metric_aggregator ). 41 | ENDMETHOD. 42 | 43 | METHOD create_json_writer. 44 | result = CAST #( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ) ). 45 | ENDMETHOD. 46 | ENDCLASS. 47 | -------------------------------------------------------------------------------- /src/zi_abap_to_codecharta.prog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZI_ABAP_TO_CODECHARTA 7 | S 8 | 1 9 | E 10 | X 11 | D$S 12 | X 13 | 14 | 15 | 16 | I 17 | BLA 18 | Abhängigkeiten 19 | 22 20 | 21 | 22 | I 23 | BLD 24 | Aggregationsebene 25 | 27 26 | 27 | 28 | S 29 | AGG_DEVC 30 | Paket 31 | 38 32 | 33 | 34 | S 35 | AGG_MODL 36 | Modul 37 | 38 38 | 39 | 40 | S 41 | CYCLS 42 | Nur direkte Zyklen 43 | 38 44 | 45 | 46 | S 47 | DPNDNCY 48 | Alle 49 | 38 50 | 51 | 52 | S 53 | WO_DPND 54 | Ohne 55 | 38 56 | 57 | 58 | S 59 | FILE 60 | . 61 | 22 62 | D 63 | 64 | 65 | S 66 | VARNT 67 | . 68 | 16 69 | D 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_where_used_provider.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | *"* use this source file for your ABAP unit test classes 2 | CLASS ltcl_test_provider DEFINITION DEFERRED. 3 | CLASS zcl_i_a2cc_where_used_provider DEFINITION LOCAL FRIENDS ltcl_test_provider. 4 | 5 | CLASS ltcl_test_provider DEFINITION FINAL FOR TESTING 6 | DURATION SHORT 7 | RISK LEVEL HARMLESS. 8 | 9 | PRIVATE SECTION. 10 | DATA cut TYPE REF TO zif_i_A2CC_where_used_provider. 11 | METHODS: 12 | setup, 13 | fail_with_xxxx FOR TESTING RAISING cx_static_check, 14 | succeed_with_meth FOR TESTING RAISING cx_static_check. 15 | ENDCLASS. 16 | 17 | CLASS lth_dummy_where_used DEFINITION FOR TESTING. 18 | PUBLIC SECTION. 19 | INTERFACES zif_i_A2CC_where_used. 20 | ENDCLASS. 21 | 22 | CLASS lth_dummy_where_used IMPLEMENTATION. 23 | 24 | METHOD zif_i_A2CC_where_used~get_cross_references. 25 | 26 | ENDMETHOD. 27 | 28 | ENDCLASS. 29 | 30 | 31 | CLASS ltcl_test_provider IMPLEMENTATION. 32 | METHOD setup. 33 | cut = NEW zcl_i_a2cc_where_used_provider( ). 34 | cast zcl_i_a2cc_where_used_provider( cut )->set_configuration( VALUE #( ( objecttype = 'CLAS' subtype = 'METH' instance = NEW lth_dummy_where_used( ) ) ) 35 | ). 36 | 37 | ENDMETHOD. 38 | 39 | METHOD succeed_with_meth. 40 | TRY. 41 | "given configuration with METH 42 | "when called with subtype Meth 43 | cut->get( objecttype = 'CLAS' subtype = 'METH' ). 44 | "then expext implementation 45 | CATCH zcx_i_A2CC_metrics_impl_error. 46 | cl_abap_unit_assert=>fail( 'Expect implementation' ). 47 | 48 | ENDTRY. 49 | 50 | ENDMETHOD. 51 | 52 | METHOD fail_with_xxxx. 53 | CONSTANTS any_non_existant_value TYPE zif_i_A2CC_where_used_provider=>subtype VALUE 'XXXX' ##NO_TEXT. 54 | TRY. 55 | "given instance and 56 | "when called with nonsense subtype 57 | cut->get( objecttype = 'CLAS' subtype = any_non_existant_value ). 58 | "then expext exception 59 | cl_abap_unit_assert=>fail( 'Expect exception zcx_i_metric_implement_error' ). 60 | CATCH zcx_i_A2CC_metrics_impl_error. 61 | ENDTRY. 62 | ENDMETHOD. 63 | 64 | ENDCLASS. 65 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_package_analyzer.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_i_a2cc_package_analyzer DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | PUBLIC SECTION. 6 | INTERFACES zif_i_a2cc_package_analyzer. 7 | PRIVATE SECTION. 8 | METHODS get_parent_packages 9 | IMPORTING 10 | package TYPE zsi_a2cc_code_metrics-package 11 | path TYPE string 12 | RETURNING 13 | VALUE(result) TYPE string. 14 | DATA packages TYPE ztti_a2cc_packages. 15 | 16 | ENDCLASS. 17 | CLASS zcl_i_a2cc_package_analyzer IMPLEMENTATION. 18 | METHOD zif_i_a2cc_package_analyzer~aggregate_packages. 19 | DATA devclasses TYPE RANGE OF devclass. 20 | 21 | devclasses = VALUE #( FOR package IN aggregated_metrics ( sign = 'I' option = 'EQ' low = package-package ) ). 22 | SORT devclasses. 23 | DELETE ADJACENT DUPLICATES FROM devclasses. 24 | 25 | SELECT devclass, parentcl FROM tdevc INTO TABLE @DATA(package_hierarchy) WHERE devclass IN @devclasses AND parentcl IN @devclasses. 26 | 27 | LOOP AT aggregated_metrics REFERENCE INTO DATA(metric). 28 | AT NEW package. 29 | TRY. 30 | APPEND VALUE #( package = metric->package 31 | parent = package_hierarchy[ devclass = metric->package ]-parentcl ) TO packages. 32 | CATCH cx_sy_itab_line_not_found. 33 | APPEND VALUE #( package = metric->package ) TO packages. 34 | ENDTRY. 35 | ENDAT. 36 | ENDLOOP. 37 | result = packages. 38 | ENDMETHOD. 39 | 40 | METHOD zif_i_a2cc_package_analyzer~get_parent_packages. 41 | result = get_parent_packages( package = package 42 | path = CONV #( package ) ). 43 | ENDMETHOD. 44 | 45 | METHOD get_parent_packages. 46 | TRY. 47 | DATA(parent_package) = packages[ package = package ]-parent. 48 | IF parent_package IS INITIAL. 49 | result = path. 50 | ELSE. 51 | result = get_parent_packages( package = parent_package 52 | path = |{ parent_package }/{ path }| ). 53 | ENDIF. 54 | CATCH cx_sy_itab_line_not_found. 55 | result = path. 56 | ENDTRY. 57 | ENDMETHOD. 58 | ENDCLASS. 59 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_where_used_provider.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_i_a2cc_where_used_provider DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. 7 | INTERFACES zif_i_A2CC_where_used_provider. 8 | METHODS constructor. 9 | PRIVATE SECTION. 10 | 11 | 12 | 13 | TYPES: BEGIN OF object_where_used_provider, 14 | objecttype TYPE zif_i_A2CC_where_used_provider=>objecttype, 15 | subtype TYPE zif_i_A2CC_where_used_provider=>subtype, 16 | instance TYPE REF TO zif_i_A2CC_where_used, 17 | END OF object_where_used_provider. 18 | TYPES object_whereused_prov_config TYPE HASHED TABLE OF object_where_used_provider WITH UNIQUE KEY objecttype subtype. 19 | DATA object_provider_config TYPE object_whereused_prov_config. 20 | 21 | METHODS get_instance_by_type IMPORTING 22 | objecttype TYPE zif_i_A2CC_where_used_provider=>objecttype 23 | subtype TYPE zif_i_A2CC_where_used_provider=>subtype 24 | RETURNING 25 | VALUE(result) TYPE REF TO zif_i_A2CC_where_used 26 | RAISING 27 | zcx_i_a2cc_metrics_impl_error. 28 | 29 | METHODS set_configuration IMPORTING object_provider_config TYPE object_whereused_prov_config. 30 | ENDCLASS. 31 | 32 | CLASS zcl_i_a2cc_where_used_provider IMPLEMENTATION. 33 | METHOD constructor. 34 | set_configuration( VALUE #( ( objecttype = 'CLAS' subtype = 'METH' instance = NEW zcl_i_a2cc_where_used_clas( 'CLAS' ) ) 35 | ( objecttype = 'FUGR' subtype = 'FUNC' instance = NEW zcl_i_a2cc_where_used_func( 'FUNC' ) ) ) ). 36 | ENDMETHOD. 37 | 38 | METHOD zif_i_A2CC_where_used_provider~get. 39 | result = get_instance_by_type( objecttype = objecttype subtype = subtype ). 40 | ENDMETHOD. 41 | 42 | METHOD get_instance_by_type. 43 | TRY. 44 | result = object_provider_config[ objecttype = objecttype subtype = subtype ]-instance. 45 | CATCH cx_sy_itab_line_not_found. 46 | RAISE EXCEPTION TYPE zcx_i_A2CC_metrics_impl_error. 47 | ENDTRY. 48 | ENDMETHOD. 49 | 50 | METHOD set_configuration. 51 | me->object_provider_config = object_provider_config. 52 | ENDMETHOD. 53 | ENDCLASS. 54 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_dpndncy_anlyzr_devc.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_i_a2cc_dpndncy_anlyzr_devc DEFINITION 2 | PUBLIC INHERITING FROM zcl_i_a2cc_dpndncy_anlyzr_clas 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. 7 | METHODS constructor. 8 | PROTECTED SECTION. 9 | METHODS collect_object_where_used_list REDEFINITION. 10 | METHODS where_used_analysis REDEFINITION. 11 | 12 | PRIVATE SECTION. 13 | 14 | TYPES: 15 | BEGIN OF object_data, 16 | object_id TYPE zei_a2cc_object_id, 17 | object_type TYPE trobjtype, 18 | package TYPE char30, 19 | END OF object_data . 20 | CONSTANTS package_obj TYPE trobjtype VALUE 'DEVC'. 21 | 22 | DATA: 23 | packages TYPE HASHED TABLE OF object_data WITH UNIQUE KEY object_id object_type. 24 | 25 | METHODS aggregate_to_package_level 26 | IMPORTING 27 | !depending_objects TYPE zif_i_a2cc_where_used=>object_list 28 | RETURNING 29 | VALUE(result) TYPE zif_i_a2cc_where_used=>object_list . 30 | ENDCLASS. 31 | 32 | 33 | 34 | CLASS zcl_i_a2cc_dpndncy_anlyzr_devc IMPLEMENTATION. 35 | 36 | METHOD aggregate_to_package_level. 37 | LOOP AT depending_objects REFERENCE INTO DATA(depending_object). 38 | DATA(package) = COND string( WHEN line_exists( packages[ object_id = depending_object->depending_object object_type = depending_object->depending_type ] ) 39 | THEN packages[ object_id = depending_object->depending_object object_type = depending_object->depending_type ]-package 40 | ELSE |{ depending_object->depending_object }.{ depending_object->depending_type }| ). 41 | 42 | INSERT VALUE #( depending_object = package depending_type = package_obj ) INTO TABLE result. 43 | ENDLOOP. 44 | SORT result. 45 | DELETE ADJACENT DUPLICATES FROM result COMPARING depending_object depending_type. 46 | ENDMETHOD. 47 | 48 | 49 | METHOD collect_object_where_used_list. 50 | TRY. 51 | DATA(references) = REF #( me->object_where_used_list_by[ object_identifier = metric->package object_type = package_obj ]-references ). 52 | LOOP AT depending_objects REFERENCE INTO DATA(depending_object). 53 | IF line_exists( references->*[ depending_object = depending_object->depending_object depending_type = depending_object->depending_type ] ). 54 | ASSIGN references->*[ depending_object = depending_object->depending_object depending_type = depending_object->depending_type ] TO FIELD-SYMBOL(). 55 | -number_of_usages = -number_of_usages + 1. 56 | ELSE. 57 | INSERT depending_object->* INTO TABLE references->*. 58 | ENDIF. 59 | ENDLOOP. 60 | CATCH cx_sy_itab_line_not_found. 61 | INSERT VALUE #( object_identifier = metric->package object_type = package_obj references = depending_objects ) INTO TABLE object_where_used_list_by. 62 | ENDTRY. 63 | ENDMETHOD. 64 | 65 | METHOD constructor. 66 | super->constructor( ). 67 | ENDMETHOD. 68 | 69 | METHOD where_used_analysis. 70 | LOOP AT metrics REFERENCE INTO DATA(metric). 71 | INSERT VALUE #( object_id = metric->modu_unit_1 object_type = metric->category package = metric->package ) INTO TABLE packages. 72 | ENDLOOP. 73 | 74 | LOOP AT metrics REFERENCE INTO metric. 75 | TRY. 76 | DATA(depending_objects) = where_used_provider->get( objecttype = metric->category subtype = metric->sub_type )->get_cross_references( VALUE #( object = metric->modu_unit_1 77 | subobject = metric->modu_unit_2 ) ). 78 | IF has_where_used_entries( depending_objects ). 79 | collect_object_where_used_list( metric = metric depending_objects = aggregate_to_package_level( depending_objects->* ) ). 80 | ENDIF. 81 | CATCH zcx_i_a2cc_metrics_impl_error. 82 | CONTINUE. 83 | ENDTRY. 84 | ENDLOOP. 85 | ENDMETHOD. 86 | ENDCLASS. 87 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_dpndncy_anlyzr_clas.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_i_a2cc_dpndncy_anlyzr_clas DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | INTERFACES zif_i_a2cc_dependency_analyzer. 7 | METHODS constructor. 8 | PROTECTED SECTION. 9 | METHODS collect_object_where_used_list 10 | IMPORTING 11 | metric TYPE REF TO zsi_a2cc_code_metrics 12 | depending_objects TYPE zif_i_a2cc_where_used=>object_list. 13 | METHODS where_used_analysis 14 | IMPORTING 15 | metrics TYPE ztti_a2cc_code_metrics. 16 | 17 | DATA where_used_provider TYPE REF TO zif_i_a2cc_where_used_provider. 18 | DATA object_where_used_list_by TYPE zif_i_a2cc_where_used=>where_used_list. 19 | 20 | METHODS has_where_used_entries 21 | IMPORTING 22 | object_list TYPE REF TO zif_i_a2cc_where_used=>object_list 23 | RETURNING 24 | VALUE(result) TYPE abap_bool. 25 | PRIVATE SECTION. 26 | DATA: analyze_dependecies TYPE abap_bool, 27 | analyze_direct_cycles TYPE abap_bool. 28 | METHODS analyze_cycles. 29 | ENDCLASS. 30 | 31 | CLASS zcl_i_a2cc_dpndncy_anlyzr_clas IMPLEMENTATION. 32 | METHOD constructor. 33 | where_used_provider = NEW zcl_i_a2cc_where_used_provider( ). 34 | ENDMETHOD. 35 | 36 | METHOD zif_i_a2cc_dependency_analyzer~find_object_usages. 37 | me->analyze_dependecies = analyze_dependecies. 38 | me->analyze_direct_cycles = analyze_direct_cycles. 39 | 40 | IF analyze_dependecies = abap_true OR analyze_direct_cycles = abap_true. 41 | where_used_analysis( metrics ). 42 | ENDIF. 43 | IF analyze_direct_cycles = abap_true. 44 | analyze_cycles( ). 45 | ENDIF. 46 | result = object_where_used_list_by. 47 | ENDMETHOD. 48 | 49 | METHOD where_used_analysis. 50 | LOOP AT metrics REFERENCE INTO DATA(metric). 51 | TRY. 52 | DATA(depending_objects) = where_used_provider->get( objecttype = metric->category subtype = metric->sub_type )->get_cross_references( VALUE #( object = metric->modu_unit_1 53 | subobject = metric->modu_unit_2 ) ). 54 | IF has_where_used_entries( depending_objects ). 55 | collect_object_where_used_list( metric = metric depending_objects = depending_objects->* ). 56 | ENDIF. 57 | CATCH zcx_i_a2cc_metrics_impl_error. 58 | "Fallback for unknown references 59 | INSERT VALUE #( object_identifier = metric->modu_unit_1 references = VALUE #( ( depending_object = |{ zcl_i_a2cc_metrics_2_json=>system }| number_of_usages = 1 ) ) ) 60 | INTO TABLE object_where_used_list_by. 61 | ENDTRY. 62 | ENDLOOP. 63 | ENDMETHOD. 64 | 65 | METHOD analyze_cycles. 66 | LOOP AT object_where_used_list_by REFERENCE INTO DATA(object_where_used). 67 | LOOP AT object_where_used->references REFERENCE INTO DATA(reference). 68 | DATA(line_index) = sy-tabix. 69 | TRY. 70 | data(references) = object_where_used_list_by[ object_identifier = reference->depending_object object_type = reference->depending_type ]-references. 71 | DATA(back_refenrence) = references[ depending_object = object_where_used->object_identifier depending_type = object_where_used->object_type ]. 72 | reference->cycle = 1. 73 | CATCH cx_sy_itab_line_not_found. 74 | DELETE TABLE object_where_used->references FROM reference->*. 75 | ENDTRY. 76 | ENDLOOP. 77 | ENDLOOP. 78 | ENDMETHOD. 79 | 80 | METHOD has_where_used_entries. 81 | result = boolc( object_list IS NOT INITIAL AND lines( object_list->* ) > 0 ). 82 | ENDMETHOD. 83 | 84 | METHOD collect_object_where_used_list. 85 | TRY. 86 | DATA(references) = REF #( me->object_where_used_list_by[ object_identifier = metric->modu_unit_1 object_type = metric->category ]-references ). 87 | LOOP AT depending_objects REFERENCE INTO DATA(depending_object). 88 | IF line_exists( references->*[ depending_object = depending_object->depending_object depending_type = depending_object->depending_type ] ). 89 | ASSIGN references->*[ depending_object = depending_object->depending_object depending_type = depending_object->depending_type ] TO FIELD-SYMBOL(). 90 | -number_of_usages = -number_of_usages + 1. 91 | ELSE. 92 | INSERT depending_object->* INTO TABLE references->*. 93 | ENDIF. 94 | ENDLOOP. 95 | CATCH cx_sy_itab_line_not_found. 96 | INSERT VALUE #( object_identifier = metric->modu_unit_1 object_type = metric->category references = depending_objects ) INTO TABLE object_where_used_list_by. 97 | ENDTRY. 98 | ENDMETHOD. 99 | ENDCLASS. 100 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_aggregator_package.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_i_a2cc_aggregator_package DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. 7 | INTERFACES zif_i_a2cc_aggregator . 8 | PRIVATE SECTION. 9 | ENDCLASS. 10 | 11 | CLASS zcl_i_a2cc_aggregator_package IMPLEMENTATION. 12 | METHOD zif_i_a2cc_aggregator~aggregate_metrics. 13 | DATA aggregated_metric TYPE zsi_a2cc_code_metrics. 14 | 15 | LOOP AT metrics REFERENCE INTO DATA(metric). 16 | aggregated_metric-component_to_be_changed = metric->component_to_be_changed. 17 | aggregated_metric-package = metric->package. 18 | aggregated_metric-category = 'DEVC'. 19 | aggregated_metric-modu_unit_1 = metric->package. 20 | aggregated_metric-loc = aggregated_metric-loc + metric->loc . 21 | IF metric->nos >= 2. 22 | aggregated_metric-nos = aggregated_metric-nos + metric->nos - 2 . "DO not Consider METHOD/ENDMETHOD 23 | ELSE. 24 | aggregated_metric-nos = aggregated_metric-nos + metric->nos. 25 | ENDIF. 26 | aggregated_metric-noc = aggregated_metric-noc + metric->noc . 27 | aggregated_metric-nop = aggregated_metric-nop + metric->nop . 28 | aggregated_metric-mcc_com = aggregated_metric-mcc_com + metric->mcc_com . 29 | aggregated_metric-vrsd_chan = aggregated_metric-vrsd_chan + metric->vrsd_chan . 30 | aggregated_metric-dd_total = aggregated_metric-dd_total + metric->dd_total . 31 | aggregated_metric-stmts_c = aggregated_metric-stmts_c + metric->stmts_c . 32 | aggregated_metric-stmts_p = aggregated_metric-stmts_p + metric->stmts_p . 33 | aggregated_metric-stmts_i = aggregated_metric-stmts_i + metric->stmts_i . 34 | aggregated_metric-stmts_e = aggregated_metric-stmts_e + metric->stmts_e . 35 | aggregated_metric-stmts_ei = aggregated_metric-stmts_ei + metric->stmts_ei . 36 | aggregated_metric-stmts_d = aggregated_metric-stmts_d + metric->stmts_d . 37 | aggregated_metric-stmts_w = aggregated_metric-stmts_w + metric->stmts_w . 38 | aggregated_metric-stmts_l = aggregated_metric-stmts_l + metric->stmts_l . 39 | aggregated_metric-stmts_ca = aggregated_metric-stmts_ca + metric->stmts_ca . 40 | aggregated_metric-stmts_wh = aggregated_metric-stmts_wh + metric->stmts_wh . 41 | aggregated_metric-stmts_sl = aggregated_metric-stmts_sl + metric->stmts_sl . 42 | aggregated_metric-stmts_ins = aggregated_metric-stmts_ins + metric->stmts_ins . 43 | aggregated_metric-stmts_upd = aggregated_metric-stmts_upd + metric->stmts_upd . 44 | aggregated_metric-stmts_del = aggregated_metric-stmts_del + metric->stmts_del . 45 | aggregated_metric-stmts_mod = aggregated_metric-stmts_mod + metric->stmts_mod . 46 | aggregated_metric-diff_vers = aggregated_metric-diff_vers + metric->diff_vers . 47 | aggregated_metric-diff_mod_l = aggregated_metric-diff_mod_l + metric->diff_mod_l. 48 | aggregated_metric-diff_new_l = aggregated_metric-diff_new_l + metric->diff_new_l. 49 | aggregated_metric-diff_sap = aggregated_metric-diff_sap + metric->diff_sap . 50 | aggregated_metric-mod_db = aggregated_metric-mod_db + metric->mod_db . 51 | aggregated_metric-mod_call = aggregated_metric-mod_call + metric->mod_call . 52 | aggregated_metric-mod_bra = aggregated_metric-mod_bra + metric->mod_bra . 53 | aggregated_metric-number_of_methods = aggregated_metric-number_of_methods + 1. 54 | AT END OF package. 55 | aggregated_metric-average_nos_per_method = aggregated_metric-nos / aggregated_metric-number_of_methods. 56 | aggregated_metric-decission_depth_complexity = aggregated_metric-dd_total. 57 | aggregated_metric-db_access_statements = aggregated_metric-stmts_sl + 58 | aggregated_metric-stmts_ins + 59 | aggregated_metric-stmts_mod + 60 | aggregated_metric-stmts_del. 61 | 62 | aggregated_metric-cyclomatic_complexity = aggregated_metric-stmts_i + 63 | aggregated_metric-stmts_e + 64 | aggregated_metric-stmts_ei + 65 | aggregated_metric-stmts_d + 66 | aggregated_metric-stmts_w + 67 | aggregated_metric-stmts_l + 68 | aggregated_metric-stmts_ca + 69 | aggregated_metric-stmts_wh. 70 | aggregated_metric-cyclomatic_complexity_avg = aggregated_metric-cyclomatic_complexity / aggregated_metric-number_of_methods. 71 | 72 | APPEND aggregated_metric TO result. 73 | CLEAR aggregated_metric. 74 | ENDAT. 75 | ENDLOOP. 76 | ENDMETHOD. 77 | ENDCLASS. 78 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_aggregator_class.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_i_a2cc_aggregator_class DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. 7 | INTERFACES zif_i_a2cc_aggregator . 8 | PRIVATE SECTION. 9 | ENDCLASS. 10 | 11 | CLASS zcl_i_a2cc_aggregator_class IMPLEMENTATION. 12 | METHOD zif_i_a2cc_aggregator~aggregate_metrics. 13 | DATA aggregated_metric TYPE zsi_a2cc_code_metrics. 14 | 15 | LOOP AT metrics REFERENCE INTO DATA(metric). 16 | aggregated_metric-component_to_be_changed = metric->component_to_be_changed. 17 | aggregated_metric-package = metric->package. 18 | aggregated_metric-category = metric->category. 19 | aggregated_metric-modu_unit_1 = metric->modu_unit_1. 20 | aggregated_metric-loc = aggregated_metric-loc + metric->loc . 21 | IF metric->nos >= 2. 22 | aggregated_metric-nos = aggregated_metric-nos + metric->nos - 2 . "DO not Consider METHOD/ENDMETHOD 23 | ELSE. 24 | aggregated_metric-nos = aggregated_metric-nos + metric->nos. 25 | ENDIF. 26 | aggregated_metric-noc = aggregated_metric-noc + metric->noc . 27 | aggregated_metric-nop = aggregated_metric-nop + metric->nop . 28 | aggregated_metric-mcc_com = aggregated_metric-mcc_com + metric->mcc_com . 29 | aggregated_metric-vrsd_chan = aggregated_metric-vrsd_chan + metric->vrsd_chan . 30 | aggregated_metric-dd_total = aggregated_metric-dd_total + metric->dd_total . 31 | aggregated_metric-stmts_c = aggregated_metric-stmts_c + metric->stmts_c . 32 | aggregated_metric-stmts_p = aggregated_metric-stmts_p + metric->stmts_p . 33 | aggregated_metric-stmts_i = aggregated_metric-stmts_i + metric->stmts_i . 34 | aggregated_metric-stmts_e = aggregated_metric-stmts_e + metric->stmts_e . 35 | aggregated_metric-stmts_ei = aggregated_metric-stmts_ei + metric->stmts_ei . 36 | aggregated_metric-stmts_d = aggregated_metric-stmts_d + metric->stmts_d . 37 | aggregated_metric-stmts_w = aggregated_metric-stmts_w + metric->stmts_w . 38 | aggregated_metric-stmts_l = aggregated_metric-stmts_l + metric->stmts_l . 39 | aggregated_metric-stmts_ca = aggregated_metric-stmts_ca + metric->stmts_ca . 40 | aggregated_metric-stmts_wh = aggregated_metric-stmts_wh + metric->stmts_wh . 41 | aggregated_metric-stmts_sl = aggregated_metric-stmts_sl + metric->stmts_sl . 42 | aggregated_metric-stmts_ins = aggregated_metric-stmts_ins + metric->stmts_ins . 43 | aggregated_metric-stmts_upd = aggregated_metric-stmts_upd + metric->stmts_upd . 44 | aggregated_metric-stmts_del = aggregated_metric-stmts_del + metric->stmts_del . 45 | aggregated_metric-stmts_mod = aggregated_metric-stmts_mod + metric->stmts_mod . 46 | aggregated_metric-diff_vers = aggregated_metric-diff_vers + metric->diff_vers . 47 | aggregated_metric-diff_mod_l = aggregated_metric-diff_mod_l + metric->diff_mod_l. 48 | aggregated_metric-diff_new_l = aggregated_metric-diff_new_l + metric->diff_new_l. 49 | aggregated_metric-diff_sap = aggregated_metric-diff_sap + metric->diff_sap . 50 | aggregated_metric-mod_db = aggregated_metric-mod_db + metric->mod_db . 51 | aggregated_metric-mod_call = aggregated_metric-mod_call + metric->mod_call . 52 | aggregated_metric-mod_bra = aggregated_metric-mod_bra + metric->mod_bra . 53 | aggregated_metric-number_of_methods = aggregated_metric-number_of_methods + 1. 54 | AT END OF modu_unit_1. 55 | aggregated_metric-average_nos_per_method = aggregated_metric-nos / aggregated_metric-number_of_methods. 56 | aggregated_metric-decission_depth_complexity = aggregated_metric-dd_total. 57 | aggregated_metric-db_access_statements = aggregated_metric-stmts_sl + 58 | aggregated_metric-stmts_ins + 59 | aggregated_metric-stmts_mod + 60 | aggregated_metric-stmts_del. 61 | 62 | aggregated_metric-cyclomatic_complexity = aggregated_metric-stmts_i + 63 | aggregated_metric-stmts_e + 64 | aggregated_metric-stmts_ei + 65 | aggregated_metric-stmts_d + 66 | aggregated_metric-stmts_w + 67 | aggregated_metric-stmts_l + 68 | aggregated_metric-stmts_ca + 69 | aggregated_metric-stmts_wh. 70 | aggregated_metric-cyclomatic_complexity_avg = aggregated_metric-cyclomatic_complexity / aggregated_metric-number_of_methods. 71 | 72 | 73 | APPEND aggregated_metric TO result. 74 | CLEAR aggregated_metric. 75 | ENDAT. 76 | ENDLOOP. 77 | ENDMETHOD. 78 | ENDCLASS. 79 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_where_used_abstract.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_i_a2cc_where_used_abstract DEFINITION 2 | PUBLIC 3 | ABSTRACT 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. 7 | CLASS-METHODS class_constructor. 8 | INTERFACES zif_i_a2cc_where_used. 9 | METHODS constructor 10 | IMPORTING objecttype TYPE zif_i_a2cc_where_used_provider=>objecttype. 11 | PROTECTED SECTION. 12 | DATA objecttype TYPE zif_i_a2cc_where_used_provider=>objecttype. 13 | METHODS get_where_used_list_from_cross 14 | IMPORTING 15 | object TYPE string 16 | RETURNING 17 | VALUE(result) TYPE REF TO zif_i_a2cc_where_used~object_list. 18 | PRIVATE SECTION. 19 | TYPES: BEGIN OF internal_object, 20 | type TYPE euobj-type, 21 | id TYPE euobj-id, 22 | END OF internal_object. 23 | 24 | CLASS-DATA internal_objects TYPE SORTED TABLE OF internal_object WITH NON-UNIQUE KEY type. 25 | 26 | METHODS get_enclosing_object 27 | IMPORTING 28 | found_object TYPE REF TO rsfindlst 29 | EXPORTING 30 | enclosing_object TYPE rsobject 31 | enclosing_type TYPE trobjtype . 32 | METHODS get_parent_object_type 33 | IMPORTING 34 | found_object TYPE REF TO rsfindlst 35 | RETURNING 36 | VALUE(result) TYPE seu_obj. 37 | ENDCLASS. 38 | 39 | 40 | 41 | CLASS zcl_i_a2cc_where_used_abstract IMPLEMENTATION. 42 | METHOD class_constructor. 43 | SELECT * FROM euobj INTO CORRESPONDING FIELDS OF TABLE internal_objects WHERE internal = abap_false. 44 | ENDMETHOD. 45 | 46 | METHOD constructor. 47 | me->objecttype = objecttype. 48 | ENDMETHOD. 49 | 50 | 51 | METHOD get_enclosing_object. 52 | DATA group TYPE rs38l_area. 53 | DATA include TYPE progname. 54 | 55 | include = found_object->object. 56 | CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' 57 | IMPORTING 58 | group = group 59 | CHANGING 60 | include = include 61 | EXCEPTIONS 62 | OTHERS = 6. 63 | IF sy-subrc = 0 AND group IS NOT INITIAL. 64 | enclosing_object = |SAPL{ group }|. 65 | enclosing_type = 'FUGR'. 66 | ELSE. 67 | enclosing_type = 'PROG'. 68 | SELECT SINGLE master FROM d010inc INTO enclosing_object WHERE include = include. 69 | IF sy-subrc <> 0. 70 | enclosing_object = include. 71 | ENDIF. 72 | ENDIF. 73 | ENDMETHOD. 74 | 75 | 76 | METHOD get_where_used_list_from_cross. 77 | DATA: findstrings TYPE TABLE OF rsfind, 78 | found_objects TYPE STANDARD TABLE OF rsfindlst, 79 | scope TYPE STANDARD TABLE OF seu_obj, 80 | find_obj_class TYPE euobj-id. 81 | DATA enclosing_type TYPE trobjtype. 82 | DATA enclosing_object TYPE rsobject. 83 | 84 | findstrings = VALUE #( ( CONV #( object ) ) ). 85 | find_obj_class = me->objecttype. 86 | 87 | CALL FUNCTION 'RS_EU_CROSSREF' 88 | EXPORTING 89 | i_find_obj_cls = find_obj_class 90 | no_dialog = abap_true 91 | TABLES 92 | i_findstrings = findstrings 93 | o_founds = found_objects 94 | i_scope_object_cls = scope 95 | EXCEPTIONS 96 | not_executed = 1 97 | not_found = 2 98 | illegal_object = 3 99 | no_cross_for_this_object = 4 100 | batch = 5 101 | batchjob_error = 6 102 | wrong_type = 7 103 | object_not_exist = 8 104 | OTHERS = 9. 105 | IF sy-subrc IS INITIAL. 106 | result = NEW #( ). 107 | LOOP AT found_objects REFERENCE INTO DATA(found_object). 108 | 109 | IF found_object->encl_objec IS NOT INITIAL. 110 | enclosing_object = found_object->encl_objec. 111 | enclosing_type = get_parent_object_type( found_object ). 112 | ELSE. 113 | get_enclosing_object( EXPORTING found_object = found_object 114 | IMPORTING enclosing_object = enclosing_object 115 | enclosing_type = enclosing_type ). 116 | ENDIF. 117 | 118 | IF line_exists( result->*[ depending_object = enclosing_object depending_type = enclosing_type(4) ] ). 119 | ASSIGN result->*[ depending_object = enclosing_object ] TO FIELD-SYMBOL(). 120 | -number_of_usages = -number_of_usages + 1. 121 | ELSE. 122 | INSERT VALUE #( depending_object = enclosing_object depending_type = enclosing_type(4) number_of_usages = 1 ) INTO TABLE result->*. 123 | ENDIF. . 124 | ENDLOOP. 125 | ENDIF. 126 | ENDMETHOD. 127 | 128 | METHOD get_parent_object_type. 129 | result = VALUE seu_obj( internal_objects[ type = found_object->object_cls ]-id OPTIONAL ). 130 | 131 | result = COND #( WHEN result(4) = 'PROG' AND found_object->*(4) = 'SAPL' THEN 'FUGR' 132 | WHEN result = 'METH' THEN 'CLAS' 133 | ELSE result(4) ). 134 | ENDMETHOD. 135 | 136 | METHOD zif_i_a2cc_where_used~get_cross_references. 137 | 138 | ENDMETHOD. 139 | ENDCLASS. 140 | -------------------------------------------------------------------------------- /src/zi_abap_to_codecharta.prog.abap: -------------------------------------------------------------------------------- 1 | * 2 | * This is version 0.5.3 3 | * 4 | *The MIT License (MIT) 5 | * 6 | *Copyright (c) 2021 Benjamin Weisheit 7 | * 8 | *Permission is hereby granted, free of charge, to any person obtaining a copy 9 | *of this software and associated documentation files (the "Software"), to deal 10 | *in the Software without restriction, including without limitation the rights 11 | *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | *copies of the Software, and to permit persons to whom the Software is 13 | *furnished to do so, subject to the following conditions: 14 | * 15 | *The above copyright notice and this permission notice shall be included in all 16 | *copies or substantial portions of the Software. 17 | * 18 | *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | *SOFTWARE. 25 | 26 | REPORT zi_abap_to_codecharta. 27 | 28 | CLASS lcl_code_metrics DEFINITION. 29 | PUBLIC SECTION. 30 | METHODS run 31 | IMPORTING 32 | selection_variant TYPE variant 33 | RETURNING 34 | VALUE(result) TYPE ztti_a2cc_code_metrics 35 | RAISING 36 | cx_salv_bs_sc_runtime_info. 37 | PRIVATE SECTION. 38 | METHODS set_alv_runtime_info. 39 | METHODS submit_code_metrics_report 40 | IMPORTING 41 | selection_variant TYPE variant. 42 | METHODS get_alv_list_from_report 43 | RETURNING 44 | VALUE(result) TYPE ztti_a2cc_code_metrics 45 | RAISING 46 | cx_salv_bs_sc_runtime_info. 47 | ENDCLASS. 48 | 49 | CLASS lcl_code_metrics IMPLEMENTATION. 50 | METHOD run. 51 | set_alv_runtime_info( ). 52 | submit_code_metrics_report( selection_variant ). 53 | result = get_alv_list_from_report( ). 54 | ENDMETHOD. 55 | 56 | METHOD get_alv_list_from_report. 57 | FIELD-SYMBOLS TYPE STANDARD TABLE. 58 | DATA alv_list TYPE REF TO data. 59 | cl_salv_bs_runtime_info=>get_data_ref( IMPORTING r_data = alv_list ). 60 | ASSIGN alv_list->* TO . 61 | MOVE-CORRESPONDING TO result. 62 | ENDMETHOD. 63 | 64 | METHOD submit_code_metrics_report. 65 | SUBMIT /sdf/cd_custom_code_metric 66 | USING SELECTION-SET selection_variant 67 | EXPORTING LIST TO MEMORY 68 | AND RETURN. 69 | ENDMETHOD. 70 | 71 | METHOD set_alv_runtime_info. 72 | cl_salv_bs_runtime_info=>set( 73 | EXPORTING display = abap_false 74 | metadata = abap_false 75 | data = abap_true ). 76 | ENDMETHOD. 77 | ENDCLASS. 78 | 79 | CLASS lcl_input_screen DEFINITION. 80 | PUBLIC SECTION. 81 | METHODS check_file_directory 82 | IMPORTING 83 | file TYPE localfile. 84 | METHODS check_variant 85 | IMPORTING 86 | variant TYPE variant. 87 | ENDCLASS. 88 | 89 | CLASS lcl_input_screen IMPLEMENTATION. 90 | METHOD check_file_directory. 91 | DATA directory TYPE localfile. 92 | CALL FUNCTION 'LIST_SPLIT_PATH' 93 | EXPORTING 94 | filename = file 95 | IMPORTING 96 | pathname = directory. 97 | CALL FUNCTION 'PFL_CHECK_DIRECTORY' 98 | EXPORTING 99 | directory_long = directory 100 | EXCEPTIONS 101 | pfl_dir_not_exist = 1 102 | pfl_permission_denied = 2 103 | pfl_cant_build_dataset_name = 3 104 | pfl_file_not_exist = 4 105 | pfl_authorization_missing = 5 106 | OTHERS = 6. 107 | IF sy-subrc <> 0. 108 | CASE sy-subrc. 109 | WHEN 1. 110 | MESSAGE 'Directory does not exist on the appserver'(002) TYPE 'E'. 111 | WHEN 2 OR 5. 112 | MESSAGE 'No permission to the directory on the appserver'(003) TYPE 'E'. 113 | WHEN OTHERS. 114 | MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno 115 | WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. 116 | ENDCASE. 117 | ENDIF. 118 | ENDMETHOD. 119 | 120 | METHOD check_variant. 121 | SELECT SINGLE variant INTO @DATA(exists) FROM varid 122 | WHERE report EQ '/SDF/CD_CUSTOM_CODE_METRIC' 123 | AND variant EQ @variant. 124 | IF sy-subrc IS NOT INITIAL. 125 | MESSAGE 'Variant not defined for Code Metrics in tx /SDF/CD_CCA'(001) TYPE 'E'. 126 | ENDIF. 127 | ENDMETHOD. 128 | ENDCLASS. 129 | 130 | CLASS lcl_file_output DEFINITION. 131 | PUBLIC SECTION. 132 | METHODS write_file 133 | IMPORTING 134 | VALUE(file_name) TYPE localfile 135 | json TYPE string. 136 | PRIVATE SECTION. 137 | METHODS convert_string_to_xstring 138 | IMPORTING 139 | string TYPE string 140 | RETURNING 141 | VALUE(result) TYPE xstring. 142 | METHODS write_xstring_to_file 143 | IMPORTING 144 | file_name TYPE localfile 145 | xstring TYPE xstring. 146 | METHODS adjust_filename 147 | IMPORTING 148 | file_name TYPE localfile 149 | RETURNING 150 | VALUE(result) TYPE localfile. 151 | ENDCLASS. 152 | 153 | CLASS lcl_file_output IMPLEMENTATION. 154 | METHOD write_file. 155 | write_xstring_to_file( 156 | file_name = adjust_filename( file_name ) 157 | xstring = convert_string_to_xstring( json ) ). 158 | ENDMETHOD. 159 | METHOD write_xstring_to_file. 160 | OPEN DATASET file_name FOR OUTPUT IN BINARY MODE. 161 | IF sy-subrc NE 0. 162 | WRITE : / 'Error Opening the Server Filepath :', file_name. 163 | ELSE. 164 | TRANSFER xstring TO file_name. 165 | CLOSE DATASET file_name. 166 | WRITE : / 'File Downloaded to the Server at :', file_name. 167 | ENDIF. 168 | ENDMETHOD. 169 | 170 | METHOD convert_string_to_xstring. 171 | CALL FUNCTION 'SCMS_STRING_TO_XSTRING' 172 | EXPORTING 173 | text = string 174 | IMPORTING 175 | buffer = result. 176 | ENDMETHOD. 177 | 178 | METHOD adjust_filename. 179 | result = file_name. 180 | REPLACE ALL OCCURRENCES OF '' IN result WITH sy-datum. 181 | ENDMETHOD. 182 | ENDCLASS. 183 | 184 | PARAMETERS varnt TYPE variant. 185 | PARAMETERS file TYPE localfile. 186 | 187 | SELECTION-SCREEN BEGIN OF BLOCK d WITH FRAME TITLE TEXT-bld. 188 | PARAMETERS agg_modl TYPE abap_bool RADIOBUTTON GROUP agg DEFAULT 'X'. 189 | PARAMETERS agg_devc TYPE abap_bool RADIOBUTTON GROUP agg. 190 | SELECTION-SCREEN END OF BLOCK d. 191 | 192 | SELECTION-SCREEN BEGIN OF BLOCK a WITH FRAME TITLE TEXT-bla. 193 | PARAMETERS dpndncy TYPE abap_bool RADIOBUTTON GROUP dpn DEFAULT 'X'. 194 | PARAMETERS wo_dpnd TYPE abap_bool RADIOBUTTON GROUP dpn. 195 | PARAMETERS cycls TYPE abap_bool RADIOBUTTON GROUP dpn. 196 | SELECTION-SCREEN END OF BLOCK a. 197 | 198 | AT SELECTION-SCREEN. 199 | DATA(input_screen) = NEW lcl_input_screen( ). 200 | input_screen->check_file_directory( file ). 201 | input_screen->check_variant( varnt ). 202 | 203 | START-OF-SELECTION. 204 | DATA(code_metrics) = NEW lcl_code_metrics( )->run( varnt ). 205 | 206 | DATA(abap2codecharta) = zcl_i_a2cc_factory=>create( COND #( WHEN agg_devc = abap_true 207 | THEN zcl_i_a2cc_factory=>aggregation_levels-package 208 | ELSE zcl_i_a2cc_factory=>aggregation_levels-class ) ). 209 | 210 | DATA(json) = abap2codecharta->to_json( metrics = code_metrics 211 | analyze_dependecies = dpndncy 212 | analyze_direct_cycles = cycls ). 213 | 214 | NEW lcl_file_output( )->write_file( file_name = file 215 | json = json ). 216 | -------------------------------------------------------------------------------- /src/zsi_a2cc_code_metrics.tabl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZSI_A2CC_CODE_METRICS 7 | D 8 | INTTAB 9 | D 10 | 1 11 | 12 | 13 | 14 | ZSI_A2CC_CODE_METRICS 15 | PACKAGE 16 | 0001 17 | CHAR30 18 | 0 19 | E 20 | 21 | 22 | ZSI_A2CC_CODE_METRICS 23 | CATEGORY 24 | 0002 25 | CHAR4 26 | 0 27 | E 28 | 29 | 30 | ZSI_A2CC_CODE_METRICS 31 | MODU_UNIT_1 32 | 0003 33 | ZEI_A2CC_OBJECT_ID 34 | 0 35 | E 36 | 37 | 38 | ZSI_A2CC_CODE_METRICS 39 | SUB_TYPE 40 | 0004 41 | CHAR4 42 | 0 43 | E 44 | 45 | 46 | ZSI_A2CC_CODE_METRICS 47 | MODU_UNIT_2 48 | 0005 49 | ZEI_A2CC_OBJECT_ID 50 | 0 51 | E 52 | 53 | 54 | ZSI_A2CC_CODE_METRICS 55 | AUTHOR 56 | 0006 57 | CHAR30 58 | 0 59 | E 60 | 61 | 62 | ZSI_A2CC_CODE_METRICS 63 | CHANGER 64 | 0007 65 | CHAR30 66 | 0 67 | E 68 | 69 | 70 | ZSI_A2CC_CODE_METRICS 71 | SOBJ_NAME 72 | 0008 73 | CHAR128 74 | 0 75 | E 76 | 77 | 78 | ZSI_A2CC_CODE_METRICS 79 | LOC 80 | 0009 81 | INT4 82 | 0 83 | E 84 | 85 | 86 | ZSI_A2CC_CODE_METRICS 87 | NOS 88 | 0010 89 | INT4 90 | 0 91 | E 92 | 93 | 94 | ZSI_A2CC_CODE_METRICS 95 | NOC 96 | 0011 97 | INT4 98 | 0 99 | E 100 | 101 | 102 | ZSI_A2CC_CODE_METRICS 103 | NOP 104 | 0012 105 | INT4 106 | 0 107 | E 108 | 109 | 110 | ZSI_A2CC_CODE_METRICS 111 | MCC_COM 112 | 0013 113 | INT4 114 | 0 115 | E 116 | 117 | 118 | ZSI_A2CC_CODE_METRICS 119 | VRSD_CHAN 120 | 0014 121 | INT4 122 | 0 123 | E 124 | 125 | 126 | ZSI_A2CC_CODE_METRICS 127 | DD_TOTAL 128 | 0015 129 | INT4 130 | 0 131 | E 132 | 133 | 134 | ZSI_A2CC_CODE_METRICS 135 | STMTS_C 136 | 0016 137 | INT4 138 | 0 139 | E 140 | 141 | 142 | ZSI_A2CC_CODE_METRICS 143 | STMTS_P 144 | 0017 145 | INT4 146 | 0 147 | E 148 | 149 | 150 | ZSI_A2CC_CODE_METRICS 151 | STMTS_I 152 | 0018 153 | INT4 154 | 0 155 | E 156 | 157 | 158 | ZSI_A2CC_CODE_METRICS 159 | STMTS_E 160 | 0019 161 | INT4 162 | 0 163 | E 164 | 165 | 166 | ZSI_A2CC_CODE_METRICS 167 | STMTS_EI 168 | 0020 169 | INT4 170 | 0 171 | E 172 | 173 | 174 | ZSI_A2CC_CODE_METRICS 175 | STMTS_D 176 | 0021 177 | INT4 178 | 0 179 | E 180 | 181 | 182 | ZSI_A2CC_CODE_METRICS 183 | STMTS_W 184 | 0022 185 | INT4 186 | 0 187 | E 188 | 189 | 190 | ZSI_A2CC_CODE_METRICS 191 | STMTS_L 192 | 0023 193 | INT4 194 | 0 195 | E 196 | 197 | 198 | ZSI_A2CC_CODE_METRICS 199 | STMTS_CA 200 | 0024 201 | INT4 202 | 0 203 | E 204 | 205 | 206 | ZSI_A2CC_CODE_METRICS 207 | STMTS_WH 208 | 0025 209 | INT4 210 | 0 211 | E 212 | 213 | 214 | ZSI_A2CC_CODE_METRICS 215 | STMTS_SL 216 | 0026 217 | INT4 218 | 0 219 | E 220 | 221 | 222 | ZSI_A2CC_CODE_METRICS 223 | STMTS_INS 224 | 0027 225 | INT4 226 | 0 227 | E 228 | 229 | 230 | ZSI_A2CC_CODE_METRICS 231 | STMTS_UPD 232 | 0028 233 | INT4 234 | 0 235 | E 236 | 237 | 238 | ZSI_A2CC_CODE_METRICS 239 | STMTS_DEL 240 | 0029 241 | INT4 242 | 0 243 | E 244 | 245 | 246 | ZSI_A2CC_CODE_METRICS 247 | STMTS_MOD 248 | 0030 249 | INT4 250 | 0 251 | E 252 | 253 | 254 | ZSI_A2CC_CODE_METRICS 255 | DIFF_VERS 256 | 0031 257 | INT4 258 | 0 259 | E 260 | 261 | 262 | ZSI_A2CC_CODE_METRICS 263 | DIFF_MOD_L 264 | 0032 265 | INT4 266 | 0 267 | E 268 | 269 | 270 | ZSI_A2CC_CODE_METRICS 271 | DIFF_NEW_L 272 | 0033 273 | INT4 274 | 0 275 | E 276 | 277 | 278 | ZSI_A2CC_CODE_METRICS 279 | DIFF_SAP 280 | 0034 281 | INT4 282 | 0 283 | E 284 | 285 | 286 | ZSI_A2CC_CODE_METRICS 287 | MOD_DB 288 | 0035 289 | INT4 290 | 0 291 | E 292 | 293 | 294 | ZSI_A2CC_CODE_METRICS 295 | MOD_CALL 296 | 0036 297 | INT4 298 | 0 299 | E 300 | 301 | 302 | ZSI_A2CC_CODE_METRICS 303 | MOD_BRA 304 | 0037 305 | INT4 306 | 0 307 | E 308 | 309 | 310 | ZSI_A2CC_CODE_METRICS 311 | NUMBER_OF_METHODS 312 | 0038 313 | INT4 314 | 0 315 | E 316 | 317 | 318 | ZSI_A2CC_CODE_METRICS 319 | AVERAGE_NOS_PER_METHOD 320 | 0039 321 | GTB_QUAN_TOTAL 322 | 0 323 | GTB_S_ALV_REFERENCE 324 | GTB_MEINH 325 | E 326 | 327 | 328 | ZSI_A2CC_CODE_METRICS 329 | DECISSION_DEPTH_COMPLEXITY 330 | 0040 331 | GTB_QUAN_TOTAL 332 | 0 333 | GTB_S_ALV_REFERENCE 334 | GTB_MEINH 335 | E 336 | 337 | 338 | ZSI_A2CC_CODE_METRICS 339 | DB_ACCESS_STATEMENTS 340 | 0041 341 | GTB_QUAN_TOTAL 342 | 0 343 | GTB_S_ALV_REFERENCE 344 | GTB_MEINH 345 | E 346 | 347 | 348 | ZSI_A2CC_CODE_METRICS 349 | CYCLOMATIC_COMPLEXITY 350 | 0042 351 | GTB_QUAN_TOTAL 352 | 0 353 | GTB_S_ALV_REFERENCE 354 | GTB_MEINH 355 | E 356 | 357 | 358 | ZSI_A2CC_CODE_METRICS 359 | CYCLOMATIC_COMPLEXITY_AVG 360 | 0043 361 | GTB_QUAN_TOTAL 362 | 0 363 | GTB_S_ALV_REFERENCE 364 | GTB_MEINH 365 | E 366 | 367 | 368 | ZSI_A2CC_CODE_METRICS 369 | COMPONENT_TO_BE_CHANGED 370 | D 371 | 0044 372 | 0 373 | g 374 | 000008 375 | STRG 376 | STRG 377 | 378 | 379 | 380 | 381 | 382 | -------------------------------------------------------------------------------- /src/zcl_i_a2cc_metrics_2_json.clas.abap: -------------------------------------------------------------------------------- 1 | * 2 | * This is version 0.1.0 3 | * 4 | *The MIT License (MIT) 5 | * 6 | *Copyright (c) 2021 Benjamin Weisheit 7 | * 8 | *Permission is hereby granted, free of charge, to any person obtaining a copy 9 | *of this software and associated documentation files (the "Software"), to deal 10 | *in the Software without restriction, including without limitation the rights 11 | *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | *copies of the Software, and to permit persons to whom the Software is 13 | *furnished to do so, subject to the following conditions: 14 | * 15 | *The above copyright notice and this permission notice shall be included in all 16 | *copies or substantial portions of the Software. 17 | * 18 | *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | *SOFTWARE. 25 | CLASS zcl_i_a2cc_metrics_2_json DEFINITION 26 | PUBLIC 27 | FINAL 28 | CREATE PUBLIC . 29 | 30 | PUBLIC SECTION. 31 | INTERFACES zif_i_a2cc_metrics_2_json. 32 | METHODS constructor 33 | IMPORTING 34 | json_writer TYPE REF TO if_sxml_writer 35 | package_analyzer TYPE REF TO zif_i_a2cc_package_analyzer 36 | dependency_analyzer TYPE REF TO zif_i_a2cc_dependency_analyzer 37 | metric_aggregator TYPE REF TO zif_i_a2cc_aggregator . 38 | 39 | 40 | CONSTANTS system TYPE string VALUE `/root/SYSTEM/OUTSIDE`. 41 | 42 | PRIVATE SECTION. 43 | CONSTANTS numeric TYPE string VALUE 'num' ##NO_TEXT. 44 | CONSTANTS strng TYPE string VALUE 'str' ##NO_TEXT. 45 | CONSTANTS array TYPE string VALUE 'array' ##NO_TEXT. 46 | CONSTANTS objct TYPE string VALUE 'object' ##NO_TEXT. 47 | DATA object_where_used_list_by TYPE zif_i_a2cc_where_used=>where_used_list. 48 | DATA analyze_dependecies TYPE abap_bool. 49 | DATA analyze_direct_cycles TYPE abap_bool. 50 | 51 | 52 | CLASS-DATA json_writer TYPE REF TO if_sxml_writer. 53 | 54 | METHODS write_package 55 | IMPORTING 56 | package TYPE zsi_a2cc_packages 57 | RAISING 58 | cx_sxml_state_error. 59 | METHODS convert2json 60 | RETURNING 61 | VALUE(result) TYPE string. 62 | METHODS write_edges. 63 | METHODS get_full_classpath 64 | IMPORTING 65 | object TYPE classname 66 | type TYPE trobjtype 67 | RETURNING 68 | VALUE(result) TYPE string. 69 | METHODS open_document 70 | RAISING 71 | cx_sxml_state_error. 72 | METHODS write_node_system_outside 73 | RAISING 74 | cx_sxml_state_error. 75 | METHODS open_nodes 76 | RAISING 77 | cx_sxml_state_error. 78 | METHODS close_nodes 79 | RAISING 80 | cx_sxml_state_error. 81 | METHODS open_edges 82 | RAISING 83 | cx_sxml_state_error. 84 | METHODS close_edges 85 | RAISING 86 | cx_sxml_state_error. 87 | METHODS close_document 88 | RAISING 89 | cx_sxml_state_error. 90 | 91 | METHODS write_nodes 92 | RAISING 93 | cx_sxml_state_error. 94 | 95 | METHODS find_object_usages 96 | IMPORTING 97 | metrics TYPE ztti_a2cc_code_metrics. 98 | 99 | CLASS-METHODS write_element IMPORTING name TYPE string 100 | attr TYPE string OPTIONAL 101 | value TYPE string OPTIONAL 102 | RAISING cx_sxml_state_error. 103 | DATA: aggregated_metrics TYPE ztti_a2cc_code_metrics, 104 | package_analyzer TYPE REF TO zif_i_a2cc_package_analyzer, 105 | dependency_analyzer TYPE REF TO zif_i_a2cc_dependency_analyzer, 106 | metric_aggregator TYPE REF TO zif_i_a2cc_aggregator, 107 | packages TYPE ztti_a2cc_packages. 108 | ENDCLASS. 109 | 110 | 111 | 112 | CLASS zcl_i_a2cc_metrics_2_json IMPLEMENTATION. 113 | 114 | 115 | METHOD close_document. 116 | json_writer->close_element( ). 117 | ENDMETHOD. 118 | 119 | 120 | METHOD close_edges. 121 | json_writer->close_element( ). 122 | ENDMETHOD. 123 | 124 | 125 | METHOD close_nodes. 126 | json_writer->close_element( ). 127 | json_writer->close_element( ). 128 | json_writer->close_element( ). 129 | ENDMETHOD. 130 | 131 | 132 | METHOD constructor. 133 | me->json_writer = json_writer. 134 | me->package_analyzer = package_analyzer. 135 | me->dependency_analyzer = dependency_analyzer. 136 | me->metric_aggregator = metric_aggregator. 137 | ENDMETHOD. 138 | 139 | 140 | METHOD convert2json. 141 | open_document( ). 142 | open_nodes( ). 143 | write_node_system_outside( ). 144 | write_nodes( ). 145 | close_nodes( ). 146 | open_edges( ). 147 | write_edges( ). 148 | close_edges( ). 149 | close_document( ). 150 | 151 | DATA(xjson) = CAST cl_sxml_string_writer( json_writer )->get_output( ). 152 | DATA(reader) = cl_sxml_string_reader=>create( xjson ). 153 | DATA(writer) = CAST if_sxml_writer( 154 | cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ) ). 155 | writer->set_option( option = if_sxml_writer=>co_opt_linebreaks ). 156 | writer->set_option( option = if_sxml_writer=>co_opt_indent ). 157 | reader->next_node( ). 158 | reader->skip_node( writer ). 159 | result = cl_abap_codepage=>convert_from( CAST cl_sxml_string_writer( writer )->get_output( ) ). 160 | ENDMETHOD. 161 | 162 | 163 | METHOD find_object_usages. 164 | object_where_used_list_by = dependency_analyzer->find_object_usages( metrics = metrics 165 | analyze_dependecies = analyze_dependecies 166 | analyze_direct_cycles = analyze_direct_cycles ). 167 | ENDMETHOD. 168 | 169 | 170 | METHOD get_full_classpath. 171 | DATA path TYPE string. 172 | 173 | TRY. 174 | DATA(package) = aggregated_metrics[ modu_unit_1 = object ]-package. 175 | path = package. 176 | path = package_analyzer->get_parent_packages( package ). 177 | result = |/root/{ path }/{ object }.{ type }|. 178 | CATCH cx_sy_itab_line_not_found. 179 | result = system. 180 | ENDTRY. 181 | ENDMETHOD. 182 | 183 | 184 | METHOD open_document. 185 | write_element( name = objct ). 186 | write_element( name = strng attr = 'projectName' value = 'ABAP' ). 187 | json_writer->close_element( ). 188 | write_element( name = strng attr = 'apiVersion' value = '1.1' ). 189 | json_writer->close_element( ). 190 | ENDMETHOD. 191 | 192 | 193 | METHOD open_edges. 194 | write_element( name = array attr = 'edges' ). 195 | ENDMETHOD. 196 | 197 | 198 | METHOD open_nodes. 199 | write_element( name = array attr = 'nodes' ). 200 | write_element( name = objct ). 201 | write_element( name = strng attr = 'name' value = 'root' ). 202 | json_writer->close_element( ). 203 | write_element( name = strng attr = 'type' value = 'Folder' ). 204 | json_writer->close_element( ). 205 | write_element( name = objct attr = 'attributes' ). 206 | json_writer->close_element( ). 207 | write_element( name = strng attr = 'link' ). 208 | json_writer->close_element( ). 209 | write_element( name = array attr = 'children' ). 210 | ENDMETHOD. 211 | 212 | 213 | METHOD zif_i_a2cc_metrics_2_json~to_json. 214 | me->analyze_dependecies = analyze_dependecies. 215 | me->analyze_direct_cycles = analyze_direct_cycles. 216 | 217 | SORT metrics. 218 | 219 | find_object_usages( metrics ). 220 | aggregated_metrics = metric_aggregator->aggregate_metrics( metrics ). 221 | packages = package_analyzer->aggregate_packages( aggregated_metrics ). 222 | result = convert2json( ). 223 | ENDMETHOD. 224 | 225 | 226 | METHOD write_edges. 227 | IF analyze_dependecies = abap_true OR analyze_direct_cycles = abap_true. 228 | LOOP AT object_where_used_list_by REFERENCE INTO DATA(usage). 229 | LOOP AT usage->references REFERENCE INTO DATA(used_by) 230 | WHERE depending_object <> usage->object_identifier. 231 | write_element( name = objct ). 232 | write_element( name = strng attr = 'fromNodeName' value = get_full_classpath( object = CONV #( used_by->depending_object ) type = used_by->depending_type ) ). 233 | json_writer->close_element( ). 234 | write_element( name = strng attr = 'toNodeName' value = get_full_classpath( object = CONV #( usage->object_identifier ) type = usage->object_type ) ). 235 | json_writer->close_element( ). 236 | write_element( name = objct attr = 'attributes' ). 237 | IF analyze_dependecies = abap_true. 238 | write_element( name = numeric attr = 'usage' value = CONV #( used_by->number_of_usages ) ). 239 | json_writer->close_element( ). 240 | ENDIF. 241 | IF used_by->cycle > 0 AND analyze_direct_cycles = abap_true. 242 | write_element( name = numeric attr = 'cycle' value = CONV #( used_by->cycle ) ). 243 | json_writer->close_element( ). 244 | ENDIF. 245 | json_writer->close_element( ). 246 | json_writer->close_element( ). 247 | ENDLOOP. 248 | ENDLOOP. 249 | ENDIF. 250 | ENDMETHOD. 251 | 252 | 253 | METHOD write_element. 254 | json_writer->open_element( name ). 255 | IF attr IS NOT INITIAL. 256 | json_writer->write_attribute( name = 'name' value = attr ). 257 | ENDIF. 258 | IF value IS NOT INITIAL. 259 | json_writer->write_value( value ). 260 | ENDIF. 261 | ENDMETHOD. 262 | 263 | 264 | METHOD write_nodes. 265 | LOOP AT packages REFERENCE INTO DATA(package) 266 | WHERE parent IS INITIAL. 267 | write_package( package->* ). 268 | ENDLOOP. 269 | ENDMETHOD. 270 | 271 | 272 | METHOD write_node_system_outside. 273 | write_element( name = objct ). 274 | write_element( name = strng attr = 'name' value = 'SYSTEM' ). 275 | json_writer->close_element( ). 276 | write_element( name = strng attr = 'type' value = 'Folder' ). 277 | json_writer->close_element( ). 278 | write_element( name = objct attr = 'attributes' ). 279 | json_writer->close_element( ). 280 | write_element( name = strng attr = 'link' ). 281 | json_writer->close_element( ). 282 | write_element( name = array attr = 'children' ). 283 | 284 | write_element( name = objct ). 285 | write_element( name = strng attr = 'name' value = CONV #( 'OUTSIDE' ) ). 286 | json_writer->close_element( ). 287 | write_element( name = strng attr = 'type' value = 'File' ). 288 | json_writer->close_element( ). 289 | write_element( name = objct attr = 'attributes' ). 290 | 291 | 292 | write_element( name = numeric attr = 'LinesOfCode' value = '200' ). 293 | json_writer->close_element( ). 294 | write_element( name = numeric attr = 'Statements' value = '200' ). 295 | json_writer->close_element( ). 296 | write_element( name = numeric attr = 'AvgStatementsPerMethod' value = '30' ). 297 | json_writer->close_element( ). 298 | write_element( name = numeric attr = 'NumberOfChanges' value = '10' ). 299 | json_writer->close_element( ). 300 | write_element( name = numeric attr = 'ComplexityOfConditions' value = '10' ). 301 | json_writer->close_element( ). 302 | write_element( name = numeric attr = 'DecissionDepth' value = '10' ). 303 | json_writer->close_element( ). 304 | 305 | json_writer->close_element( ). 306 | write_element( name = strng attr = 'link' value = VALUE #( ) ). 307 | json_writer->close_element( ). 308 | write_element( name = array attr = 'children' ). 309 | json_writer->close_element( ). 310 | json_writer->close_element( ). 311 | 312 | json_writer->close_element( ). 313 | json_writer->close_element( ). 314 | ENDMETHOD. 315 | 316 | 317 | METHOD write_package. 318 | write_element( name = objct ). 319 | write_element( name = strng attr = 'name' value = CONV #( package-package ) ). 320 | json_writer->close_element( ). 321 | write_element( name = strng attr = 'type' value = 'Folder' ). 322 | json_writer->close_element( ). 323 | write_element( name = objct attr = 'attributes' ). 324 | json_writer->close_element( ). 325 | write_element( name = strng attr = 'link' ). 326 | json_writer->close_element( ). 327 | write_element( name = array attr = 'children' ). 328 | LOOP AT aggregated_metrics REFERENCE INTO DATA(class) 329 | WHERE package = package-package. 330 | write_element( name = objct ). 331 | write_element( name = strng attr = 'name' value = |{ class->modu_unit_1 }.{ class->category }| ). 332 | json_writer->close_element( ). 333 | write_element( name = strng attr = 'type' value = 'File' ). 334 | json_writer->close_element( ). 335 | write_element( name = objct attr = 'attributes' ). 336 | 337 | 338 | write_element( name = numeric attr = 'LinesOfCode' value = CONV #( class->loc ) ). 339 | json_writer->close_element( ). 340 | write_element( name = numeric attr = 'Statements' value = CONV #( class->nos ) ). 341 | json_writer->close_element( ). 342 | write_element( name = numeric attr = 'AvgStatementsPerMethod' value = CONV #( class->average_nos_per_method ) ). 343 | json_writer->close_element( ). 344 | write_element( name = numeric attr = 'NumberOfChanges' value = CONV #( class->diff_vers ) ).. 345 | json_writer->close_element( ). 346 | write_element( name = numeric attr = 'DecissionDepth' value = CONV #( class->decission_depth_complexity ) ). 347 | json_writer->close_element( ). 348 | write_element( name = numeric attr = 'DbAccesses' value = CONV #( class->db_access_statements ) ). 349 | json_writer->close_element( ). 350 | write_element( name = numeric attr = 'Complexity' value = CONV #( class->cyclomatic_complexity ) ). 351 | json_writer->close_element( ). 352 | write_element( name = numeric attr = 'AvgComplexityPerMethod' value = CONV #( class->cyclomatic_complexity_avg ) ). 353 | json_writer->close_element( ). 354 | 355 | json_writer->close_element( ). 356 | write_element( name = strng attr = 'link' value = VALUE #( ) ). 357 | json_writer->close_element( ). 358 | write_element( name = array attr = 'children' ). 359 | json_writer->close_element( ). 360 | json_writer->close_element( ). 361 | ENDLOOP. 362 | LOOP AT packages REFERENCE INTO DATA(child_package) 363 | WHERE parent = package-package. 364 | write_package( child_package->* ). 365 | ENDLOOP. 366 | json_writer->close_element( ). 367 | json_writer->close_element( ). 368 | ENDMETHOD. 369 | ENDCLASS. 370 | --------------------------------------------------------------------------------