Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

My first Code Inspector extension

Former Member
0 Likes
650

I'm trying to write my first own extension of Code Inspector. I don't like to discover again new wheel so I'm asking You:

Is in ABAP any test which check how long is procedure (how many lines is beetwene FORM ENDFORM statement?) which return warnings when length is just a little bit to big and errors when exceed a lot maximum length?

<b>I'm only interesting that is already in SAP this kind of test.</b>

Cheers, Tomek

2 REPLIES 2
Read only

former_member183804
Active Contributor
0 Likes
548

Hello Thomasz,

you will see all SAP checks when starting SCI. Only with the newer releases there is a check on program metrics.

Regards,

Klaus

<b>Documentation</b>



Determining Complexity of Procedures in ABAP Programs

The check calculates different complexity measurements for procedures in ABAP programs. These measurements are:


Number of Statements. Cyclical complexity. Here there is also the variant through a test parameter as to whether a CASE statement is treated as a simple or multiple branch.
Number of Versions. This measurement can only be determined in the original system of the respective program since these versions are only there.
In the results display, there is only one single information message. The results list is displayed when you double-click this message. In this list, the above-mentioned complexity measurements are specified after the procedure type and the procedure name. In addition, the Include and the line where the respective procedure begins are displayed. By double-clicking here, you can branch to the source code. The list can be sorted, as usual, by any column you wish. In addition, the standard procedures for exporting (for example, to Excel) are provided.


The test specifies the various procedure types in the  results list in the following manner:

METH : Methods
FORM: Forms
FUNC: Function modules
MOD: Modules
STAS: START-OF-SELECTION event
TOPS: TOP-OF-PAGE event


<b>Some code excerpt</b>



method RUN .
  data:
    L_EXCP  type ref to CX_EXCEPTION,
    L_NAME  type STRING,
    L_CLASS type STRING.


  if REF_SCAN is initial.
    check GET( ) = 'X'.
  endif.

  check REF_SCAN->SUBRC = 0.

  if PA_VERSION = 'X'.
    GET_PROC_VERSIONS( ).
  endif.

  STATEMENT_INDEX = 1.

  try.
      do.
        read table REF_SCAN->STATEMENTS index STATEMENT_INDEX into STATEMENT_WA.
        if SY-SUBRC <> 0. exit. endif.
        add 1 to STATEMENT_INDEX.
        check STATEMENT_WA-FROM <= STATEMENT_WA-TO.
