Show nesting in ABAP code
Copy and paste the attached function module-code to create a utility to show you how your ABAP is nested.
Continue Reading This Article
Enjoy this article as well as all of our content, including E-Guides, news, tips and more.
1) FORM any_form. IF this = true. | CASE x. | ] WHEN '1'. | ] WHEN '2'. | ] [ statement. | ] [ IF that = true. | ] [ } statement. | ] [ } statement. | ] [ } statement. | ] [ } CASE t. | ] [ } { WHEN OTHERS. | ] [ } ENDCASE. | ] [ ENDIF. | ] WHEN '3'. | ] [ statement. | ] [ statement. | ] WHEN OTHERS. | ENDCASE. ENDIF. ENDFORM. 2) FUNCTION z_cdf_lineup_commands . *"---------------------------------------------------------------------- *"*"Local interface: *" IMPORTING *" VALUE(IP_LINEUP_TXT) TYPE C DEFAULT '|][}{' *" CHANGING *" REFERENCE(CP_PGM_TEXT) TYPE ZCDF_T_PGM_TEXT *"---------------------------------------------------------------------- DATA: lw_nest_ind(1) TYPE c, "nest character needed? lw_overlay_txt(80) TYPE c, "line of nesting markings lw_txt_len_num TYPE i, "length of marking chars lw_char_ofs_num TYPE i, "offset of nesting character to use lw_cmnd_ofs_num TYPE i, "offset of SAP command of interest lw_deep_num TYPE i. "how many nested levels deep? FIELD-SYMBOLS: <l_pgm_line> TYPE zcdf_pgm_text. * Find first space, then sy-fdpos tells length of data. IF ip_lineup_txt CA '# #'. lw_txt_len_num = sy-fdpos. ELSE. "no blanks DESCRIBE FIELD ip_lineup_txt LENGTH lw_txt_len_num. ENDIF. * LOOP thru program text and add nesting markings. LOOP AT cp_pgm_text ASSIGNING <l_pgm_line>. * Avoid comment lines. IF <l_pgm_line>-txt(1) NE '*'. * Find first command on line. * Only a single comand per line * The command cannot start in column 1, must be * in a processing block. IF <l_pgm_line>-txt CS ' IF ' OR <l_pgm_line>-txt CS ' CASE ' OR <l_pgm_line>-txt CS ' LOOP ' OR <l_pgm_line>-txt CS ' LOOP. ' OR <l_pgm_line>-txt CS ' SELECT ' OR <l_pgm_line>-txt CS ' CATCH ' OR <l_pgm_line>-txt CS ' DEFINE ' OR <l_pgm_line>-txt CS ' TRY ' OR <l_pgm_line>-txt CS ' BEGIN OF ' OR <l_pgm_line>-txt CS ' WHILE '. * Save offset of the command without leading space. lw_cmnd_ofs_num = sy-fdpos + 1. * Avoid command in a line ending comment. First get the offset * of the start of the comment if any. If found, sy-fdpos * will contain the offset. If not found, sy-fdpos is set * to the length of the text. IF <l_pgm_line>-txt CS '"'. ENDIF. * Only continue if the command was found before the ". IF lw_cmnd_ofs_num < sy-fdpos. lw_nest_ind = 'X'. * Special handling for SELECT. Some versions of SELECT are * NOT loops, for example SELECT SINGLE and * SELECT...INTO TABLE. If not a loop, then no nesting * mark required. IF <l_pgm_line>-txt+lw_cmnd_ofs_num(6) = 'SELECT'. lw_nest_ind = space. PERFORM check_select_command USING cp_pgm_text sy-tabix CHANGING lw_nest_ind. ENDIF. * Add nesting character if needed. IF lw_nest_ind = 'X'. lw_deep_num = lw_deep_num + 1. lw_char_ofs_num = ( lw_deep_num - 1 ) MOD lw_txt_len_num. * If the offset has become negative, * something strange has happened. For example, this can * happen if IFs are not indented properly. * Avoid negative offsets. IF lw_char_ofs_num < 0. lw_char_ofs_num = 0. ENDIF. * Set marking in overlay line. lw_overlay_txt+lw_cmnd_ofs_num(1) = ip_lineup_txt+lw_char_ofs_num(1). * Special handling for CASE. WHEN must follow so provide for * a marking of WHEN. IF <l_pgm_line>-txt+lw_cmnd_ofs_num(4) = 'CASE'. lw_deep_num = lw_deep_num + 1. lw_char_ofs_num = ( lw_deep_num - 1 ) MOD lw_txt_len_num. * If the offset has become negative, * something strange has happened. For example, this can * happen if IFs are not indented properly. * Avoid negative offsets. IF lw_char_ofs_num < 0. lw_char_ofs_num = 0. ENDIF. * Set marking in overlay line for upcoming WHEN statement. * Assumption is that indentation is 2 characters. lw_cmnd_ofs_num = lw_cmnd_ofs_num + 2. lw_overlay_txt+lw_cmnd_ofs_num(1) = ip_lineup_txt+lw_char_ofs_num(1). ENDIF. ENDIF. ENDIF. ENDIF. * Now check for ending commands. * Starting and ending commands on the same line are supported. * Multiple commands on a line are not supported. IF <l_pgm_line>-txt CS ' ENDIF. ' OR <l_pgm_line>-txt CS ' ENDCASE. ' OR <l_pgm_line>-txt CS ' ENDLOOP. ' OR <l_pgm_line>-txt CS ' ENDSELECT. ' OR <l_pgm_line>-txt CS ' ENDCATCH. ' OR <l_pgm_line>-txt CS ' ENDTRY. ' OR <l_pgm_line>-txt CS ' END-OF_DEFINITION. ' OR <l_pgm_line>-txt CS ' END OF ' OR <l_pgm_line>-txt CS ' ENDWHILE. '. * Save offset of the command without leading space. lw_cmnd_ofs_num = sy-fdpos + 1. * Avoid ending command in a line ending comment. IF <l_pgm_line>-txt CS '"'. ENDIF. * Only continue if the ending command was found before the ". IF lw_cmnd_ofs_num < sy-fdpos. * Find the current end of the overlay line. IF lw_overlay_txt CP '*# '. lw_char_ofs_num = sy-fdpos - 1. * Something strange has happened. Avoid negative offsets. IF lw_char_ofs_num < 0. lw_char_ofs_num = 0. ENDIF. * Remove marking (+ everything to the right) * from overlay line. lw_overlay_txt+lw_char_ofs_num = space. lw_deep_num = lw_deep_num - 1. * Special handling for ENDCASE. When CASE found, both * CASE and WHEN were marked. Now for ENDCASE, undo * mark for both CASE and WHEN. IF <l_pgm_line>-txt+lw_cmnd_ofs_num(7) = 'ENDCASE'. * Find current end of overlay line. IF lw_overlay_txt CP '*# '. lw_char_ofs_num = sy-fdpos - 1. * Something strange has happened. Avoid negative offsets. IF lw_char_ofs_num < 0. lw_char_ofs_num = 0. ENDIF. * Remove marking (+ everything to the right) * from overlay lw_overlay_txt+lw_char_ofs_num = space. lw_deep_num = lw_deep_num - 1. ENDIF. ENDIF. ENDIF. ENDIF. ENDIF. ENDIF. * Insert nesting marks into source code. OVERLAY <l_pgm_line>-txt WITH lw_overlay_txt. ENDLOOP. ENDFUNCTION. *---------------------------------------------------------------------* * Form check_select_command * * Check if a SELECT command is initiating a loop * requiring ENDSELECT * * Input Parameters - * ipt_pgm_text - Program Text;passed by ref to avoid copying * ip_tabix - Index in table where SELECT was found * Changing Parameters - * cp_nest_ind - 'X' indicates SELECT starts a loop *----------------------------------------------------------------------* FORM check_select_command USING ipt_pgm_text TYPE zcdf_t_pgm_text value(ip_tabix) TYPE sy-tabix CHANGING cp_nest_ind TYPE c. DATA: l_period_ind TYPE zgn_ind, l_fdpos TYPE sy-fdpos, lwa_pgm_text TYPE zcdf_pgm_text, l_select_txt TYPE string. cp_nest_ind = space. l_period_ind = space. LOOP AT ipt_pgm_text FROM ip_tabix INTO lwa_pgm_text. * Avoid comment lines. CHECK lwa_pgm_text-txt(1) NE '*'. * Eliminate any line ending comment. IF lwa_pgm_text-txt CS '"'. ENDIF. IF sy-fdpos NE 0 AND sy-fdpos LE 79. lwa_pgm_text-txt+sy-fdpos = space. ENDIF. * If ending period found, eliminate anything after the period. IF lwa_pgm_text-txt CS '.'. ENDIF. IF sy-fdpos NE 0 AND sy-fdpos LE 79. l_period_ind = 'X'. ENDIF. IF sy-fdpos NE 0 AND sy-fdpos LT 79. l_fdpos = sy-fdpos + 1. lwa_pgm_text-txt+l_fdpos = space. ENDIF. * Add to our string. CONCATENATE l_select_txt lwa_pgm_text-txt INTO l_select_txt SEPARATED BY space. * If period found, SELECT end has been reached. IF l_period_ind = 'X'. EXIT. "EXIT the LOOP ENDIF. ENDLOOP. * Our STRING variable now has the complete SELECT command. * Cleanup before we do our searches. CONDENSE l_select_txt. * Look for options determining if loop started. * Loading into an internal table without package size does NOT * start a loop. IF ( l_select_txt CS 'INTO TABLE' OR l_select_txt CS 'INTO CORRESPONDING FIELDS OF TABLE' OR l_select_txt CS 'APPENDING TABLE' OR l_select_txt CS 'APPENDING CORRESPONDING FIELDS OF TABLE' ) AND l_select_txt NS 'PACKAGE SIZE'. cp_nest_ind = space. "no loop EXIT. "EXIT subroutine ENDIF. * SELECT SINGLE does NOT start loop. IF l_select_txt CS 'SELECT SINGLE'. cp_nest_ind = space. "no loop EXIT. "EXIT subroutine ENDIF. * Otherwise, start SELECT LOOP cp_nest_ind = 'X'. ENDFORM. " check_select_command 3) REPORT zcdf_show_program. PARAMETER: pa_rpt TYPE programm OBLIGATORY, pa_ste TYPE rdir_rstat OBLIGATORY DEFAULT 'A'. " 'A'ctive or 'I'nactive source. DATA: t_abap_text TYPE zcdf_t_pgm_text. START-OF-SELECTION. READ REPORT pa_rpt INTO t_abap_text STATE pa_ste. CALL FUNCTION 'Z_CDF_LINEUP_COMMANDS' CHANGING cp_pgm_text = t_abap_text. EDITOR-CALL FOR t_abap_text.