‎2006 Oct 24 12:54 PM
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
‎2006 Nov 07 8:48 AM
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.
‎2011 Jul 20 6:54 PM
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.