Tip

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. Your code should NOT start in column 1 and Pretty Printer indentation is expected.

Shown below is:
1) Sample output
2) Function module
3) Sample program to invoke function module

Type ZCDF_T_PGM_TEXT is a table type definition, standard table, default key, with structure ZCDF_PGM_TEXT that has a single field called txt that is character, length 80.

The code was written in 4.6C. 4.7 users might want to add the TRY command.

Question/comments? I can be reached at cfolwell@csc.com.
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,

    Requires Free Membership to View

"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.

This was first published in October 2003

There are Comments. Add yours.

 
TIP: Want to include a code block in your comment? Use <pre> or <code> tags around the desired text. Ex: <code>insert code</code>

REGISTER or login:

Forgot Password?
By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy
Sort by: OldestNewest

Forgot Password?

No problem! Submit your e-mail address below. We'll send you an email containing your password.

Your password has been sent to:

Disclaimer: Our Tips Exchange is a forum for you to share technical advice and expertise with your peers and to learn from other enterprise IT professionals. TechTarget provides the infrastructure to facilitate this sharing of information. However, we cannot guarantee the accuracy or validity of the material submitted. You agree that your use of the Ask The Expert services and your reliance on any questions, answers, information or other materials received through this Web site is at your own risk.