*-- avoid native SQL
        check STATEMENT_WA-TYPE na 'EMPSDR'.

        case KEYWORD( ).
          when 'PROGRAM'
            or 'REPORT'
            or 'START-OF-SELECTION'.
            CHECK( P_PROC_TYPE = 'SSEL' P_PROC_NAME = '%' ).

          when 'END-OF-SELECTION'.
            CHECK( P_PROC_TYPE = 'ESEL' P_PROC_NAME = '%' ).

          when 'FORM'.
            L_NAME = GET_TOKEN_REL( 2 ).
            CHECK( P_PROC_TYPE = 'FORM' P_PROC_NAME = L_NAME ).

          when 'FUNCTION'.
            L_NAME = GET_TOKEN_REL( 2 ).
            CHECK( P_PROC_TYPE = 'FUNC' P_PROC_NAME = L_NAME  ).

          when 'METHOD'.
            L_NAME = GET_TOKEN_REL( 2 ).
            concatenate L_CLASS '=>' L_NAME into L_NAME.
            CHECK( P_PROC_TYPE = 'METH' P_PROC_NAME = L_NAME  ).

          when 'MODULE'.
            L_NAME = GET_TOKEN_REL( 2 ).
            if GET_TOKEN_REL( 3 ) = 'OUTPUT'.
              CHECK( P_PROC_TYPE = 'MODO' P_PROC_NAME = L_NAME ).
            else.
              CHECK( P_PROC_TYPE = 'MODI' P_PROC_NAME = L_NAME ).
            endif.

          when 'CLASS'.
            L_CLASS = GET_TOKEN_REL( 2 ).

          when 'INITIALIZATION'.
            CHECK( P_PROC_TYPE = 'INIT' P_PROC_NAME = '%' ).

          when 'GET'.
            L_NAME = GET_TOKEN_REL( 2 ).
            if  GET_TOKEN_REL( 3 ) = 'LATE'.
              CHECK( P_PROC_TYPE = 'GETL' P_PROC_NAME = L_NAME ).
            else.
              CHECK( P_PROC_TYPE = 'GET' P_PROC_NAME = L_NAME ).
            endif.

          when 'AT'.
            L_NAME = GET_TOKEN_REL( 2 ).
            if strlen( L_NAME ) > 2 and L_NAME(2) = 'PF'.
              L_NAME = L_NAME+2.
              CHECK( P_PROC_TYPE = 'ATPF' P_PROC_NAME = L_NAME ).
            else.
              case L_NAME.
                when 'USER-COMMAND'.
                  CHECK( P_PROC_TYPE = 'ATUC' P_PROC_NAME = '%' ).

                when 'LINE-SELECTION'.
                  CHECK( P_PROC_TYPE = 'LISE' P_PROC_NAME = '%' ).

                when 'SELECTION-SCREEN'.

                  L_NAME = GET_TOKEN_REL( 3 ).
                  if L_NAME is initial.
                    CHECK( P_PROC_TYPE = 'ATSS' P_PROC_NAME = '%' ).
                  else.
                    CHECK( P_PROC_TYPE = 'ATSS' P_PROC_NAME = L_NAME ).
                  endif.
              endcase.
            endif.

          when 'TOP-OF-PAGE'.
            if GET_TOKEN_REL( 2 ) = 'DURING'.
              CHECK( P_PROC_TYPE = 'TOPS' P_PROC_NAME = '%' ).
            else.
              CHECK( P_PROC_TYPE = 'TOPA' P_PROC_NAME = '%' ).
            endif.

          when 'END-OF-PAGE'.
            CHECK( P_PROC_TYPE = 'ENPA' P_PROC_NAME = '%' ).

          when 'LOAD-OF-PROGRAM'.
            CHECK( P_PROC_TYPE = 'LDPR' P_PROC_NAME = '%' ).

        endcase.
      enddo.
    catch CX_EXCEPTION into L_EXCP.
      raise event MESSAGE exporting
                 P_SUB_OBJ_TYPE = C_TYPE_INCLUDE
                 P_SUB_OBJ_NAME = L_EXCP->INCLUDE
                 P_LINE         = L_EXCP->LINE
                 P_COLUMN       = L_EXCP->COLUMN
                 P_KIND         = C_WARNING
                 P_TEST         = C_MY_NAME
                 P_CODE         = 'SYNTAX'.
  endtry.
endmethod.



method CHECK .
  data:
    L_INCLUDE      type PROGRAM,
    L_LINE         type I,
    L_COLUMN       type TOKEN_COL,
    L_COMPLEXITY   type I value 1,
    L_STMNTS       type I,
    L_VERSIONS     type I,
    L_COMPLEXITY_C type SYCHAR10,
    L_STMNTS_C     type SYCHAR10,
    L_VERSIONS_C   type SYCHAR10,
    L_NESTED_C     type SYCHAR10,
    L_PARAM_1      type STRING,
    L_TOKEN        type STRING,
    L_PROC_VERSION like line of PROC_VERSIONS,
    L_NESTED       type I,
    L_MAX_NESTED   type I.


  L_INCLUDE = GET_INCLUDE( ).
  L_LINE    = TOKEN_WA-ROW.
  L_COLUMN  = TOKEN_WA-COL.


  do.
    read table REF_SCAN->STATEMENTS index STATEMENT_INDEX into STATEMENT_WA.
    if SY-SUBRC <> 0.
      exit.
    endif.

    add 1 to STATEMENT_INDEX.

    check STATEMENT_WA-FROM <= STATEMENT_WA-TO.
    check STATEMENT_WA-TYPE na 'PS'.



