├── .gitignore ├── img ├── readme.txt ├── github_1.png ├── github_2.png ├── check_failure.png ├── check_success.png ├── findings_error_1.png ├── findings_error_2.png ├── findings_success.png └── check_in_progress.png ├── src ├── zabaplint_logo.w3mi.data.png ├── zif_abaplint_abapgit_ext.intf.abap ├── package.devc.xml ├── zif_abaplint_abapgit_ext.intf.xml ├── zcl_abaplint_abapgit_ext_logo.clas.xml ├── zcl_abaplint_abapgit_ext_exit.clas.xml ├── zabaplint_logo.w3mi.xml ├── zcl_abaplint_abapgit_ext_annot.clas.xml ├── zcl_abaplint_abapgit_ext_chkrn.clas.xml ├── zcl_abaplint_abapgit_ext_ui.clas.xml ├── zcl_abaplint_abapgit_ext_agent.clas.xml ├── zcl_abaplint_abapgit_ext_logo.clas.abap ├── zcl_abaplint_abapgit_ext_issue.clas.xml ├── zcl_abaplint_abapgit_ext_annot.clas.abap ├── zcl_abaplint_abapgit_ext_agent.clas.abap ├── zcl_abaplint_abapgit_ext_chkrn.clas.abap ├── zcl_abaplint_abapgit_ext_exit.clas.abap ├── zcl_abaplint_abapgit_ext_issue.clas.abap └── zcl_abaplint_abapgit_ext_ui.clas.abap ├── .github └── workflows │ └── reuse.yml ├── .abapgit.xml ├── .reuse └── dep5 ├── .editorconfig ├── LICENSES └── MIT.txt ├── LICENSE ├── CHANGELOG.md ├── CONTRIBUTING.md ├── README.md └── abaplint.json /.gitignore: -------------------------------------------------------------------------------- 1 | deps2 2 | -------------------------------------------------------------------------------- /img/readme.txt: -------------------------------------------------------------------------------- 1 | Images for documentation 2 | -------------------------------------------------------------------------------- /img/github_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marc-Bernard-Tools/abaplint-Ext-for-abapGit/HEAD/img/github_1.png -------------------------------------------------------------------------------- /img/github_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marc-Bernard-Tools/abaplint-Ext-for-abapGit/HEAD/img/github_2.png -------------------------------------------------------------------------------- /img/check_failure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marc-Bernard-Tools/abaplint-Ext-for-abapGit/HEAD/img/check_failure.png -------------------------------------------------------------------------------- /img/check_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marc-Bernard-Tools/abaplint-Ext-for-abapGit/HEAD/img/check_success.png -------------------------------------------------------------------------------- /img/findings_error_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marc-Bernard-Tools/abaplint-Ext-for-abapGit/HEAD/img/findings_error_1.png -------------------------------------------------------------------------------- /img/findings_error_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marc-Bernard-Tools/abaplint-Ext-for-abapGit/HEAD/img/findings_error_2.png -------------------------------------------------------------------------------- /img/findings_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marc-Bernard-Tools/abaplint-Ext-for-abapGit/HEAD/img/findings_success.png -------------------------------------------------------------------------------- /img/check_in_progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marc-Bernard-Tools/abaplint-Ext-for-abapGit/HEAD/img/check_in_progress.png -------------------------------------------------------------------------------- /src/zabaplint_logo.w3mi.data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Marc-Bernard-Tools/abaplint-Ext-for-abapGit/HEAD/src/zabaplint_logo.w3mi.data.png -------------------------------------------------------------------------------- /src/zif_abaplint_abapgit_ext.intf.abap: -------------------------------------------------------------------------------- 1 | INTERFACE zif_abaplint_abapgit_ext PUBLIC. 2 | 3 | CONSTANTS c_version TYPE string VALUE '1.2.1' ##NEEDED. 4 | 5 | TYPES ty_sha1 TYPE c LENGTH 40. 6 | 7 | ENDINTERFACE. 8 | -------------------------------------------------------------------------------- /.github/workflows/reuse.yml: -------------------------------------------------------------------------------- 1 | name: REUSE Compliance Check 2 | 3 | on: [push, pull_request,workflow_dispatch] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - name: REUSE Compliance Check 11 | uses: fsfe/reuse-action@v1 12 | -------------------------------------------------------------------------------- /.abapgit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | E 6 | /src/ 7 | PREFIX 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.reuse/dep5: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: abaplint Extension for abapGit 3 | Upstream-Contact: Marc Bernard 4 | Source: https://github.com/Marc-Bernard-Tools/abaplint-Ext-for-abapGit 5 | 6 | Files: * 7 | Copyright: 2021 Marc Bernard 8 | License: MIT 9 | -------------------------------------------------------------------------------- /src/package.devc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | abaplint - Extension for abapGit 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # 1 space indentation for xml files 7 | [*.xml] 8 | charset = utf-8 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | indent_style = space 13 | indent_size = 1 14 | 15 | # match the format used by abapGit 16 | [*.{abap,js,json,html,css}] 17 | charset = utf-8 18 | end_of_line = lf 19 | insert_final_newline = true 20 | trim_trailing_whitespace = true 21 | indent_size = 2 22 | indent_style = space 23 | -------------------------------------------------------------------------------- /src/zif_abaplint_abapgit_ext.intf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZIF_ABAPLINT_ABAPGIT_EXT 7 | E 8 | abaplint - Extension for abapGit (Definitions) 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_logo.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_ABAPLINT_ABAPGIT_EXT_LOGO 7 | E 8 | abaplint - Extension for abapGit (Logo) 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_exit.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_ABAPLINT_ABAPGIT_EXT_EXIT 7 | E 8 | abaplint - Extension for abapGit (Exit) 9 | 1 10 | X 11 | X 12 | X 13 | K 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/zabaplint_logo.w3mi.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ZABAPLINT_LOGO 6 | abaplint Logo 7 | 8 | 9 | fileextension 10 | .png 11 | 12 | 13 | filename 14 | abaplint_logo.png 15 | 16 | 17 | mimetype 18 | image/png 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_annot.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_ABAPLINT_ABAPGIT_EXT_ANNOT 7 | E 8 | abaplint - Extension for abapGit (Annotation) 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | CONSTRUCTOR 17 | ZCX_ABAPGIT_EXCEPTION 18 | E 19 | Exception 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_chkrn.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_ABAPLINT_ABAPGIT_EXT_CHKRN 7 | E 8 | abaplint - Extension for abapGit (Check Run) 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | CONSTRUCTOR 17 | ZCX_ABAPGIT_EXCEPTION 18 | E 19 | Exception 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Marc Bernard 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/zcl_abaplint_abapgit_ext_ui.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_ABAPLINT_ABAPGIT_EXT_UI 7 | E 8 | abaplint - Extension for abapGit (UI) 9 | 1 10 | X 11 | X 12 | X 13 | K 14 | 15 | 16 | 17 | _RENDER_ISSUE 18 | RI_HTML 19 | E 20 | abapGit HTML engine interface 21 | 22 | 23 | _RENDER_ISSUE 24 | ZCX_ABAPGIT_EXCEPTION 25 | E 26 | Exception 27 | 28 | 29 | _RENDER_ISSUES 30 | RI_HTML 31 | E 32 | abapGit HTML engine interface 33 | 34 | 35 | _RENDER_ISSUES 36 | ZCX_ABAPGIT_EXCEPTION 37 | E 38 | Exception 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). 6 | The project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) 7 | and [ISO Date Format](https://www.iso.org/iso-8601-date-and-time-format.html). 8 | 9 | ## [Unreleased] 10 | 11 | ### Added 12 | 13 | ### Changed 14 | 15 | ### Fixed 16 | 17 | 18 | ## Version [1.2.1] - 2023-02-03 19 | 20 | ### Fixed 21 | 22 | - Remove dependency on abapGit SHA1 type (due to https://github.com/abapGit/abapGit/pull/6029) 23 | 24 | ## Version [1.2.0] - 2022-12-12 25 | 26 | ### Changed 27 | 28 | - Suppress wall message if repo is not hosted on GitHub 29 | 30 | ### Fixed 31 | 32 | - Fix styling 33 | - Catch errors raised by abaplint app 34 | - Fix jump to function modules with namespace 35 | - Remove duplicate error message 36 | 37 | ## Version [1.1.1] - 2022-10-12 38 | 39 | ### Fixed 40 | 41 | - Removed unnecessary text "[adjust installations]..." from wall message 42 | 43 | ## Version [1.1.0] - 2022-05-18 44 | 45 | ### Fixed 46 | 47 | - Detect conclusions *other* than success, in progress, failed 48 | 49 | ## Version [1.0.0] - 2022-02-01 50 | 51 | Public Release 52 | 53 | 54 | [Unreleased]: https://github.com/Marc-Bernard-Tools/ABAP-Lint-Ext-for-abapGit/compare/1.2.1...main 55 | [1.2.1]: https://github.com/Marc-Bernard-Tools/ABAP-Lint-Ext-for-abapGit/compare/1.2.0...1.2.1 56 | [1.2.0]: https://github.com/Marc-Bernard-Tools/ABAP-Lint-Ext-for-abapGit/compare/1.1.1...1.2.0 57 | [1.1.1]: https://github.com/Marc-Bernard-Tools/ABAP-Lint-Ext-for-abapGit/compare/1.1.0...1.1.1 58 | [1.1.0]: https://github.com/Marc-Bernard-Tools/ABAP-Lint-Ext-for-abapGit/compare/1.0.0...1.1.0 59 | [1.0.0]: https://github.com/Marc-Bernard-Tools/ABAP-Lint-Ext-for-abapGit/releases/tag/1.0.0 60 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_agent.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_ABAPLINT_ABAPGIT_EXT_AGENT 7 | E 8 | abaplint - Extension for abapGit (Agent) 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | CONSTRUCTOR 17 | ZCX_ABAPGIT_EXCEPTION 18 | E 19 | Exception 20 | 21 | 22 | GET_ANNOTATIONS 23 | RI_JSON 24 | E 25 | AJSON reader interface 26 | 27 | 28 | GET_ANNOTATIONS 29 | ZCX_ABAPGIT_AJSON_ERROR 30 | E 31 | AJSON exception 32 | 33 | 34 | GET_ANNOTATIONS 35 | ZCX_ABAPGIT_EXCEPTION 36 | E 37 | Exception 38 | 39 | 40 | GET_CHECK_RUNS 41 | RI_JSON 42 | E 43 | AJSON reader interface 44 | 45 | 46 | GET_CHECK_RUNS 47 | ZCX_ABAPGIT_AJSON_ERROR 48 | E 49 | AJSON exception 50 | 51 | 52 | GET_CHECK_RUNS 53 | ZCX_ABAPGIT_EXCEPTION 54 | E 55 | Exception 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_logo.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_abaplint_abapgit_ext_logo DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC. 5 | 6 | PUBLIC SECTION. 7 | 8 | CONSTANTS c_logo TYPE string VALUE 'abaplint_logo.png'. 9 | 10 | CLASS-METHODS get_logo_mime 11 | RETURNING 12 | VALUE(rv_xdata) TYPE xstring 13 | RAISING 14 | zcx_abapgit_exception. 15 | 16 | CLASS-METHODS get_logo_html 17 | IMPORTING 18 | !iv_title TYPE string OPTIONAL 19 | RETURNING 20 | VALUE(rv_html) TYPE string. 21 | 22 | PRIVATE SECTION. 23 | 24 | CONSTANTS c_mime TYPE string VALUE 'ZABAPLINT_LOGO'. 25 | 26 | ENDCLASS. 27 | 28 | 29 | 30 | CLASS zcl_abaplint_abapgit_ext_logo IMPLEMENTATION. 31 | 32 | 33 | METHOD get_logo_html. 34 | rv_html = 35 | ||. 38 | ENDMETHOD. 39 | 40 | 41 | METHOD get_logo_mime. 42 | 43 | DATA: 44 | ls_key TYPE wwwdatatab, 45 | lv_size_c TYPE wwwparams-value, 46 | lv_size TYPE i, 47 | lt_w3mime TYPE STANDARD TABLE OF w3mime, 48 | ls_w3mime LIKE LINE OF lt_w3mime. 49 | 50 | ls_key-relid = 'MI'. 51 | ls_key-objid = c_mime. 52 | 53 | " Get exact file size 54 | CALL FUNCTION 'WWWPARAMS_READ' 55 | EXPORTING 56 | relid = ls_key-relid 57 | objid = ls_key-objid 58 | name = 'filesize' 59 | IMPORTING 60 | value = lv_size_c 61 | EXCEPTIONS 62 | entry_not_exists = 1. 63 | 64 | IF sy-subrc IS NOT INITIAL. 65 | RETURN. 66 | ENDIF. 67 | 68 | lv_size = lv_size_c. 69 | 70 | " Get binary data 71 | CALL FUNCTION 'WWWDATA_IMPORT' 72 | EXPORTING 73 | key = ls_key 74 | TABLES 75 | mime = lt_w3mime 76 | EXCEPTIONS 77 | wrong_object_type = 1 78 | import_error = 2. 79 | 80 | IF sy-subrc IS NOT INITIAL. 81 | RETURN. 82 | ENDIF. 83 | 84 | LOOP AT lt_w3mime INTO ls_w3mime. 85 | CONCATENATE rv_xdata ls_w3mime-line INTO rv_xdata IN BYTE MODE. 86 | ENDLOOP. 87 | rv_xdata = rv_xdata(lv_size). 88 | 89 | ENDMETHOD. 90 | ENDCLASS. 91 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_issue.clas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZCL_ABAPLINT_ABAPGIT_EXT_ISSUE 7 | E 8 | abaplint - Extension for abapGit (Issue) 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | GET 17 | ZCX_ABAPGIT_EXCEPTION 18 | E 19 | Exception 20 | 21 | 22 | _FOLDER_FOR_REGEX 23 | ZCX_ABAPGIT_EXCEPTION 24 | E 25 | Exception 26 | 27 | 28 | _PARSE 29 | ZCX_ABAPGIT_EXCEPTION 30 | E 31 | Exception 32 | 33 | 34 | _READ_CLASS_INCLUDE 35 | IV_CLSNAME 36 | E 37 | Object Type Name 38 | 39 | 40 | _READ_CLASS_INCLUDE 41 | ZCX_ABAPGIT_EXCEPTION 42 | E 43 | Exception 44 | 45 | 46 | _READ_CLASS_LINE 47 | ET_SOURCE 48 | E 49 | ABAP Source 50 | 51 | 52 | _READ_CLASS_LINE 53 | EV_PROGRAM 54 | E 55 | ABAP Program Name 56 | 57 | 58 | _READ_CLASS_LINE 59 | IV_CLSNAME 60 | E 61 | Object Type Name 62 | 63 | 64 | _READ_CLASS_LINE 65 | ZCX_ABAPGIT_EXCEPTION 66 | E 67 | Exception 68 | 69 | 70 | _READ_PROGRAM 71 | IV_PROGRAM 72 | E 73 | ABAP Program Name 74 | 75 | 76 | _READ_PROGRAM 77 | RT_SOURCE 78 | E 79 | ABAP Source 80 | 81 | 82 | _READ_PROGRAM 83 | ZCX_ABAPGIT_EXCEPTION 84 | E 85 | Exception 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_annot.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_abaplint_abapgit_ext_annot DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC. 5 | 6 | * GitHub REST API for Checks - Annotation 7 | * https://docs.github.com/en/rest/reference/checks 8 | PUBLIC SECTION. 9 | 10 | TYPES: 11 | * Example: 12 | * { 13 | * "path": "src/dev/zcl_abapinst_installer.clas.abap", 14 | * "blob_href": "https://github.com/Marc-Bernard-Tools/ABAP-Installer/blob/ 15 | * 95990d129bf6e29701917804c4d2e9f93a701f2f/src/dev/zcl_abapinst_installer.clas.abap", 16 | * "start_line": 631, 17 | * "start_column": null, 18 | * "end_line": 631, 19 | * "end_column": null, 20 | * "annotation_level": "failure", 21 | * "title": "Not a structure, type unknown, FieldChain", 22 | * "message": "https://rules.abaplint.org/check_syntax", 23 | * "raw_details": null 24 | * } 25 | BEGIN OF ty_annotation, 26 | path TYPE string, 27 | blob_href TYPE string, 28 | start_line TYPE i, 29 | start_column TYPE i, 30 | end_line TYPE i, 31 | end_column TYPE i, 32 | annotation_level TYPE string, 33 | title TYPE string, 34 | message TYPE string, 35 | raw_details TYPE string, 36 | END OF ty_annotation. 37 | TYPES: 38 | ty_annotations TYPE STANDARD TABLE OF ty_annotation WITH DEFAULT KEY. 39 | 40 | METHODS constructor 41 | IMPORTING 42 | !iv_url TYPE string 43 | !iv_check_run TYPE string 44 | RAISING 45 | zcx_abapgit_exception. 46 | METHODS get 47 | RETURNING 48 | VALUE(rt_annotations) TYPE ty_annotations 49 | RAISING 50 | zcx_abapgit_exception. 51 | PROTECTED SECTION. 52 | PRIVATE SECTION. 53 | 54 | DATA mv_url TYPE string . 55 | DATA mv_check_run TYPE string. 56 | 57 | ENDCLASS. 58 | 59 | 60 | 61 | CLASS zcl_abaplint_abapgit_ext_annot IMPLEMENTATION. 62 | 63 | 64 | METHOD constructor. 65 | mv_url = iv_url. 66 | mv_check_run = iv_check_run. 67 | ENDMETHOD. 68 | 69 | 70 | METHOD get. 71 | 72 | DATA: 73 | li_json TYPE REF TO zif_abapgit_ajson, 74 | li_json_anno TYPE REF TO zif_abapgit_ajson, 75 | lx_error TYPE REF TO zcx_abapgit_ajson_error, 76 | lv_msg TYPE string, 77 | lt_anno TYPE TABLE OF string, 78 | lv_anno TYPE string, 79 | ls_annotation TYPE ty_annotation. 80 | 81 | TRY. 82 | li_json = zcl_abaplint_abapgit_ext_agent=>get_instance( mv_url )->get_annotations( mv_check_run ). 83 | 84 | lv_msg = li_json->get( '/message' ). 85 | 86 | IF lv_msg <> ''. 87 | zcx_abapgit_exception=>raise( |Error getting annotations: { lv_msg }| ). 88 | ENDIF. 89 | 90 | lt_anno = li_json->members( '/' ). 91 | 92 | LOOP AT lt_anno INTO lv_anno. 93 | 94 | li_json_anno = li_json->slice( |/{ lv_anno }| ). 95 | li_json_anno->to_abap( IMPORTING ev_container = ls_annotation ). 96 | 97 | INSERT ls_annotation INTO TABLE rt_annotations. 98 | ENDLOOP. 99 | 100 | CATCH zcx_abapgit_ajson_error INTO lx_error. 101 | zcx_abapgit_exception=>raise_with_text( lx_error ). 102 | ENDTRY. 103 | 104 | ENDMETHOD. 105 | ENDCLASS. 106 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Marc Bernard Tools 2 | 3 | Marc Bernard Tools welcomes your suggestions and contributions! Before opening your first issue or pull request, please review our [Code of Conduct](https://github.com/Marc-Bernard-Tools/.github/blob/main/CODE_OF_CONDUCT.md) to understand how our community interacts in an inclusive and respectful manner. 4 | 5 | ## General Advice 6 | 7 | * If you're new and want to help out, see if there are "good first issues" listed [here](../../issues). They should not be complicated to implement but require you to get the project up and running. Or pick something that annoys you. Fix a typo. Improve an error message. Or try something unusual just to see if it works and if it doesn't, open an issue. 8 | 9 | * Before starting any significant development, open an issue and propose your solution first. A discussion can save a lot of unnecessary work. It also helps others know that this is being worked on. 10 | 11 | * It is in your best interest to keep the commits/PRs as small as possible and solve one thing at a time. The smaller your change is, the easier it is to review and it will be more likely to get accepted. 12 | 13 | * Commit often, whenever something is working, and is a step in the right direction do a commit or PR. This way other contributors can see the changes, and it will minimize the risk of merge conflicts. 14 | 15 | * If you don't have the time or knowledge to fix the problem yourself, you can still make it move along faster by providing an accurate description or a repo which reproduces the issue. 16 | 17 | ## Bug Reports 18 | 19 | A bug is a _demonstrable problem_ that is caused by the code in the repository. Good bug reports are extremely helpful - thank you! 20 | 21 | Guidelines for bug reports: 22 | 23 | 1. **Use the GitHub issue search** — check if the issue has already been reported. 24 | 25 | 2. **Check if the issue has been fixed** — try to reproduce it using the latest version or development branch in the repository. 26 | 27 | 3. **Demonstrate the problem** — provide clear steps that can be reproduced. 28 | 29 | A good bug report should not leave others needing to chase you up for more information. Please try to be as detailed as possible in your report. What is your environment? What steps will reproduce the issue? What would you expect to be the outcome? All these details will help to fix any potential bugs. 30 | 31 | ## Development Guidelines 32 | 33 | ### Compatibility 34 | 35 | Marc Bernard Tools are targeted for SAP Basis 7.31 and higher, so the code should only contain expressions and statements that works on 7.31. abaplint will automatically check every pull request for language syntax that is not available on these releases. 36 | 37 | ### Linting 38 | 39 | Pull requests are checked using [abaplint](https://abaplint.org) and must pass all configured [checks](../../abaplint.json) before they can be merged. 40 | 41 | ### Pretty Printer 42 | 43 | Use pretty printer, keywords upper case + indentation. 44 | 45 | ### Prefixing 46 | 47 | Variables are prefixed using the standard setting in [abapOpenChecks](http://docs.abapopenchecks.org/checks/69/) naming conventions. 48 | 49 | ### Internationalization (I18N) 50 | 51 | Currently, Marc Bernard Tools support only English language. Neither objects nor text literals are translated. Therefore, all objects shall be set to English as the original language. Text literals in the code shall be maintained in English. 52 | 53 | ## Contribution Licensing 54 | 55 | Most of our code is distributed under the terms of the [license](LICENSE), and when you contribute code that you wrote to our repositories, you agree that you are contributing under those same terms. In addition, by submitting your contributions you are indicating that you have the right to submit those contributions under those terms. 56 | 57 | If you wish to contribute code or documentation *authored by others*, or using the terms of any other license, please indicate that clearly in your pull request so that the project team can discuss the situation with you. 58 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_agent.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_abaplint_abapgit_ext_agent DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PRIVATE. 5 | 6 | " Calling Github API for check runs and annotations 7 | " https://docs.github.com/en/rest/reference/checks 8 | PUBLIC SECTION. 9 | 10 | CONSTANTS c_github_api_version TYPE string VALUE '2022-11-28'. 11 | 12 | " Maximum number of annotations available by API without paging 13 | CONSTANTS c_max_annotations TYPE i VALUE 50. 14 | 15 | CLASS-METHODS get_instance 16 | IMPORTING 17 | !iv_url TYPE string 18 | RETURNING 19 | VALUE(ro_instance) TYPE REF TO zcl_abaplint_abapgit_ext_agent 20 | RAISING 21 | zcx_abapgit_exception. 22 | METHODS constructor 23 | IMPORTING 24 | !iv_url TYPE string 25 | RAISING 26 | zcx_abapgit_exception. 27 | METHODS get_annotations 28 | IMPORTING 29 | !iv_check_run TYPE string 30 | RETURNING 31 | VALUE(ri_json) TYPE REF TO zif_abapgit_ajson 32 | RAISING 33 | zcx_abapgit_exception 34 | zcx_abapgit_ajson_error. 35 | METHODS get_check_runs 36 | IMPORTING 37 | !iv_commit TYPE zif_abaplint_abapgit_ext=>ty_sha1 38 | RETURNING 39 | VALUE(ri_json) TYPE REF TO zif_abapgit_ajson 40 | RAISING 41 | zcx_abapgit_exception 42 | zcx_abapgit_ajson_error. 43 | PROTECTED SECTION. 44 | PRIVATE SECTION. 45 | 46 | TYPES: 47 | BEGIN OF ty_instance, 48 | url TYPE string, 49 | instanace TYPE REF TO zcl_abaplint_abapgit_ext_agent, 50 | END OF ty_instance . 51 | 52 | CLASS-DATA: 53 | gt_instance TYPE HASHED TABLE OF ty_instance WITH UNIQUE KEY url . 54 | DATA mv_url TYPE string . 55 | DATA mo_agent TYPE REF TO zif_abapgit_http_agent . 56 | ENDCLASS. 57 | 58 | 59 | 60 | CLASS zcl_abaplint_abapgit_ext_agent IMPLEMENTATION. 61 | 62 | 63 | METHOD constructor. 64 | 65 | IF iv_url NS 'github.com'. 66 | zcx_abapgit_exception=>raise( 'abaplint Extension for abapGit only works with Github.com' ). 67 | ENDIF. 68 | 69 | mv_url = replace( 70 | val = iv_url 71 | sub = 'github.com' 72 | with = 'api.github.com/repos' ). 73 | 74 | mv_url = replace( 75 | val = mv_url 76 | regex = '\.git$' 77 | with = '' ). 78 | 79 | mo_agent = zcl_abapgit_factory=>get_http_agent( ). 80 | 81 | mo_agent->global_headers( )->set( 82 | iv_key = 'Accept' 83 | iv_val = 'application/vnd.github.v3+json' ). 84 | 85 | mo_agent->global_headers( )->set( 86 | iv_key = 'X-GitHub-Api-Version' 87 | iv_val = c_github_api_version ). 88 | 89 | " Get auth token from repo 90 | IF zcl_abapgit_login_manager=>get( iv_url ) IS NOT INITIAL. 91 | mo_agent->global_headers( )->set( 92 | iv_key = 'Authorization' 93 | iv_val = zcl_abapgit_login_manager=>get( iv_url ) ). 94 | ENDIF. 95 | 96 | ENDMETHOD. 97 | 98 | 99 | METHOD get_annotations. 100 | 101 | DATA lv_url TYPE string. 102 | 103 | " Get first 50 annotations which is the current max before paging (default = 30) 104 | lv_url = mv_url && |/check-runs/{ iv_check_run }/annotations?per_page={ c_max_annotations }|. 105 | 106 | ri_json = mo_agent->request( lv_url )->json( ). 107 | 108 | ENDMETHOD. 109 | 110 | 111 | METHOD get_check_runs. 112 | 113 | DATA lv_url TYPE string. 114 | 115 | lv_url = mv_url && |/commits/{ iv_commit }/check-runs|. 116 | 117 | ri_json = mo_agent->request( lv_url )->json( ). 118 | 119 | ENDMETHOD. 120 | 121 | 122 | METHOD get_instance. 123 | 124 | DATA ls_instance LIKE LINE OF gt_instance. 125 | 126 | READ TABLE gt_instance INTO ls_instance WITH TABLE KEY url = iv_url. 127 | IF sy-subrc = 0. 128 | ro_instance = ls_instance-instanace. 129 | ELSE. 130 | CREATE OBJECT ro_instance 131 | EXPORTING 132 | iv_url = iv_url. 133 | 134 | ls_instance-url = iv_url. 135 | ls_instance-instanace = ro_instance. 136 | INSERT ls_instance INTO TABLE gt_instance. 137 | ENDIF. 138 | 139 | ENDMETHOD. 140 | ENDCLASS. 141 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_chkrn.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_abaplint_abapgit_ext_chkrn DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | * GitHub REST API for Checks - Check Run 7 | * https://docs.github.com/en/rest/reference/checks 8 | PUBLIC SECTION. 9 | 10 | TYPES: 11 | BEGIN OF ty_check_run, 12 | app TYPE string, 13 | status TYPE string, 14 | conclusion TYPE string, 15 | name TYPE string, 16 | id TYPE string, 17 | url TYPE string, 18 | summary TYPE string, 19 | count_shown TYPE i, 20 | count_total TYPE i, 21 | END OF ty_check_run. 22 | 23 | METHODS constructor 24 | IMPORTING 25 | !iv_url TYPE string 26 | !iv_commit TYPE zif_abaplint_abapgit_ext=>ty_sha1 27 | RAISING 28 | zcx_abapgit_exception . 29 | METHODS get 30 | RETURNING 31 | VALUE(rs_check_run) TYPE ty_check_run 32 | RAISING 33 | zcx_abapgit_exception . 34 | PROTECTED SECTION. 35 | PRIVATE SECTION. 36 | 37 | DATA mv_url TYPE string . 38 | DATA mv_commit TYPE zif_abaplint_abapgit_ext=>ty_sha1 . 39 | 40 | ENDCLASS. 41 | 42 | 43 | 44 | CLASS zcl_abaplint_abapgit_ext_chkrn IMPLEMENTATION. 45 | 46 | 47 | METHOD constructor. 48 | mv_url = iv_url. 49 | mv_commit = iv_commit. 50 | ENDMETHOD. 51 | 52 | 53 | METHOD get. 54 | 55 | DATA: 56 | li_json TYPE REF TO zif_abapgit_ajson, 57 | lx_error TYPE REF TO zcx_abapgit_ajson_error, 58 | lt_check_runs TYPE TABLE OF string, 59 | lv_check_run TYPE string, 60 | lv_msg TYPE string, 61 | lv_count TYPE string, 62 | lv_app TYPE string, 63 | lv_name TYPE string. 64 | 65 | TRY. 66 | li_json = zcl_abaplint_abapgit_ext_agent=>get_instance( mv_url )->get_check_runs( mv_commit ). 67 | 68 | lv_msg = li_json->get( '/message' ). 69 | 70 | IF lv_msg <> ''. 71 | zcx_abapgit_exception=>raise( |Error getting check runs: { lv_msg }| ). 72 | ENDIF. 73 | 74 | lt_check_runs = li_json->members( '/check_runs' ). 75 | 76 | LOOP AT lt_check_runs INTO lv_check_run. 77 | 78 | lv_app = li_json->get( |/check_runs/{ lv_check_run }/app/name| ). 79 | lv_name = li_json->get( |/check_runs/{ lv_check_run }/name| ). 80 | 81 | " Only interested in abaplint run (not builds or abalint/observations) 82 | IF lv_app = 'abaplint' AND lv_name = 'abaplint'. 83 | 84 | rs_check_run-app = lv_app. 85 | rs_check_run-name = lv_name. 86 | rs_check_run-id = li_json->get( |/check_runs/{ lv_check_run }/id| ). 87 | rs_check_run-status = li_json->get( |/check_runs/{ lv_check_run }/status| ). 88 | rs_check_run-conclusion = li_json->get( |/check_runs/{ lv_check_run }/conclusion| ). 89 | rs_check_run-url = li_json->get( |/check_runs/{ lv_check_run }/html_url| ). 90 | rs_check_run-summary = li_json->get( |/check_runs/{ lv_check_run }/output/summary| ). 91 | rs_check_run-count_shown = li_json->get( |/check_runs/{ lv_check_run }/output/annotation_count| ). 92 | 93 | IF rs_check_run-summary CS 'Error'. 94 | zcx_abapgit_exception=>raise( rs_check_run-summary ). 95 | ENDIF. 96 | 97 | SPLIT rs_check_run-summary AT space INTO lv_count lv_msg. 98 | rs_check_run-count_total = lv_count. 99 | 100 | REPLACE ALL OCCURRENCES OF 101 | cl_abap_char_utilities=>newline && cl_abap_char_utilities=>newline 102 | IN rs_check_run-summary WITH `, `. 103 | 104 | " Remove link to https://github.com/apps/abaplint/installations/new 105 | REPLACE REGEX ', \[adjust installations\].*' IN rs_check_run-summary WITH ''. 106 | 107 | EXIT. 108 | 109 | ENDIF. 110 | 111 | ENDLOOP. 112 | 113 | CATCH zcx_abapgit_ajson_error INTO lx_error. 114 | zcx_abapgit_exception=>raise_with_text( lx_error ). 115 | ENDTRY. 116 | 117 | ENDMETHOD. 118 | ENDCLASS. 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Version](https://img.shields.io/endpoint?url=https://shield.abappm.com/github/Marc-Bernard-Tools/abaplint-Ext-for-abapGit/src/zif_abaplint_abapgit_ext.intf.abap/c_version&label=Version&color=blue) 2 | 3 | [![License](https://img.shields.io/github/license/Marc-Bernard-Tools/abaplint-Ext-for-abapGit?label=License&color=success)](LICENSE) 4 | [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg?color=success)](https://github.com/Marc-Bernard-Tools/.github/blob/main/CODE_OF_CONDUCT.md) 5 | [![REUSE Status](https://api.reuse.software/badge/github.com/Marc-Bernard-Tools/abaplint-Ext-for-abapGit)](https://api.reuse.software/info/github.com/Marc-Bernard-Tools/abaplint-Ext-for-abapGit) 6 | [![ClearlyDefined Score](https://img.shields.io/clearlydefined/score/git/github/marc-bernard-tools/abap-lint-ext-for-abapgit/e7046746c18809e14f129c1644b2c2bf537e58ac?label=ClearlyDefined%20Score)](https://clearlydefined.io/definitions/git/github/marc-bernard-tools/abap-lint-ext-for-abapgit/e7046746c18809e14f129c1644b2c2bf537e58ac) 7 | 8 | # abaplint Extension for abapGit 9 | 10 | View [abaplint](https://abaplint.org/) results and detailed findings directly in [abapGit](https://github.com/abapGit/abapGit). 11 | 12 | Made by [Marc Bernard Tools](https://marcbernardtools.com/) giving back to the [SAP Community](https://community.sap.com/). 13 | 14 | NO WARRANTIES, [MIT License](LICENSE) 15 | 16 | ## The Problem 17 | 18 | After committing changes from abapGit to your repository and running abaplint there, you have to switch to GitHub or another tool to view the abaplint results. If the abaplint check fails, the detailed findings are hard to process since they don't link back to your SAP system where you want to fix the issues. 19 | 20 | ![github2](img/github_2.png) 21 | 22 | Note: VSCode with [abaplint extension](https://marketplace.visualstudio.com/items?itemName=larshp.vscode-abaplint) is an exception showing lint results within your ABAP code. But then you are not using abapGit in the first place. 23 | 24 | ## The Solution 25 | 26 | This repository provides an extension for abapGit integrating the abaplint results (as [user exits](https://docs.abapgit.org/ref-exits.html)). A summary of the results is displayed in the abapGit repository view and details are shown on a separate page with a code preview and an option to jump directly to the code in question. 27 | 28 | ### Repository View 29 | 30 | Under the name of the repository, the status and summary of the last abaplint check will be displayed. 31 | 32 | ![check1](img/check_success.png) 33 | 34 | ![check2](img/check_in_progress.png) 35 | 36 | ![check3](img/check_failure.png) 37 | 38 | You can click on the status icon to open the corresponding page on GitHub. If you click on the result summary, the detailed issues will be shown. 39 | 40 | ### Issue View 41 | 42 | The issues are listed similarly to syntax and ATC checks in abapGit. For each finding, the view shows the object type, name, and line number. Below, it prints the abaplint message. A link on the error code opens the corresponding definition on [rules.abaplint.org](https://rules.abaplint.org/). 43 | 44 | ![findings1](img/findings_error_1.png) 45 | 46 | Optionally, you can sort the results by object, location, or error code. You can also hide the source code preview. 47 | 48 | ![findings1](img/findings_error_2.png) 49 | 50 | ## Installation 51 | 52 | ### Prerequisites 53 | 54 | 1. SAP Basis 7.02 or higher 55 | 56 | 2. abapGit needs to be installed 57 | 58 | 3. abaplint must be installed and given access to your GitHub repository. 59 | 60 | - Install abaplint 61 | 62 | https://github.com/apps/abaplint/installations/new 63 | 64 | - Give abaplint access to your repos 65 | 66 | https://github.com/settings/installations 67 | 68 | - Add abaplint.json to your repo 69 | 70 | Get the latest default from [schema.abapgit.org](https://schema.abaplint.org/default.json) 71 | 72 | ### Repository 73 | 74 | You can install the repository using [abapGit](https://github.com/abapGit/abapGit) creating a new online repository for https://github.com/Marc-Bernard-Tools/ABAP-Lint-Ext-for-abapGit. We recommend using package `$ABAPGIT-EXT-ABAPLINT`. 75 | 76 | ### User Exits 77 | 78 | Implement abapGit [user exits](https://docs.abapgit.org/ref-exits.html) [`wall_message_repo`](https://docs.abapgit.org/ref-exits.html#wall_message_repo) and [`on_event`](https://docs.abapgit.org/ref-exits.html#on_event) as follows: 79 | 80 | ```abap 81 | METHOD zif_abapgit_exit~wall_message_repo. 82 | 83 | zcl_abaplint_abapgit_ext_exit=>get_instance( )->wall_message_repo( 84 | is_repo_meta = is_repo_meta 85 | ii_html = ii_html ). 86 | 87 | ENDMETHOD. 88 | ``` 89 | 90 | ```abap 91 | METHOD zif_abapgit_exit~on_event. 92 | 93 | IF rs_handled IS INITIAL. 94 | rs_handled = zcl_abaplint_abapgit_ext_exit=>get_instance( )->on_event( ii_event ). 95 | ENDIF. 96 | 97 | ENDMETHOD. 98 | ``` 99 | 100 | ### SSL and Certificates 101 | 102 | The abaplint status is retrieved via `https://api.github.com/`. Therefore, a proper SSL configuration and certificates for `api.github.com` are required. See [SSL setup](https://docs.abapgit.org/guide-ssl-setup.html) for details. 103 | 104 | ## Contributions 105 | 106 | All contributions are welcome! Read our [Contribution Guidelines](CONTRIBUTING.md), fork this repo, and create a pull request. 107 | 108 | ## About 109 | 110 | Made with ❤️ in Canada 111 | 112 | Copyright 2025 Marc Bernard 113 | 114 | Follow [@marcf.be](https://bsky.app/profile/marcf.be) on Bluesky and [@marcfbe](https://linkedin.com/in/marcfbe) on LinkedIn 115 | 116 |

MBT Logo

117 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_exit.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_abaplint_abapgit_ext_exit DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PRIVATE. 5 | 6 | PUBLIC SECTION. 7 | 8 | CLASS-METHODS get_instance 9 | RETURNING 10 | VALUE(ro_instance) TYPE REF TO zcl_abaplint_abapgit_ext_exit. 11 | METHODS on_event 12 | IMPORTING 13 | !ii_event TYPE REF TO zif_abapgit_gui_event 14 | RETURNING 15 | VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result 16 | RAISING 17 | zcx_abapgit_exception. 18 | METHODS wall_message_repo 19 | IMPORTING 20 | !is_repo_meta TYPE zif_abapgit_persistence=>ty_repo 21 | !ii_html TYPE REF TO zif_abapgit_html. 22 | METHODS get_last_url 23 | RETURNING 24 | VALUE(rv_url) TYPE string. 25 | PROTECTED SECTION. 26 | PRIVATE SECTION. 27 | 28 | TYPES: 29 | BEGIN OF ty_wall, 30 | commit TYPE string, 31 | html TYPE REF TO zif_abapgit_html, 32 | url TYPE string, 33 | END OF ty_wall. 34 | 35 | CONSTANTS: 36 | BEGIN OF c_action, 37 | go_abaplint TYPE string VALUE 'go_abaplint', 38 | END OF c_action. 39 | CONSTANTS: 40 | BEGIN OF c_git_status, 41 | queued TYPE string VALUE 'queued', 42 | in_progress TYPE string VALUE 'in_progress', 43 | completed TYPE string VALUE 'completed', 44 | END OF c_git_status. 45 | CONSTANTS: 46 | BEGIN OF c_git_conclusion, 47 | neutral TYPE string VALUE 'neutral', 48 | success TYPE string VALUE 'success', 49 | failure TYPE string VALUE 'failure', 50 | action_required TYPE string VALUE 'action_required', 51 | cancelled TYPE string VALUE 'cancelled', 52 | skipped TYPE string VALUE 'skipped', 53 | stale TYPE string VALUE 'stale', 54 | timed_out TYPE string VALUE 'timed_out', 55 | END OF c_git_conclusion. 56 | CLASS-DATA go_instance TYPE REF TO zcl_abaplint_abapgit_ext_exit. 57 | DATA: 58 | mt_wall TYPE HASHED TABLE OF ty_wall WITH UNIQUE KEY commit. 59 | DATA mv_last_url TYPE string. 60 | 61 | METHODS _wall_message_abaplint 62 | IMPORTING 63 | !iv_key TYPE zif_abapgit_persistence=>ty_repo-key 64 | !is_check_run TYPE zcl_abaplint_abapgit_ext_chkrn=>ty_check_run 65 | RETURNING 66 | VALUE(ri_html) TYPE REF TO zif_abapgit_html. 67 | ENDCLASS. 68 | 69 | 70 | 71 | CLASS zcl_abaplint_abapgit_ext_exit IMPLEMENTATION. 72 | 73 | 74 | METHOD get_instance. 75 | IF go_instance IS INITIAL. 76 | CREATE OBJECT go_instance. 77 | ENDIF. 78 | ro_instance = go_instance. 79 | ENDMETHOD. 80 | 81 | 82 | METHOD get_last_url. 83 | rv_url = mv_last_url. 84 | ENDMETHOD. 85 | 86 | 87 | METHOD on_event. 88 | 89 | IF ii_event->mv_action = c_action-go_abaplint. 90 | rs_handled-page = zcl_abaplint_abapgit_ext_ui=>create( 91 | iv_key = |{ ii_event->query( )->get( 'KEY' ) }| 92 | iv_check_run = |{ ii_event->query( )->get( 'CHECKRUN' ) }| 93 | iv_count_total = |{ ii_event->query( )->get( 'TOTAL' ) }| ). 94 | rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. 95 | ENDIF. 96 | 97 | ENDMETHOD. 98 | 99 | 100 | METHOD wall_message_repo. 101 | 102 | DATA: 103 | lx_error TYPE REF TO zcx_abapgit_exception, 104 | lo_repo_online TYPE REF TO zcl_abapgit_repo_online, 105 | lv_commit TYPE zif_abaplint_abapgit_ext=>ty_sha1, 106 | ls_wall TYPE ty_wall, 107 | lo_check_run TYPE REF TO zcl_abaplint_abapgit_ext_chkrn, 108 | ls_check_run TYPE zcl_abaplint_abapgit_ext_chkrn=>ty_check_run, 109 | li_html TYPE REF TO zif_abapgit_html. 110 | 111 | IF is_repo_meta-offline = abap_true. 112 | RETURN. 113 | ENDIF. 114 | 115 | TRY. 116 | lo_repo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( is_repo_meta-key ). 117 | 118 | lv_commit = lo_repo_online->get_current_remote( ). 119 | 120 | CATCH zcx_abapgit_exception. 121 | " If this fails, AG will show an error on the repo view anyway 122 | RETURN. 123 | ENDTRY. 124 | 125 | " abaplint is only available on GitHub 126 | IF lo_repo_online->get_url( ) NS 'github.com'. 127 | RETURN. 128 | ENDIF. 129 | 130 | READ TABLE mt_wall INTO ls_wall WITH TABLE KEY commit = lv_commit. 131 | IF sy-subrc <> 0. 132 | 133 | TRY. 134 | CREATE OBJECT lo_check_run 135 | EXPORTING 136 | iv_url = is_repo_meta-url 137 | iv_commit = lv_commit. 138 | 139 | ls_check_run = lo_check_run->get( ). 140 | 141 | IF ls_check_run IS INITIAL. 142 | RETURN. 143 | ENDIF. 144 | 145 | CATCH zcx_abapgit_exception INTO lx_error. 146 | ii_html->add( |
{ lx_error->get_text( ) }
| ). 147 | RETURN. 148 | ENDTRY. 149 | 150 | li_html = _wall_message_abaplint( 151 | iv_key = is_repo_meta-key 152 | is_check_run = ls_check_run ). 153 | 154 | ls_wall-commit = lv_commit. 155 | ls_wall-html = li_html. 156 | ls_wall-url = ls_check_run-url. 157 | 158 | " Cache result of completed checkruns (others might change) 159 | IF ls_check_run-status = c_git_status-completed. 160 | INSERT ls_wall INTO TABLE mt_wall. 161 | ENDIF. 162 | 163 | ENDIF. 164 | 165 | ii_html->add( ls_wall-html->render( ) ). 166 | 167 | " Remember URL of last shown check run 168 | mv_last_url = ls_wall-url. 169 | 170 | ENDMETHOD. 171 | 172 | 173 | METHOD _wall_message_abaplint. 174 | 175 | DATA: 176 | lv_style TYPE string, 177 | lv_act TYPE string, 178 | lv_msg TYPE string, 179 | lv_summary TYPE string. 180 | 181 | lv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ is_check_run-url }|. 182 | 183 | CREATE OBJECT ri_html TYPE zcl_abapgit_html. 184 | 185 | lv_style = 'padding-right: 10px; margin-top: 10px; float: left;'. 186 | 187 | ri_html->add( |
| ). 188 | 189 | CASE is_check_run-status. 190 | WHEN c_git_status-queued. 191 | ri_html->add_a( 192 | iv_txt = zcl_abapgit_html=>icon( 193 | iv_name = 'circle-solid' 194 | iv_hint = is_check_run-status ) 195 | iv_act = lv_act ). 196 | WHEN c_git_status-in_progress. 197 | ri_html->add_a( 198 | iv_txt = zcl_abapgit_html=>icon( 199 | iv_name = 'circle-solid' 200 | iv_class = 'warning' 201 | iv_hint = is_check_run-status ) 202 | iv_act = lv_act ). 203 | WHEN c_git_status-completed. 204 | CASE is_check_run-conclusion. 205 | WHEN c_git_conclusion-neutral. 206 | ri_html->add_a( 207 | iv_txt = zcl_abapgit_html=>icon( 208 | iv_name = 'circle-solid' 209 | iv_hint = is_check_run-conclusion ) 210 | iv_act = lv_act ). 211 | WHEN c_git_conclusion-success. 212 | ri_html->add_a( 213 | iv_txt = zcl_abapgit_html=>icon( 214 | iv_name = 'check' 215 | iv_class = 'success' 216 | iv_hint = is_check_run-conclusion ) 217 | iv_act = lv_act ). 218 | WHEN c_git_conclusion-failure 219 | OR c_git_conclusion-action_required 220 | OR c_git_conclusion-cancelled 221 | OR c_git_conclusion-skipped 222 | OR c_git_conclusion-stale 223 | OR c_git_conclusion-timed_out. 224 | ri_html->add_a( 225 | iv_txt = zcl_abapgit_html=>icon( 226 | iv_name = 'times-solid' 227 | iv_class = 'error' 228 | iv_hint = is_check_run-conclusion ) 229 | iv_act = lv_act ). 230 | WHEN OTHERS. 231 | ri_html->add( |Unexpected value "{ is_check_run-conclusion }" for "conclusion"| ). 232 | ENDCASE. 233 | WHEN OTHERS. 234 | ri_html->add( |Unexpected value "{ is_check_run-status }" for "status"| ). 235 | ENDCASE. 236 | 237 | lv_msg = is_check_run-name. 238 | IF lv_msg <> is_check_run-app. 239 | lv_msg = |{ is_check_run-app } - { is_check_run-name }|. 240 | ENDIF. 241 | 242 | lv_summary = is_check_run-summary. 243 | IF lv_summary IS NOT INITIAL. 244 | REPLACE 'First 50 annotations shown, ' IN lv_summary WITH ''. 245 | 246 | lv_act = |{ c_action-go_abaplint }?| && 247 | |key={ iv_key }&checkrun={ is_check_run-id }&total={ is_check_run-count_total }|. 248 | 249 | " todo, maybe better to show link only for failures 250 | lv_summary = ri_html->a( 251 | iv_txt = lv_summary 252 | iv_act = lv_act ). 253 | 254 | lv_msg = |{ lv_msg }: { lv_summary }|. 255 | ENDIF. 256 | 257 | ri_html->add( lv_msg ). 258 | ri_html->add( '
' ). 259 | 260 | ENDMETHOD. 261 | ENDCLASS. 262 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_issue.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_abaplint_abapgit_ext_issue DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | * Derive abapGit issue from abaplint annotation 7 | PUBLIC SECTION. 8 | 9 | TYPES: 10 | BEGIN OF ty_issue, 11 | obj_type TYPE tadir-object, 12 | obj_name TYPE tadir-obj_name, 13 | obj_subtype TYPE string, 14 | extension TYPE string, 15 | program TYPE progname, 16 | line TYPE i, 17 | source TYPE rswsourcet, 18 | level TYPE string, 19 | title TYPE string, 20 | url TYPE string, 21 | END OF ty_issue . 22 | TYPES: 23 | ty_issues TYPE STANDARD TABLE OF ty_issue WITH DEFAULT KEY . 24 | 25 | METHODS constructor 26 | IMPORTING 27 | !is_annotation TYPE zcl_abaplint_abapgit_ext_annot=>ty_annotation OPTIONAL 28 | !iv_issue TYPE string OPTIONAL 29 | !iv_folder TYPE string DEFAULT '/src/' 30 | RAISING 31 | zcx_abapgit_exception . 32 | METHODS get 33 | RETURNING 34 | VALUE(rs_issue) TYPE ty_issue 35 | RAISING 36 | zcx_abapgit_exception . 37 | PROTECTED SECTION. 38 | PRIVATE SECTION. 39 | 40 | TYPES: 41 | ty_functab TYPE STANDARD TABLE OF rs38l_incl WITH DEFAULT KEY . 42 | 43 | CONSTANTS: 44 | c_active TYPE c LENGTH 1 VALUE 'A' ##NO_TEXT. 45 | DATA mv_folder TYPE string . 46 | DATA mv_issue TYPE string . 47 | DATA ms_issue TYPE ty_issue . 48 | DATA ms_annotation TYPE zcl_abaplint_abapgit_ext_annot=>ty_annotation . 49 | 50 | METHODS _folder_for_regex 51 | IMPORTING 52 | !iv_folder TYPE string 53 | RETURNING 54 | VALUE(rv_folder) TYPE string 55 | RAISING 56 | zcx_abapgit_exception . 57 | METHODS _get_issue_clas 58 | IMPORTING 59 | !is_issue TYPE ty_issue 60 | RETURNING 61 | VALUE(rs_issue) TYPE ty_issue 62 | RAISING 63 | zcx_abapgit_exception . 64 | METHODS _get_issue_intf 65 | IMPORTING 66 | !is_issue TYPE ty_issue 67 | RETURNING 68 | VALUE(rs_issue) TYPE ty_issue 69 | RAISING 70 | zcx_abapgit_exception . 71 | METHODS _get_issue_prog 72 | IMPORTING 73 | !is_issue TYPE ty_issue 74 | RETURNING 75 | VALUE(rs_issue) TYPE ty_issue 76 | RAISING 77 | zcx_abapgit_exception . 78 | METHODS _get_issue_fugr 79 | IMPORTING 80 | !is_issue TYPE ty_issue 81 | RETURNING 82 | VALUE(rs_issue) TYPE ty_issue 83 | RAISING 84 | zcx_abapgit_exception . 85 | METHODS _get_issue_type 86 | IMPORTING 87 | !is_issue TYPE ty_issue 88 | RETURNING 89 | VALUE(rs_issue) TYPE ty_issue 90 | RAISING 91 | zcx_abapgit_exception . 92 | METHODS _parse 93 | IMPORTING 94 | !iv_issue TYPE string 95 | RETURNING 96 | VALUE(rs_issue) TYPE ty_issue 97 | RAISING 98 | zcx_abapgit_exception . 99 | METHODS _read_class_line 100 | IMPORTING 101 | !iv_clsname TYPE seoclsname 102 | !iv_line TYPE i 103 | EXPORTING 104 | !et_source TYPE rswsourcet 105 | !ev_program TYPE progname 106 | !ev_line TYPE i 107 | RAISING 108 | zcx_abapgit_exception . 109 | METHODS _read_class_include 110 | IMPORTING 111 | !iv_clsname TYPE seoclsname 112 | !iv_clspart TYPE seop_include_ext_app 113 | RETURNING 114 | VALUE(rv_program) TYPE progname 115 | RAISING 116 | zcx_abapgit_exception . 117 | METHODS _read_functions 118 | IMPORTING 119 | !iv_area TYPE rs38l_area 120 | RETURNING 121 | VALUE(rt_functab) TYPE ty_functab 122 | RAISING 123 | zcx_abapgit_exception . 124 | METHODS _read_program 125 | IMPORTING 126 | !iv_program TYPE progname 127 | RETURNING 128 | VALUE(rt_source) TYPE rswsourcet 129 | RAISING 130 | zcx_abapgit_exception . 131 | ENDCLASS. 132 | 133 | 134 | 135 | CLASS zcl_abaplint_abapgit_ext_issue IMPLEMENTATION. 136 | 137 | 138 | METHOD constructor. 139 | 140 | IF iv_issue IS INITIAL AND is_annotation IS INITIAL. 141 | zcx_abapgit_exception=>raise( 'Neither issue nor annotation supplied' ). 142 | ENDIF. 143 | 144 | ms_annotation = is_annotation. 145 | 146 | IF iv_issue IS INITIAL. 147 | mv_issue = to_upper( |{ ms_annotation-start_line } in { ms_annotation-path }| ). 148 | ELSE. 149 | mv_issue = to_upper( iv_issue ). 150 | ENDIF. 151 | 152 | ms_issue = _parse( mv_issue ). 153 | ms_issue-level = ms_annotation-annotation_level. 154 | ms_issue-title = ms_annotation-title. 155 | ms_issue-url = ms_annotation-message. 156 | 157 | mv_folder = _folder_for_regex( iv_folder ). 158 | 159 | ENDMETHOD. 160 | 161 | 162 | METHOD get. 163 | 164 | CASE ms_issue-obj_type. 165 | WHEN 'CLAS'. 166 | rs_issue = _get_issue_clas( ms_issue ). 167 | WHEN 'INTF'. 168 | rs_issue = _get_issue_intf( ms_issue ). 169 | WHEN 'PROG'. 170 | rs_issue = _get_issue_prog( ms_issue ). 171 | WHEN 'FUGR'. 172 | rs_issue = _get_issue_fugr( ms_issue ). 173 | WHEN 'TYPE'. 174 | rs_issue = _get_issue_type( ms_issue ). 175 | WHEN OTHERS. 176 | MOVE-CORRESPONDING ms_issue TO rs_issue. 177 | ENDCASE. 178 | 179 | IF rs_issue-extension = 'XML'. 180 | CLEAR rs_issue-source. 181 | ENDIF. 182 | 183 | ENDMETHOD. 184 | 185 | 186 | METHOD _folder_for_regex. 187 | 188 | IF strlen( iv_folder ) < 1. 189 | zcx_abapgit_exception=>raise( 'Missing starting folder' ). 190 | ENDIF. 191 | 192 | rv_folder = replace( 193 | val = to_upper( iv_folder+1 ) 194 | sub = '/' 195 | with = '\/' ). 196 | 197 | ENDMETHOD. 198 | 199 | 200 | METHOD _get_issue_clas. 201 | 202 | MOVE-CORRESPONDING is_issue TO rs_issue. 203 | 204 | CASE to_lower( is_issue-obj_subtype ). 205 | WHEN zif_abapgit_oo_object_fnc=>c_parts-locals_def. 206 | rs_issue-program = _read_class_include( 207 | iv_clsname = |{ is_issue-obj_name }| 208 | iv_clspart = seop_ext_class_locals_def ). 209 | WHEN zif_abapgit_oo_object_fnc=>c_parts-locals_imp. 210 | rs_issue-program = _read_class_include( 211 | iv_clsname = |{ is_issue-obj_name }| 212 | iv_clspart = seop_ext_class_locals_imp ). 213 | WHEN zif_abapgit_oo_object_fnc=>c_parts-macros. 214 | rs_issue-program = _read_class_include( 215 | iv_clsname = |{ is_issue-obj_name }| 216 | iv_clspart = seop_ext_class_macros ). 217 | WHEN zif_abapgit_oo_object_fnc=>c_parts-testclasses. 218 | rs_issue-program = _read_class_include( 219 | iv_clsname = |{ is_issue-obj_name }| 220 | iv_clspart = seop_ext_class_testclasses ). 221 | WHEN OTHERS. 222 | _read_class_line( 223 | EXPORTING 224 | iv_clsname = |{ is_issue-obj_name }| 225 | iv_line = is_issue-line 226 | IMPORTING 227 | ev_program = rs_issue-program 228 | ev_line = rs_issue-line ). 229 | ENDCASE. 230 | 231 | IF rs_issue-program IS INITIAL. 232 | rs_issue-program = cl_oo_classname_service=>get_classpool_name( |{ is_issue-obj_name }| ). 233 | ENDIF. 234 | 235 | rs_issue-source = _read_program( rs_issue-program ). 236 | 237 | ENDMETHOD. 238 | 239 | 240 | METHOD _get_issue_fugr. 241 | 242 | DATA: 243 | lt_functab TYPE ty_functab, 244 | lv_namespace TYPE rs38l-namespace, 245 | lv_complete_area TYPE rs38l-area, 246 | lv_area TYPE rs38l-area. 247 | 248 | FIELD-SYMBOLS TYPE LINE OF ty_functab. 249 | 250 | MOVE-CORRESPONDING is_issue TO rs_issue. 251 | 252 | lt_functab = _read_functions( |{ is_issue-obj_name }| ). 253 | 254 | READ TABLE lt_functab ASSIGNING WITH KEY funcname = is_issue-obj_subtype. 255 | IF sy-subrc = 0. 256 | rs_issue-program = -include. 257 | ELSE. 258 | rs_issue-program = is_issue-obj_subtype. 259 | ENDIF. 260 | 261 | IF rs_issue-program IS INITIAL. 262 | lv_complete_area = |{ is_issue-obj_name }|. 263 | CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' 264 | EXPORTING 265 | complete_area = lv_complete_area 266 | IMPORTING 267 | namespace = lv_namespace 268 | group = lv_area 269 | EXCEPTIONS 270 | include_not_exists = 1 271 | group_not_exists = 2 272 | no_selections = 3 273 | no_function_include = 4 274 | no_function_pool = 5 275 | delimiter_wrong_position = 6 276 | no_customer_function_group = 7 277 | no_customer_function_include = 8 278 | reserved_name_customer = 9 279 | namespace_too_long = 10 280 | area_length_error = 11 281 | OTHERS = 12. 282 | CONCATENATE lv_namespace 'SAPL' lv_area INTO rs_issue-program. 283 | ENDIF. 284 | 285 | rs_issue-source = _read_program( rs_issue-program ). 286 | 287 | ENDMETHOD. 288 | 289 | 290 | METHOD _get_issue_intf. 291 | 292 | MOVE-CORRESPONDING is_issue TO rs_issue. 293 | 294 | rs_issue-program = cl_oo_classname_service=>get_intfsec_name( |{ is_issue-obj_name }| ). 295 | rs_issue-source = _read_program( rs_issue-program ). 296 | 297 | ENDMETHOD. 298 | 299 | 300 | METHOD _get_issue_prog. 301 | 302 | MOVE-CORRESPONDING is_issue TO rs_issue. 303 | 304 | rs_issue-program = is_issue-obj_name. 305 | rs_issue-source = _read_program( rs_issue-program ). 306 | 307 | ENDMETHOD. 308 | 309 | 310 | METHOD _get_issue_type. 311 | 312 | MOVE-CORRESPONDING is_issue TO rs_issue. 313 | 314 | rs_issue-program = |%_C{ is_issue-obj_name }|. 315 | rs_issue-source = _read_program( rs_issue-program ). 316 | 317 | ENDMETHOD. 318 | 319 | 320 | METHOD _parse. 321 | 322 | DATA: 323 | lv_regex_type TYPE string, 324 | lv_regex_subtype TYPE string, 325 | lv_line TYPE string, 326 | lv_obj_type TYPE string, 327 | lv_obj_subtype TYPE string, 328 | lv_obj_name TYPE string, 329 | lv_ext TYPE string, 330 | lv_rest TYPE string. 331 | 332 | lv_regex_subtype = '(\d*) IN ' && mv_folder && '(.*)\.(.*)\.(.*)\.(.*)'. 333 | lv_regex_type = '(\d*) IN ' && mv_folder && '(.*)\.(.*)\.(.*)'. 334 | 335 | FIND REGEX lv_regex_subtype IN iv_issue 336 | SUBMATCHES lv_line lv_obj_name lv_obj_type lv_obj_subtype lv_ext. 337 | IF sy-subrc <> 0. 338 | FIND REGEX lv_regex_type IN iv_issue 339 | SUBMATCHES lv_line lv_obj_name lv_obj_type lv_ext. 340 | ENDIF. 341 | IF sy-subrc <> 0. 342 | zcx_abapgit_exception=>raise( 'Unable to identify object from issue description' ). 343 | ENDIF. 344 | 345 | DO. 346 | IF lv_obj_name CS '/'. 347 | SPLIT lv_obj_name AT '/' INTO lv_rest lv_obj_name. 348 | ELSE. 349 | EXIT. 350 | ENDIF. 351 | ENDDO. 352 | 353 | REPLACE ALL OCCURRENCES OF '#' IN lv_obj_name WITH '/'. 354 | REPLACE ALL OCCURRENCES OF '#' IN lv_obj_subtype WITH '/'. 355 | 356 | CLEAR rs_issue. 357 | rs_issue-obj_type = lv_obj_type. 358 | rs_issue-obj_name = lv_obj_name. 359 | rs_issue-obj_subtype = lv_obj_subtype. 360 | rs_issue-extension = lv_ext. 361 | rs_issue-line = lv_line. 362 | 363 | ENDMETHOD. 364 | 365 | 366 | METHOD _read_class_include. 367 | 368 | DATA: ls_include TYPE progstruc. 369 | 370 | ASSERT iv_clspart = seop_ext_class_locals_def 371 | OR iv_clspart = seop_ext_class_locals_imp 372 | OR iv_clspart = seop_ext_class_macros 373 | OR iv_clspart = seop_ext_class_testclasses. 374 | 375 | ls_include-rootname = iv_clsname. 376 | TRANSLATE ls_include-rootname USING ' ='. 377 | ls_include-categorya = iv_clspart(1). 378 | ls_include-codea = iv_clspart+1(4). 379 | 380 | rv_program = ls_include. 381 | 382 | ENDMETHOD. 383 | 384 | 385 | METHOD _read_class_line. 386 | 387 | DATA: 388 | lx_error TYPE REF TO cx_root, 389 | lo_instance TYPE REF TO cl_oo_factory, 390 | lo_source TYPE REF TO cl_oo_clif_source, 391 | lo_scanner TYPE REF TO cl_oo_source_scanner_class, 392 | ls_int TYPE cl_oo_source_scanner_class=>type_source_interval, 393 | lt_methods TYPE cl_oo_source_scanner_class=>type_method_implementations, 394 | ls_method TYPE seocpdkey. 395 | 396 | TRY. 397 | lo_instance = cl_oo_factory=>create_instance( ). 398 | 399 | lo_source ?= lo_instance->create_clif_source( 400 | clif_name = iv_clsname 401 | version = c_active ). 402 | 403 | lo_source->get_source( IMPORTING source = et_source ). 404 | 405 | lo_scanner ?= lo_source->get_scanner( ). 406 | 407 | ls_int = lo_scanner->get_public_section_interval( ). 408 | IF iv_line >= ls_int-begin-line AND iv_line < ls_int-end-line. 409 | ev_program = cl_oo_classname_service=>get_pubsec_name( iv_clsname ). 410 | ev_line = iv_line - ls_int-begin-line + 1. 411 | RETURN. 412 | ENDIF. 413 | 414 | ls_int = lo_scanner->get_protected_section_interval( ). 415 | IF iv_line >= ls_int-begin-line AND iv_line < ls_int-end-line. 416 | ev_program = cl_oo_classname_service=>get_prosec_name( iv_clsname ). 417 | ev_line = iv_line - ls_int-begin-line + 1. 418 | RETURN. 419 | ENDIF. 420 | 421 | ls_int = lo_scanner->get_private_section_interval( ). 422 | IF iv_line >= ls_int-begin-line AND iv_line < ls_int-end-line. 423 | ev_program = cl_oo_classname_service=>get_prisec_name( iv_clsname ). 424 | ev_line = iv_line - ls_int-begin-line + 1. 425 | RETURN. 426 | ENDIF. 427 | 428 | ls_method-clsname = iv_clsname. 429 | lt_methods = lo_scanner->get_method_implementations( ). 430 | LOOP AT lt_methods INTO ls_method-cpdname. 431 | ls_int = lo_scanner->get_method_impl_interval( ls_method-cpdname ). 432 | IF iv_line >= ls_int-begin-line AND iv_line < ls_int-end-line. 433 | ev_program = cl_oo_classname_service=>get_method_include( ls_method ). 434 | ev_line = iv_line - ls_int-begin-line + 1. 435 | RETURN. 436 | ENDIF. 437 | ENDLOOP. 438 | 439 | CATCH cx_root INTO lx_error. 440 | MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. 441 | ENDTRY. 442 | 443 | ENDMETHOD. 444 | 445 | 446 | METHOD _read_functions. 447 | 448 | FIELD-SYMBOLS LIKE LINE OF rt_functab. 449 | 450 | CALL FUNCTION 'RS_FUNCTION_POOL_CONTENTS' 451 | EXPORTING 452 | function_pool = iv_area 453 | TABLES 454 | functab = rt_functab 455 | EXCEPTIONS 456 | function_pool_not_found = 1 457 | OTHERS = 2. 458 | IF sy-subrc <> 0. 459 | zcx_abapgit_exception=>raise_t100( ). 460 | ENDIF. 461 | 462 | " The result can also contain function which are lowercase 463 | LOOP AT rt_functab ASSIGNING . 464 | TRANSLATE TO UPPER CASE. 465 | ENDLOOP. 466 | 467 | SORT rt_functab BY funcname ASCENDING. 468 | DELETE ADJACENT DUPLICATES FROM rt_functab COMPARING funcname. 469 | 470 | ENDMETHOD. 471 | 472 | 473 | METHOD _read_program. 474 | 475 | DATA lv_msg LIKE LINE OF rt_source. 476 | 477 | " abapGit only deals with active objects which we read here 478 | " Note: The issue might be fixed already in inactive code 479 | READ REPORT iv_program INTO rt_source STATE c_active. 480 | IF sy-subrc <> 0. 481 | lv_msg = |Program { iv_program } does not exist in active version|. 482 | APPEND lv_msg TO rt_source. 483 | ENDIF. 484 | 485 | ENDMETHOD. 486 | ENDCLASS. 487 | -------------------------------------------------------------------------------- /src/zcl_abaplint_abapgit_ext_ui.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_abaplint_abapgit_ext_ui DEFINITION 2 | PUBLIC 3 | INHERITING FROM zcl_abapgit_gui_component 4 | FINAL 5 | CREATE PRIVATE. 6 | 7 | PUBLIC SECTION. 8 | 9 | INTERFACES zif_abapgit_gui_event_handler. 10 | INTERFACES zif_abapgit_gui_renderable. 11 | INTERFACES zif_abapgit_gui_menu_provider. 12 | 13 | CLASS-METHODS create 14 | IMPORTING 15 | !iv_key TYPE zif_abapgit_persistence=>ty_repo-key 16 | !iv_check_run TYPE string 17 | !iv_count_total TYPE string 18 | RETURNING 19 | VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable 20 | RAISING 21 | zcx_abapgit_exception. 22 | 23 | METHODS constructor 24 | IMPORTING 25 | !iv_key TYPE zif_abapgit_persistence=>ty_repo-key OPTIONAL 26 | !iv_check_run TYPE string OPTIONAL 27 | !iv_count_total TYPE string 28 | RAISING 29 | zcx_abapgit_exception. 30 | 31 | PRIVATE SECTION. 32 | 33 | CONSTANTS: 34 | BEGIN OF c_action, 35 | go_back TYPE string VALUE 'go_back', 36 | sort_1 TYPE string VALUE 'sort_1', 37 | sort_2 TYPE string VALUE 'sort_2', 38 | sort_3 TYPE string VALUE 'sort_3', 39 | jump_edit TYPE string VALUE 'jump_edit', 40 | toggle_view_source TYPE string VALUE 'toggle_view_source', 41 | END OF c_action. 42 | 43 | CONSTANTS c_lines_before TYPE i VALUE 5. 44 | CONSTANTS c_lines_after TYPE i VALUE 5. 45 | 46 | DATA mo_repo TYPE REF TO zcl_abapgit_repo_online. 47 | DATA mv_check_run TYPE string. 48 | DATA mv_count_total TYPE i. 49 | DATA mt_issues TYPE zcl_abaplint_abapgit_ext_issue=>ty_issues. 50 | DATA mv_view_source TYPE abap_bool. 51 | 52 | METHODS _get_issues 53 | RETURNING 54 | VALUE(rt_issues) TYPE zcl_abaplint_abapgit_ext_issue=>ty_issues 55 | RAISING 56 | zcx_abapgit_exception. 57 | 58 | METHODS _render_footer 59 | RETURNING 60 | VALUE(ri_html) TYPE REF TO zif_abapgit_html 61 | RAISING 62 | zcx_abapgit_exception. 63 | 64 | METHODS _render_issue 65 | IMPORTING 66 | !is_issue TYPE zcl_abaplint_abapgit_ext_issue=>ty_issue 67 | RETURNING 68 | VALUE(ri_html) TYPE REF TO zif_abapgit_html 69 | RAISING 70 | zcx_abapgit_exception. 71 | 72 | METHODS _render_issues 73 | RETURNING 74 | VALUE(ri_html) TYPE REF TO zif_abapgit_html 75 | RAISING 76 | zcx_abapgit_exception. 77 | 78 | METHODS _render_source 79 | IMPORTING 80 | !is_issue TYPE zcl_abaplint_abapgit_ext_issue=>ty_issue 81 | RETURNING 82 | VALUE(ri_html) TYPE REF TO zif_abapgit_html. 83 | 84 | ENDCLASS. 85 | 86 | 87 | 88 | CLASS zcl_abaplint_abapgit_ext_ui IMPLEMENTATION. 89 | 90 | 91 | METHOD constructor. 92 | 93 | super->constructor( ). 94 | 95 | IF iv_key IS INITIAL. 96 | zcx_abapgit_exception=>raise( 'No repository key supplied' ). 97 | ELSE. 98 | mo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). 99 | ENDIF. 100 | 101 | IF iv_check_run IS INITIAL. 102 | zcx_abapgit_exception=>raise( 'No check run supplied' ). 103 | ELSE. 104 | mv_check_run = iv_check_run. 105 | mv_count_total = iv_count_total. 106 | ENDIF. 107 | 108 | mt_issues = _get_issues( ). 109 | 110 | " Could be a user setting 111 | mv_view_source = abap_true. 112 | 113 | gui_services( )->cache_asset( 114 | iv_type = 'image' 115 | iv_subtype = 'png' 116 | iv_url = |{ zcl_abaplint_abapgit_ext_logo=>c_logo }| 117 | iv_xdata = zcl_abaplint_abapgit_ext_logo=>get_logo_mime( ) ). 118 | 119 | ENDMETHOD. 120 | 121 | 122 | METHOD create. 123 | 124 | DATA lo_component TYPE REF TO zcl_abaplint_abapgit_ext_ui. 125 | 126 | CREATE OBJECT lo_component 127 | EXPORTING 128 | iv_key = iv_key 129 | iv_check_run = iv_check_run 130 | iv_count_total = iv_count_total. 131 | 132 | ri_page = zcl_abapgit_gui_page_hoc=>create( 133 | iv_page_title = 'abaplint Issues' 134 | ii_page_menu_provider = lo_component 135 | ii_child_component = lo_component ). 136 | 137 | ENDMETHOD. 138 | 139 | 140 | METHOD zif_abapgit_gui_event_handler~on_event. 141 | 142 | DATA: 143 | lv_jump_type TYPE tadir-object, 144 | lv_jump_name TYPE tadir-obj_name, 145 | lv_include TYPE progname, 146 | lv_line TYPE i, 147 | lv_position TYPE string. 148 | 149 | CASE ii_event->mv_action. 150 | WHEN c_action-go_back. 151 | 152 | rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. 153 | 154 | WHEN c_action-toggle_view_source. 155 | 156 | mv_view_source = boolc( mv_view_source = abap_false ). 157 | rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. 158 | 159 | WHEN c_action-jump_edit. 160 | 161 | lv_jump_type = ii_event->query( )->get( 'TYPE' ). 162 | lv_jump_name = ii_event->query( )->get( 'NAME' ). 163 | 164 | IF lv_jump_type = 'PROG'. 165 | lv_include = lv_jump_name. 166 | lv_line = ii_event->query( )->get( 'LINE' ). 167 | lv_position = nmax( val1 = 1 168 | val2 = lv_line ). 169 | ENDIF. 170 | 171 | " We could use zcl_abapgit_objects=>jump but we want to stay in same window 172 | CALL FUNCTION 'RS_TOOL_ACCESS' 173 | EXPORTING 174 | operation = 'EDIT' 175 | object_name = lv_jump_name 176 | object_type = lv_jump_type 177 | include = lv_include 178 | position = lv_position 179 | in_new_window = abap_false 180 | EXCEPTIONS 181 | not_executed = 1 182 | invalid_object_type = 2 183 | OTHERS = 3. 184 | IF sy-subrc <> 0. 185 | zcx_abapgit_exception=>raise_t100( ). 186 | ENDIF. 187 | 188 | rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. 189 | 190 | WHEN c_action-sort_1. 191 | SORT mt_issues BY obj_type obj_name obj_subtype line url title. 192 | rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. 193 | 194 | WHEN c_action-sort_2. 195 | SORT mt_issues BY obj_type obj_name url title obj_subtype line. 196 | rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. 197 | 198 | WHEN c_action-sort_3. 199 | SORT mt_issues BY url title obj_type obj_name obj_subtype line. 200 | rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. 201 | 202 | ENDCASE. 203 | 204 | ENDMETHOD. 205 | 206 | 207 | METHOD zif_abapgit_gui_menu_provider~get_menu. 208 | 209 | DATA: 210 | lo_sort_menu TYPE REF TO zcl_abapgit_html_toolbar, 211 | lo_view_menu TYPE REF TO zcl_abapgit_html_toolbar. 212 | 213 | CREATE OBJECT lo_sort_menu. 214 | 215 | lo_sort_menu->add( 216 | iv_txt = 'By Object, Sub-object, Line' 217 | iv_act = c_action-sort_1 218 | )->add( 219 | iv_txt = 'By Object, Check, Sub-object' 220 | iv_act = c_action-sort_2 221 | )->add( 222 | iv_txt = 'By Check, Object, Sub-object' 223 | iv_act = c_action-sort_3 ). 224 | 225 | CREATE OBJECT lo_view_menu. 226 | 227 | lo_view_menu->add( 228 | iv_txt = 'Source Code' 229 | iv_chk = mv_view_source 230 | iv_act = c_action-toggle_view_source ). 231 | 232 | CREATE OBJECT ro_toolbar. 233 | 234 | ro_toolbar->add( 235 | iv_txt = 'Sort' 236 | io_sub = lo_sort_menu 237 | )->add( 238 | iv_txt = 'View' 239 | io_sub = lo_view_menu 240 | )->add( 241 | iv_txt = 'Back' 242 | iv_act = zif_abapgit_definitions=>c_action-go_back ). 243 | 244 | ENDMETHOD. 245 | 246 | 247 | METHOD zif_abapgit_gui_renderable~render. 248 | 249 | gui_services( )->register_event_handler( me ). 250 | 251 | CREATE OBJECT ri_html TYPE zcl_abapgit_html. 252 | 253 | ri_html->add( `
` ). 254 | ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( 255 | io_repo = mo_repo 256 | iv_show_commit = abap_false 257 | iv_interactive_branch = abap_false ) ). 258 | ri_html->add( `
` ). 259 | 260 | ri_html->add( _render_issues( ) ). 261 | 262 | ri_html->add( _render_footer( ) ). 263 | 264 | ENDMETHOD. 265 | 266 | 267 | METHOD _get_issues. 268 | 269 | DATA: 270 | lo_annotations TYPE REF TO zcl_abaplint_abapgit_ext_annot, 271 | ls_annotation TYPE zcl_abaplint_abapgit_ext_annot=>ty_annotation, 272 | lt_annotations TYPE zcl_abaplint_abapgit_ext_annot=>ty_annotations, 273 | lo_issue TYPE REF TO zcl_abaplint_abapgit_ext_issue, 274 | ls_issue TYPE zcl_abaplint_abapgit_ext_issue=>ty_issue. 275 | 276 | CREATE OBJECT lo_annotations 277 | EXPORTING 278 | iv_url = mo_repo->get_url( ) 279 | iv_check_run = mv_check_run. 280 | 281 | lt_annotations = lo_annotations->get( ). 282 | 283 | LOOP AT lt_annotations INTO ls_annotation. 284 | 285 | CREATE OBJECT lo_issue 286 | EXPORTING 287 | is_annotation = ls_annotation. 288 | 289 | ls_issue = lo_issue->get( ). 290 | 291 | INSERT ls_issue INTO TABLE rt_issues. 292 | 293 | ENDLOOP. 294 | 295 | SORT rt_issues BY obj_type obj_name obj_subtype line url title. 296 | 297 | ENDMETHOD. 298 | 299 | 300 | METHOD _render_footer. 301 | 302 | DATA lv_url TYPE string. 303 | 304 | lv_url = zcl_abaplint_abapgit_ext_exit=>get_instance( )->get_last_url( ). 305 | 306 | CREATE OBJECT ri_html TYPE zcl_abapgit_html. 307 | 308 | IF lines( mt_issues ) = 0. 309 | 310 | ri_html->add( '
' ). 311 | ri_html->add( ri_html->icon( 'check' ) ). 312 | ri_html->add( 'No abaplint findings' ). 313 | ri_html->add( '
' ). 314 | 315 | ELSEIF lines( mt_issues ) < mv_count_total. 316 | 317 | ri_html->add( '
' ). 318 | ri_html->add( ri_html->icon( 'exclamation-triangle' ) ). 319 | ri_html->add( |First { lines( mt_issues ) } of { mv_count_total } findings shown in list. | ). 320 | ri_html->add_a( 321 | iv_txt = 'Show more...' 322 | iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ lv_url }| ). 323 | ri_html->add( '
' ). 324 | 325 | ENDIF. 326 | 327 | ENDMETHOD. 328 | 329 | 330 | METHOD _render_issue. 331 | 332 | DATA: 333 | ls_mtdkey TYPE seocpdkey, 334 | lv_class TYPE string, 335 | lv_icon TYPE string, 336 | lv_jump_type TYPE tadir-object, 337 | lv_jump_name TYPE tadir-obj_name, 338 | lv_obj_text TYPE string, 339 | lv_obj_link TYPE string, 340 | lv_msg_text TYPE string, 341 | lv_msg_link TYPE string, 342 | lv_msg_code TYPE string, 343 | lv_rest TYPE string. 344 | 345 | CREATE OBJECT ri_html TYPE zcl_abapgit_html. 346 | 347 | CASE is_issue-level. 348 | WHEN 'failure'. 349 | lv_class = 'ci-error'. 350 | lv_icon = ri_html->icon( 351 | iv_name = 'exclamation-circle/red' 352 | iv_hint = 'Failure' ). 353 | WHEN 'warning'. 354 | lv_class = 'ci-warning'. 355 | lv_icon = ri_html->icon( 356 | iv_name = 'exclamation-triangle/yellow' 357 | iv_hint = 'Warning' ). 358 | WHEN OTHERS. 359 | lv_class = 'ci-info'. 360 | ENDCASE. 361 | 362 | " Default jump is to source 363 | lv_jump_type = 'PROG'. 364 | lv_jump_name = is_issue-program. 365 | 366 | CASE is_issue-obj_type. 367 | WHEN 'CLAS'. 368 | CASE to_lower( is_issue-obj_subtype ). 369 | WHEN zif_abapgit_oo_object_fnc=>c_parts-locals_def. 370 | lv_obj_text = |CLAS { is_issue-obj_name } : Local Definitions|. 371 | WHEN zif_abapgit_oo_object_fnc=>c_parts-locals_imp. 372 | lv_obj_text = |CLAS { is_issue-obj_name } : Local Implementations|. 373 | WHEN zif_abapgit_oo_object_fnc=>c_parts-macros. 374 | lv_obj_text = |CLAS { is_issue-obj_name } : Macros|. 375 | WHEN zif_abapgit_oo_object_fnc=>c_parts-testclasses. 376 | lv_obj_text = |CLAS { is_issue-obj_name } : Test Classes|. 377 | WHEN OTHERS. 378 | cl_oo_classname_service=>get_method_by_include( 379 | EXPORTING 380 | incname = is_issue-program 381 | RECEIVING 382 | mtdkey = ls_mtdkey 383 | EXCEPTIONS 384 | class_not_existing = 1 385 | method_not_existing = 2 386 | OTHERS = 3 ). 387 | IF sy-subrc = 0. 388 | lv_obj_text = |CLAS { is_issue-obj_name }->{ ls_mtdkey-cpdname }|. 389 | ELSE. 390 | lv_obj_text = |CLAS { is_issue-obj_name }|. 391 | ENDIF. 392 | ENDCASE. 393 | WHEN 'FUGR'. 394 | lv_obj_text = |FUGR { is_issue-obj_name } { is_issue-obj_subtype }|. 395 | WHEN OTHERS. 396 | lv_obj_text = |{ is_issue-obj_type } { is_issue-obj_name }|. 397 | lv_jump_type = is_issue-obj_type. 398 | lv_jump_name = is_issue-obj_name. 399 | ENDCASE. 400 | 401 | lv_msg_text = escape( 402 | val = is_issue-title 403 | format = cl_abap_format=>e_html_text ). 404 | 405 | lv_msg_code = reverse( is_issue-url ). 406 | SPLIT lv_msg_code AT '/' INTO lv_msg_code lv_rest. 407 | lv_msg_code = reverse( lv_msg_code ). 408 | 409 | lv_msg_link = ri_html->a( 410 | iv_txt = lv_msg_code 411 | iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ is_issue-url }| 412 | iv_class = 'url' ). 413 | 414 | lv_obj_text = |{ lv_obj_text } [ @{ is_issue-line } ]|. 415 | lv_obj_link = |{ c_action-jump_edit }?type={ lv_jump_type }&name={ lv_jump_name }&line={ is_issue-line }|. 416 | 417 | ri_html->add( |
  • | ). 418 | ri_html->add_a( 419 | iv_txt = lv_obj_text 420 | iv_act = lv_obj_link 421 | iv_typ = zif_abapgit_html=>c_action_type-sapevent ). 422 | 423 | ri_html->add( '' ). 424 | ri_html->add( zcl_abaplint_abapgit_ext_logo=>get_logo_html( lv_msg_code ) ). 425 | ri_html->add( | { lv_msg_text } ({ lv_msg_link })| ). 426 | ri_html->add( '' ). 427 | 428 | IF mv_view_source = abap_true. 429 | ri_html->add( _render_source( is_issue ) ). 430 | ENDIF. 431 | 432 | ri_html->add( |
  • | ). 433 | 434 | ENDMETHOD. 435 | 436 | 437 | METHOD _render_issues. 438 | 439 | DATA ls_issue LIKE LINE OF mt_issues. 440 | 441 | CREATE OBJECT ri_html TYPE zcl_abapgit_html. 442 | 443 | ri_html->add( '
      ' ). 444 | 445 | LOOP AT mt_issues INTO ls_issue. 446 | 447 | ri_html->add( _render_issue( ls_issue ) ). 448 | 449 | ENDLOOP. 450 | 451 | ri_html->add( '
    ' ). 452 | 453 | ENDMETHOD. 454 | 455 | 456 | METHOD _render_source. 457 | 458 | DATA: 459 | lv_source LIKE LINE OF is_issue-source, 460 | lv_line TYPE i, 461 | lv_class TYPE string, 462 | lo_highlighter TYPE REF TO zcl_abapgit_syntax_highlighter. 463 | 464 | CREATE OBJECT ri_html TYPE zcl_abapgit_html. 465 | 466 | IF is_issue-source IS INITIAL. 467 | RETURN. 468 | ENDIF. 469 | 470 | " Assume all findings are in ABAP code 471 | lo_highlighter = zcl_abapgit_syntax_factory=>create( 'code.abap' ). 472 | ASSERT lo_highlighter IS NOT INITIAL. 473 | 474 | " Use same styles as diff pages 475 | ri_html->add( '
    ' ). 476 | ri_html->add( '' ). 477 | ri_html->add( '' ). 478 | ri_html->add( '' ). 479 | ri_html->add( '' ). 480 | ri_html->add( '' ). 481 | ri_html->add( '' ). 482 | ri_html->add( '' ). 483 | 484 | LOOP AT is_issue-source INTO lv_source FROM is_issue-line - c_lines_before TO is_issue-line + c_lines_after. 485 | lv_line = sy-tabix. 486 | lv_source = lo_highlighter->process_line( lv_source ). 487 | ri_html->add( '' ). 488 | IF lv_line = is_issue-line. 489 | CASE is_issue-level. 490 | WHEN 'failure'. 491 | lv_class = 'diff_del'. "red 492 | WHEN 'warning'. 493 | lv_class = 'diff_upd'. "yellow 494 | WHEN OTHERS. 495 | lv_class = 'diff_ins'. "green 496 | ENDCASE. 497 | ELSE. 498 | lv_class = 'diff_others'. 499 | ENDIF. 500 | ri_html->add( || ). 501 | ri_html->add( '' ). 502 | ENDLOOP. 503 | IF sy-subrc <> 0. 504 | ri_html->add( '' ). 505 | ri_html->add( '' ). 506 | ri_html->add( '' ). 507 | ri_html->add( '' ). 508 | ENDIF. 509 | 510 | ri_html->add( '
    { lv_line }{ lv_source }
    0Source location does not exist (anymore)
    ' ). 511 | ri_html->add( '
    ' ). 512 | 513 | ENDMETHOD. 514 | ENDCLASS. 515 | -------------------------------------------------------------------------------- /abaplint.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | { 4 | "files": "/src/**/*.*", 5 | "folder": "/deps", 6 | "url": "https://github.com/abaplint/deps" 7 | }, 8 | { 9 | "files": "/src/**/*.*", 10 | "folder": "/deps2", 11 | "url": "https://github.com/abapGit/abapGit" 12 | } 13 | ], 14 | "global": { 15 | "exclude": [], 16 | "files": "/src/**/*.*", 17 | "noIssues": [], 18 | "skipGeneratedBOPFInterfaces": false, 19 | "skipGeneratedFunctionGroups": false, 20 | "skipGeneratedGatewayClasses": false, 21 | "skipGeneratedPersistentClasses": false, 22 | "skipGeneratedProxyClasses": false, 23 | "skipGeneratedProxyInterfaces": false, 24 | "skipIncludesWithoutMain": false, 25 | "useApackDependencies": false 26 | }, 27 | "rules": { 28 | "7bit_ascii": { 29 | "exclude": [], 30 | "severity": "Error" 31 | }, 32 | "abapdoc": { 33 | "checkLocal": false, 34 | "classDefinition": false, 35 | "exclude": [".*"], 36 | "interfaceDefinition": false, 37 | "severity": "Error" 38 | }, 39 | "allowed_object_naming": { 40 | "exclude": [], 41 | "severity": "Error" 42 | }, 43 | "allowed_object_types": { 44 | "allowed": [ 45 | "CLAS", 46 | "DEVC", 47 | "INTF", 48 | "W3MI" 49 | ], 50 | "exclude": [], 51 | "severity": "Error" 52 | }, 53 | "ambiguous_statement": { 54 | "exclude": [], 55 | "severity": "Error" 56 | }, 57 | "avoid_use": { 58 | "break": true, 59 | "defaultKey": true, 60 | "define": true, 61 | "describeLines": true, 62 | "exclude": [], 63 | "severity": "Error", 64 | "skipQuickFix": false, 65 | "statics": true, 66 | "testSeams": true 67 | }, 68 | "begin_end_names": { 69 | "exclude": [], 70 | "severity": "Error" 71 | }, 72 | "begin_single_include": { 73 | "exclude": [], 74 | "severity": "Error" 75 | }, 76 | "call_transaction_authority_check": { 77 | "exclude": [], 78 | "severity": "Error" 79 | }, 80 | "chain_mainly_declarations": { 81 | "check": true, 82 | "clear": true, 83 | "definitions": true, 84 | "exclude": [], 85 | "free": true, 86 | "hide": true, 87 | "include": true, 88 | "move": true, 89 | "refresh": true, 90 | "severity": "Error", 91 | "sort": true, 92 | "unassign": true, 93 | "write": true 94 | }, 95 | "check_abstract": { 96 | "exclude": [], 97 | "severity": "Error" 98 | }, 99 | "check_comments": { 100 | "allowEndOfLine": true, 101 | "exclude": [], 102 | "severity": "Error" 103 | }, 104 | "check_ddic": { 105 | "exclude": [], 106 | "severity": "Error" 107 | }, 108 | "check_include": { 109 | "exclude": [], 110 | "severity": "Error" 111 | }, 112 | "check_subrc": { 113 | "assign": true, 114 | "authorityCheck": true, 115 | "exclude": [], 116 | "find": true, 117 | "insertDatabase": true, 118 | "modifyDatabase": true, 119 | "openDataset": true, 120 | "readTable": true, 121 | "selectSingle": true, 122 | "selectTable": true, 123 | "severity": "Error", 124 | "updateDatabase": true 125 | }, 126 | "check_syntax": { 127 | "exclude": [], 128 | "severity": "Error" 129 | }, 130 | "check_text_elements": { 131 | "exclude": [], 132 | "severity": "Error" 133 | }, 134 | "check_transformation_exists": { 135 | "exclude": [], 136 | "severity": "Error" 137 | }, 138 | "class_attribute_names": { 139 | "constants": "^C_.+$", 140 | "exclude": [], 141 | "ignoreExceptions": true, 142 | "ignoreInterfaces": false, 143 | "ignoreLocal": true, 144 | "ignoreNames": [], 145 | "ignorePatterns": [], 146 | "instance": "^M._.+$", 147 | "patternKind": "required", 148 | "severity": "Error", 149 | "statics": "^G._.+$" 150 | }, 151 | "cloud_types": { 152 | "exclude": [], 153 | "severity": "Error" 154 | }, 155 | "colon_missing_space": { 156 | "exclude": [], 157 | "severity": "Error" 158 | }, 159 | "commented_code": { 160 | "allowIncludeInFugr": true, 161 | "exclude": [], 162 | "severity": "Warning" 163 | }, 164 | "constructor_visibility_public": { 165 | "exclude": [], 166 | "severity": "Error" 167 | }, 168 | "contains_tab": { 169 | "exclude": [], 170 | "severity": "Error", 171 | "spaces": 1 172 | }, 173 | "cyclic_oo": { 174 | "exclude": [], 175 | "severity": "Error", 176 | "skip": [], 177 | "skipTestclasses": true, 178 | "skipSharedMemory": true 179 | }, 180 | "cyclomatic_complexity": { 181 | "exclude": [], 182 | "max": 20, 183 | "severity": "Error" 184 | }, 185 | "dangerous_statement": { 186 | "deleteDynpro": true, 187 | "deleteReport": true, 188 | "deleteTextpool": true, 189 | "dynamicSQL": true, 190 | "exclude": [], 191 | "execSQL": true, 192 | "exportDynpro": true, 193 | "generateDynpro": true, 194 | "generateReport": true, 195 | "generateSubroutine": true, 196 | "insertReport": true, 197 | "kernelCall": true, 198 | "severity": "Error", 199 | "systemCall": true 200 | }, 201 | "db_operation_in_loop": { 202 | "exclude": [], 203 | "severity": "Error" 204 | }, 205 | "definitions_top": { 206 | "exclude": [], 207 | "severity": "Error" 208 | }, 209 | "description_empty": { 210 | "exclude": [], 211 | "severity": "Error" 212 | }, 213 | "double_space": { 214 | "afterColon": true, 215 | "endParen": true, 216 | "exclude": [], 217 | "keywords": true, 218 | "severity": "Error", 219 | "startParen": true 220 | }, 221 | "downport": { 222 | "exclude": [], 223 | "severity": "Error" 224 | }, 225 | "empty_line_in_statement": { 226 | "allowChained": false, 227 | "exclude": [], 228 | "severity": "Error" 229 | }, 230 | "empty_statement": { 231 | "exclude": [], 232 | "severity": "Error" 233 | }, 234 | "empty_structure": { 235 | "at": true, 236 | "case": true, 237 | "do": true, 238 | "exclude": [], 239 | "if": true, 240 | "loop": true, 241 | "select": true, 242 | "severity": "Error", 243 | "try": true, 244 | "when": true, 245 | "while": true 246 | }, 247 | "exit_or_check": { 248 | "allowCheck": false, 249 | "allowExit": false, 250 | "exclude": [], 251 | "severity": "Error" 252 | }, 253 | "exporting": { 254 | "exclude": [], 255 | "severity": "Error" 256 | }, 257 | "forbidden_identifier": { 258 | "check": [], 259 | "exclude": [], 260 | "severity": "Error" 261 | }, 262 | "forbidden_pseudo_and_pragma": { 263 | "exclude": [], 264 | "ignoreGlobalClassDefinition": false, 265 | "ignoreGlobalInterface": false, 266 | "pragmas": [], 267 | "pseudo": [], 268 | "severity": "Error" 269 | }, 270 | "forbidden_void_type": { 271 | "check": [ 272 | "^stringtab$", 273 | "^char[0-9]+$", 274 | "^int4$", 275 | "^rs_c_true$", 276 | "^rs_c_false$", 277 | "^flag$", 278 | "^sydatum$", 279 | "^syindex$", 280 | "^sytabix$", 281 | "^syuzeit$" 282 | ], 283 | "exclude": [], 284 | "severity": "Error" 285 | }, 286 | "form_tables_obsolete": { 287 | "exclude": [], 288 | "severity": "Error" 289 | }, 290 | "fully_type_constants": { 291 | "checkData": true, 292 | "exclude": [], 293 | "severity": "Error" 294 | }, 295 | "function_module_recommendations": { 296 | "exclude": [], 297 | "recommendations": [ 298 | { 299 | "name": "SUBST_GET_FILE_LIST", 300 | "replace": "see note 1686357" 301 | }, 302 | { 303 | "name": "ROUND", 304 | "replace": "use built in function: round()" 305 | }, 306 | { 307 | "name": "SO_NEW_DOCUMENT_ATT_SEND_API1", 308 | "replace": "use CL_BCS" 309 | }, 310 | { 311 | "name": "ECATT_CONV_XSTRING_TO_STRING", 312 | "replace": "use CL_BINARY_CONVERT" 313 | }, 314 | { 315 | "name": "SCMS_STRING_TO_XSTRING", 316 | "replace": "use CL_BINARY_CONVERT" 317 | }, 318 | { 319 | "name": "JOB_CREATE", 320 | "replace": "use CL_BP_ABAP_JOB" 321 | }, 322 | { 323 | "name": "JOB_SUBMIT", 324 | "replace": "use CL_BP_ABAP_JOB" 325 | }, 326 | { 327 | "name": "GUI_DOWNLOAD", 328 | "replace": "use CL_GUI_FRONTEND_SERVICES" 329 | }, 330 | { 331 | "name": "GUI_UPLOAD", 332 | "replace": "use CL_GUI_FRONTEND_SERVICES" 333 | }, 334 | { 335 | "name": "WS_FILENAME_GET", 336 | "replace": "use CL_GUI_FRONTEND_SERVICES" 337 | }, 338 | { 339 | "name": "F4_FILENAME", 340 | "replace": "use CL_GUI_FRONTEND_SERVICES" 341 | }, 342 | { 343 | "name": "SAPGUI_PROGRESS_INDICATOR", 344 | "replace": "use CL_PROGRESS_INDICATOR" 345 | }, 346 | { 347 | "name": "GUID_CREATE", 348 | "replace": "use CL_SYSTEM_UUID" 349 | }, 350 | { 351 | "name": "SSFC_BASE64_DECODE", 352 | "replace": "use class CL_HTTP_UTILITY methods" 353 | }, 354 | { 355 | "name": "SSFC_BASE64_ENCODE", 356 | "replace": "use class CL_HTTP_UTILITY methods" 357 | }, 358 | { 359 | "name": "SCMS_BASE64_DECODE_STR", 360 | "replace": "use class CL_HTTP_UTILITY methods" 361 | }, 362 | { 363 | "name": "POPUP_TO_DECIDE", 364 | "replace": "use POPUP_TO_CONFIRM" 365 | }, 366 | { 367 | "name": "REUSE_ALV_GRID_DISPLAY", 368 | "replace": "use CL_SALV_TABLE=>FACTORY or CL_GUI_ALV_GRID" 369 | }, 370 | { 371 | "name": "CALCULATE_HASH_FOR_RAW", 372 | "replace": "use CL_ABAP_HMAC" 373 | }, 374 | { 375 | "name": "FUNCTION_EXISTS", 376 | "replace": "surround with try-catch CX_SY_DYN_CALL_ILLEGAL_METHOD instead" 377 | } 378 | ], 379 | "severity": "Error" 380 | }, 381 | "functional_writing": { 382 | "exclude": [], 383 | "ignoreExceptions": true, 384 | "severity": "Error" 385 | }, 386 | "global_class": { 387 | "exclude": [], 388 | "severity": "Error" 389 | }, 390 | "identical_conditions": { 391 | "exclude": [], 392 | "severity": "Error" 393 | }, 394 | "identical_contents": { 395 | "exclude": [".*"], 396 | "severity": "Error" 397 | }, 398 | "identical_descriptions": { 399 | "exclude": [], 400 | "severity": "Error" 401 | }, 402 | "identical_form_names": { 403 | "exclude": [], 404 | "severity": "Error" 405 | }, 406 | "if_in_if": { 407 | "exclude": [".*"], 408 | "severity": "Error" 409 | }, 410 | "implement_methods": { 411 | "exclude": [], 412 | "severity": "Error" 413 | }, 414 | "in_statement_indentation": { 415 | "blockStatements": 2, 416 | "exclude": [".*"], 417 | "ignoreExceptions": true, 418 | "severity": "Error" 419 | }, 420 | "indentation": { 421 | "alignTryCatch": false, 422 | "exclude": [], 423 | "globalClassSkipFirst": false, 424 | "ignoreExceptions": true, 425 | "ignoreGlobalClassDefinition": false, 426 | "ignoreGlobalInterface": false, 427 | "selectionScreenBlockIndentation": false, 428 | "severity": "Error" 429 | }, 430 | "inline_data_old_versions": { 431 | "exclude": [], 432 | "severity": "Error" 433 | }, 434 | "intf_referencing_clas": { 435 | "allow": [], 436 | "exclude": [], 437 | "severity": "Error" 438 | }, 439 | "keep_single_parameter_on_one_line": { 440 | "exclude": [], 441 | "length": 120, 442 | "severity": "Error" 443 | }, 444 | "keyword_case": { 445 | "exclude": [], 446 | "ignoreExceptions": true, 447 | "ignoreFunctionModuleName": false, 448 | "ignoreGlobalClassBoundaries": false, 449 | "ignoreGlobalClassDefinition": false, 450 | "ignoreGlobalInterface": false, 451 | "ignoreKeywords": [], 452 | "ignoreLowerClassImplmentationStatement": true, 453 | "severity": "Error", 454 | "style": "upper" 455 | }, 456 | "line_break_multiple_parameters": { 457 | "count": 1, 458 | "exclude": [], 459 | "severity": "Error" 460 | }, 461 | "line_break_style": { 462 | "exclude": [], 463 | "severity": "Error" 464 | }, 465 | "line_length": { 466 | "exclude": [], 467 | "length": 120, 468 | "severity": "Error" 469 | }, 470 | "line_only_punc": { 471 | "exclude": [], 472 | "ignoreExceptions": true, 473 | "severity": "Error" 474 | }, 475 | "local_class_naming": { 476 | "exception": "^LCX_.+$", 477 | "exclude": [], 478 | "ignoreNames": [], 479 | "ignorePatterns": [], 480 | "local": "^LCL_.+$", 481 | "patternKind": "required", 482 | "severity": "Error", 483 | "test": "^LTCL_.+$" 484 | }, 485 | "local_testclass_consistency": { 486 | "exclude": [], 487 | "severity": "Error" 488 | }, 489 | "local_variable_names": { 490 | "exclude": [], 491 | "expectedConstant": "^LC_.+$", 492 | "expectedData": "^L._.+$", 493 | "expectedFS": "^$", 494 | "ignoreNames": [], 495 | "ignorePatterns": [], 496 | "patternKind": "required", 497 | "severity": "Error" 498 | }, 499 | "main_file_contents": { 500 | "exclude": [], 501 | "severity": "Error" 502 | }, 503 | "many_parentheses": { 504 | "exclude": [], 505 | "severity": "Error" 506 | }, 507 | "max_one_method_parameter_per_line": { 508 | "exclude": [], 509 | "severity": "Error" 510 | }, 511 | "max_one_statement": { 512 | "exclude": [], 513 | "severity": "Error" 514 | }, 515 | "message_exists": { 516 | "exclude": [], 517 | "severity": "Error" 518 | }, 519 | "method_implemented_twice": { 520 | "exclude": [], 521 | "severity": "Error" 522 | }, 523 | "method_length": { 524 | "checkForms": true, 525 | "errorWhenEmpty": true, 526 | "exclude": [], 527 | "ignoreTestClasses": true, 528 | "severity": "Warning", 529 | "statements": 100 530 | }, 531 | "method_overwrites_builtin": { 532 | "exclude": [], 533 | "severity": "Error" 534 | }, 535 | "method_parameter_names": { 536 | "changing": "^C._.+$", 537 | "exclude": [], 538 | "exporting": "^E._.+$", 539 | "ignoreExceptions": true, 540 | "ignoreNames": [], 541 | "ignorePatterns": [], 542 | "importing": "^I._.+$", 543 | "patternKind": "required", 544 | "returning": "^R._.+|RESULT$", 545 | "severity": "Error" 546 | }, 547 | "mix_returning": { 548 | "exclude": [], 549 | "severity": "Error" 550 | }, 551 | "modify_only_own_db_tables": { 552 | "exclude": [], 553 | "ownTables": "^[yz]", 554 | "reportDynamic": true, 555 | "severity": "Error" 556 | }, 557 | "msag_consistency": { 558 | "exclude": [], 559 | "severity": "Error" 560 | }, 561 | "names_no_dash": { 562 | "exclude": [], 563 | "severity": "Error" 564 | }, 565 | "nesting": { 566 | "depth": 5, 567 | "exclude": [], 568 | "severity": "Error" 569 | }, 570 | "newline_between_methods": { 571 | "count": 3, 572 | "exclude": [], 573 | "logic": "less", 574 | "severity": "Error" 575 | }, 576 | "no_public_attributes": { 577 | "allowReadOnly": true, 578 | "exclude": [], 579 | "ignoreTestClasses": false, 580 | "severity": "Error" 581 | }, 582 | "no_yoda_conditions": { 583 | "exclude": [], 584 | "onlyConstants": false, 585 | "severity": "Error" 586 | }, 587 | "object_naming": { 588 | "auth": "^Z", 589 | "clas": "^ZC(L|X)\\_ABAPLINT_ABAPGIT_EXT", 590 | "doma": "^Z", 591 | "dtel": "^Z", 592 | "enqu": "^EZ", 593 | "exclude": [], 594 | "fugr": "^Z", 595 | "idoc": "^Z", 596 | "ignoreNames": [], 597 | "ignorePatterns": [], 598 | "intf": "^ZIF\\_ABAPLINT_ABAPGIT_EXT", 599 | "msag": "^Z", 600 | "patternKind": "required", 601 | "pinf": "^Z", 602 | "prog": "^Z", 603 | "severity": "Error", 604 | "shlp": "^Z", 605 | "ssfo": "^Z", 606 | "ssst": "^Z", 607 | "tabl": "^Z", 608 | "tran": "^Z", 609 | "ttyp": "^Z", 610 | "xslt": "^Z" 611 | }, 612 | "obsolete_statement": { 613 | "add": true, 614 | "callTransformation": true, 615 | "clientSpecified": true, 616 | "communication": true, 617 | "compute": true, 618 | "divide": true, 619 | "exclude": [], 620 | "exitFromSQL": true, 621 | "fieldSymbolStructure": true, 622 | "formDefinition": true, 623 | "formImplementation": true, 624 | "freeMemory": true, 625 | "load": true, 626 | "move": true, 627 | "multiply": true, 628 | "occurences": true, 629 | "occurs": true, 630 | "pack": true, 631 | "parameter": true, 632 | "ranges": true, 633 | "refresh": true, 634 | "regex": true, 635 | "requested": true, 636 | "selectWithoutInto": true, 637 | "setExtended": true, 638 | "severity": "Error", 639 | "sortByFS": true, 640 | "subtract": true, 641 | "typePools": true, 642 | "withHeaderLine": true 643 | }, 644 | "omit_parameter_name": { 645 | "exclude": [], 646 | "severity": "Error" 647 | }, 648 | "omit_receiving": { 649 | "exclude": [], 650 | "severity": "Error" 651 | }, 652 | "parser_702_chaining": { 653 | "exclude": [], 654 | "severity": "Error" 655 | }, 656 | "parser_error": { 657 | "exclude": [], 658 | "severity": "Error" 659 | }, 660 | "parser_missing_space": { 661 | "exclude": [], 662 | "severity": "Error" 663 | }, 664 | "prefer_inline": { 665 | "exclude": [], 666 | "severity": "Error" 667 | }, 668 | "prefer_is_not": { 669 | "exclude": [], 670 | "severity": "Error" 671 | }, 672 | "prefer_raise_exception_new": { 673 | "exclude": [], 674 | "severity": "Error" 675 | }, 676 | "prefer_returning_to_exporting": { 677 | "exclude": [], 678 | "severity": "Error" 679 | }, 680 | "prefer_xsdbool": { 681 | "exclude": [], 682 | "severity": "Error" 683 | }, 684 | "preferred_compare_operator": { 685 | "badOperators": [ 686 | "EQ", 687 | "><", 688 | "NE", 689 | "GE", 690 | "GT", 691 | "LT", 692 | "LE" 693 | ], 694 | "exclude": [], 695 | "severity": "Error" 696 | }, 697 | "prefix_is_current_class": { 698 | "exclude": [], 699 | "omitMeInstanceCalls": true, 700 | "severity": "Error" 701 | }, 702 | "reduce_string_templates": { 703 | "exclude": [], 704 | "severity": "Error" 705 | }, 706 | "release_idoc": { 707 | "exclude": [], 708 | "severity": "Error" 709 | }, 710 | "remove_descriptions": { 711 | "exclude": [".*"], 712 | "ignoreExceptions": false, 713 | "ignoreWorkflow": true, 714 | "severity": "Error" 715 | }, 716 | "rfc_error_handling": { 717 | "exclude": [], 718 | "severity": "Error" 719 | }, 720 | "select_add_order_by": { 721 | "exclude": [], 722 | "severity": "Error" 723 | }, 724 | "select_performance": { 725 | "endSelect": true, 726 | "exclude": [], 727 | "selectStar": true, 728 | "severity": "Error", 729 | "starOkayIfFewColumns": 10 730 | }, 731 | "selection_screen_naming": { 732 | "exclude": [], 733 | "ignoreNames": [], 734 | "ignorePatterns": [], 735 | "parameter": "^P_.+$", 736 | "patternKind": "required", 737 | "screenElement": "^SC_.+$", 738 | "selectOption": "^S_.+$", 739 | "severity": "Error" 740 | }, 741 | "sequential_blank": { 742 | "exclude": [], 743 | "lines": 4, 744 | "severity": "Error" 745 | }, 746 | "short_case": { 747 | "allow": [], 748 | "exclude": [], 749 | "length": 1, 750 | "severity": "Error" 751 | }, 752 | "sicf_consistency": { 753 | "exclude": [], 754 | "severity": "Error" 755 | }, 756 | "space_before_colon": { 757 | "exclude": [], 758 | "severity": "Error" 759 | }, 760 | "space_before_dot": { 761 | "exclude": [], 762 | "ignoreExceptions": true, 763 | "ignoreGlobalDefinition": true, 764 | "severity": "Error" 765 | }, 766 | "sql_escape_host_variables": { 767 | "exclude": [], 768 | "severity": "Error" 769 | }, 770 | "start_at_tab": { 771 | "exclude": [], 772 | "severity": "Error" 773 | }, 774 | "superclass_final": { 775 | "exclude": [], 776 | "severity": "Error" 777 | }, 778 | "sy_modification": { 779 | "exclude": [], 780 | "severity": "Error" 781 | }, 782 | "tabl_enhancement_category": { 783 | "exclude": [], 784 | "severity": "Error" 785 | }, 786 | "try_without_catch": { 787 | "exclude": [], 788 | "severity": "Error" 789 | }, 790 | "type_form_parameters": { 791 | "exclude": [], 792 | "severity": "Error" 793 | }, 794 | "types_naming": { 795 | "exclude": [], 796 | "pattern": "^TY_.+$", 797 | "severity": "Error" 798 | }, 799 | "uncaught_exception": { 800 | "exclude": [], 801 | "severity": "Error" 802 | }, 803 | "unknown_types": { 804 | "exclude": [], 805 | "severity": "Error" 806 | }, 807 | "unreachable_code": { 808 | "exclude": [], 809 | "severity": "Error" 810 | }, 811 | "unsecure_fae": { 812 | "exclude": [], 813 | "severity": "Error" 814 | }, 815 | "unused_ddic": { 816 | "exclude": [], 817 | "severity": "Error" 818 | }, 819 | "unused_methods": { 820 | "exclude": [], 821 | "severity": "Error" 822 | }, 823 | "unused_types": { 824 | "exclude": [], 825 | "severity": "Error", 826 | "skipNames": [] 827 | }, 828 | "unused_variables": { 829 | "exclude": [], 830 | "severity": "Error", 831 | "skipNames": [] 832 | }, 833 | "use_bool_expression": { 834 | "exclude": [], 835 | "severity": "Error" 836 | }, 837 | "use_class_based_exceptions": { 838 | "exclude": [], 839 | "severity": "Error" 840 | }, 841 | "use_line_exists": { 842 | "exclude": [], 843 | "severity": "Error" 844 | }, 845 | "use_new": { 846 | "exclude": [], 847 | "severity": "Error" 848 | }, 849 | "when_others_last": { 850 | "exclude": [], 851 | "severity": "Error" 852 | }, 853 | "whitespace_end": { 854 | "exclude": [], 855 | "severity": "Error" 856 | }, 857 | "xml_consistency": { 858 | "exclude": [], 859 | "severity": "Error" 860 | } 861 | }, 862 | "syntax": { 863 | "errorNamespace": "^(LCL_|LIF_|Y|Z)", 864 | "globalConstants": [ 865 | "seop_ext_class_locals_def", 866 | "seop_ext_class_locals_imp", 867 | "seop_ext_class_macros", 868 | "seop_ext_class_testclasses" 869 | ], 870 | "globalMacros": [], 871 | "version": "v702" 872 | } 873 | } 874 | --------------------------------------------------------------------------------