*-- avoid native SQL
*  check STATEMENT_WA-TYPE na 'EMDR'.

    case KEYWORD( ).
      when 'IF' or 'WHILE' or 'LOOP' or 'DO' or 'PROVIDE'.
        if TOKEN_WA-ROW <> 0.
          add 1 to L_COMPLEXITY.
          add 1 to L_NESTED.
          if L_NESTED > L_MAX_NESTED.
            L_MAX_NESTED = L_NESTED.
          endif.
        endif.

      when 'ELSEIF'.
        if TOKEN_WA-ROW <> 0.
          add 1 to L_COMPLEXITY.
        endif.

      when 'ENDIF' or 'ENDWHILE' or 'ENDLOOP' or 'ENDDO' or 'ENDTRY'.
        subtract 1 from L_NESTED.

      when 'TRY'.
        add 1 to L_NESTED.
        if L_NESTED > L_MAX_NESTED.
          L_MAX_NESTED = L_NESTED.
        endif.

      when 'SELECT'.


      when 'ENDSELECT'.
        if TOKEN_WA-ROW <> 0.
          add 1 to L_COMPLEXITY.
          add 1 to L_NESTED.
          if L_NESTED > L_MAX_NESTED.
            L_MAX_NESTED = L_NESTED.
          endif.
          subtract 1 from L_NESTED.
        endif.

      when 'CHECK'.
        if TOKEN_WA-ROW <> 0.
          add 1 to L_COMPLEXITY.
        endif.

      when 'CASE'.
        if PA_WITH_CASE = 'X'.
          add 1 to L_COMPLEXITY.
        endif.
        add 1 to L_NESTED.
        if L_NESTED > L_MAX_NESTED.
          L_MAX_NESTED = L_NESTED.
        endif.

      when 'ENDCASE'.
        subtract 1 from L_NESTED.

      when 'WHEN'.
        if PA_WITH_CASE <> 'X' and TOKEN_WA-ROW <> 0.
          if GET_TOKEN_REL( 2 ) <> 'OTHERS'.
            add 1 to L_COMPLEXITY.
          endif.
        endif.

      when 'ENDFORM' or 'ENDFUNCTION' or 'ENDMETHOD' or 'ENDMODULE'.
        exit.

      when 'FORM'
        or 'FUNCTION'
        or 'MODULE'
        or 'START-OF-SELECTION'
        or 'END-OF-SELECTION'
        or 'TOP-OF-PAGE'
        or 'END-OF-PAGE'
        or 'LOAD-OF-PROGRAM'
        or 'INITIALIZATION'
        or 'CLASS'.
        subtract 1 from STATEMENT_INDEX.
        exit.

      when 'GET'.
        if GET_TOKEN_REL( 2 ) <> 'TIME'.
          case GET_TOKEN_REL( 3 ).
            when 'LATE' or 'FIELDS' or ''.
              subtract 1 from STATEMENT_INDEX.
              exit.
          endcase.
        endif.

      when 'AT'.
        L_TOKEN = GET_TOKEN_REL( 2 ).
        if strlen( L_TOKEN ) > 2 and L_TOKEN(2) = 'PF'.
          subtract 1 from STATEMENT_INDEX.
          exit.
        else.
          case L_TOKEN.
            when 'USER-COMMAND'.
              subtract 1 from STATEMENT_INDEX.
              exit.
            when 'LINE-SELECTION'.
              subtract 1 from STATEMENT_INDEX.
              exit.
            when 'SELECTION-SCREEN'.
              subtract 1 from STATEMENT_INDEX.
              exit.
          endcase.
        endif.

        add 1 to L_NESTED.
        if L_NESTED > L_MAX_NESTED.
          L_MAX_NESTED = L_NESTED.
        endif.

        add 1 to L_COMPLEXITY.


      when 'ENDAT'.
        subtract 1 from L_NESTED.


    endcase.

    if PA_VERSION = 'X'.
      loop at REF_SCAN->TOKENS from STATEMENT_WA-FROM to STATEMENT_WA-TO into TOKEN_WA.
        check TOKEN_WA-ROW <> 0.
        CL_CI_PROVIDE_CHECKSUM=>GEN_CHKSUM_FROM_STRING( exporting P_PARAM     = TOKEN_WA-STR
                                                        changing  P_CRC_VALUE = L_PROC_VERSION-CRC ).
      endloop.
    endif.

    add 1 to L_STMNTS.

  enddo.
  L_PROC_VERSION-PROC_TYPE = P_PROC_TYPE.
  L_PROC_VERSION-PROC_NAME = P_PROC_NAME.
  collect L_PROC_VERSION into PROC_VERSIONS.

  loop at PROC_VERSIONS transporting no fields where PROC_TYPE = P_PROC_TYPE and PROC_NAME = P_PROC_NAME.
    add 1 to L_VERSIONS.
  endloop.

  L_COMPLEXITY_C = L_COMPLEXITY.
  L_NESTED_C     = L_MAX_NESTED.
  L_STMNTS_C     = L_STMNTS.
  L_VERSIONS_C   = L_VERSIONS.

  concatenate P_PROC_TYPE P_PROC_NAME L_STMNTS_C L_COMPLEXITY_C L_NESTED_C L_VERSIONS_C into L_PARAM_1 separated by ' '.
  condense L_PARAM_1.

  raise event MESSAGE exporting
                  P_SUB_OBJ_TYPE = C_TYPE_INCLUDE
                  P_SUB_OBJ_NAME = L_INCLUDE
                  P_LINE         = L_LINE
                  P_COLUMN       = L_COLUMN
                  P_KIND         = C_NOTE
                  P_TEST         = C_MY_NAME
                  P_CODE         = C_CODE_SUMMARY
                  P_PARAM_1      = L_PARAM_1.

  if L_COMPLEXITY >= PA_COMPLEXITY.
    raise event MESSAGE exporting
                  P_SUB_OBJ_TYPE = C_TYPE_INCLUDE
                  P_SUB_OBJ_NAME = L_INCLUDE
                  P_LINE         = L_LINE
                  P_COLUMN       = L_COLUMN
                  P_KIND         = C_WARNING
                  P_TEST         = C_MY_NAME
                  P_CODE         = C_CODE_COMPLEXITY
                  P_PARAM_1      = L_COMPLEXITY_C.
  endif.

  if L_STMNTS >= PA_STMNTS.
    raise event MESSAGE exporting
                  P_SUB_OBJ_TYPE = C_TYPE_INCLUDE
                  P_SUB_OBJ_NAME = L_INCLUDE
                  P_LINE         = L_LINE
                  P_COLUMN       = L_COLUMN
                  P_KIND         = C_WARNING
                  P_TEST         = C_MY_NAME
                  P_CODE         = C_CODE_STMNTS
                  P_PARAM_1      = L_STMNTS_C.
  endif.

  if L_NESTED >= PA_NESTED.
    raise event MESSAGE exporting
                  P_SUB_OBJ_TYPE = C_TYPE_INCLUDE
                  P_SUB_OBJ_NAME = L_INCLUDE
                  P_LINE         = L_LINE
                  P_COLUMN       = L_COLUMN
                  P_KIND         = C_WARNING
                  P_TEST         = C_MY_NAME
                  P_CODE         = C_CODE_NESTED
                  P_PARAM_1      = L_NESTED_C.
  endif.

  if L_VERSIONS >= PA_VERSIONS.
    raise event MESSAGE exporting
                  P_SUB_OBJ_TYPE = C_TYPE_INCLUDE
                  P_SUB_OBJ_NAME = L_INCLUDE
                  P_LINE         = L_LINE
                  P_COLUMN       = L_COLUMN
                  P_KIND         = C_WARNING
                  P_TEST         = C_MY_NAME
                  P_CODE         = C_CODE_VERSIONS
                  P_PARAM_1      = L_VERSIONS_C.
  endif.







endmethod.

Read only

Former Member
0 Likes
548

It was impossible to reach the solution due to fact, that some CI classes were set as a final, so I was unable to inherit from them, to modify behaviour.