Intro
Some years ago I wrote a tiny program exploring program source code covering also all includes. Now I did a rewrite, it is a bit OOP and it offers ability to explore also repository classes used within the report.What it offers is obvious from input selection screen
Possible options
- Investigate transaction or program directly
- From transaction it takes program name and continues as with ordinary program.
- Within program it consider the following:
- main report
- all includes - used also for local classes
- all repository classes defined as:
- REF TO something - it is further checked for class existance
- something=>method( ) - it considers static calls as well
- Furthermore there is an option to check just custom namespace classes + Y/Z ones. It means classes under the same namespace as main report. Otherwise it reads all the classes including SAP ones as e.g. SALV classes etc.
- It does the same for repository class as an input.
- You can provide free text as an input or regular expression to be checked against line of coding.
Some examples
Possible output for "select" as a free text. You can check the below picture, the pattern exists within main program and used class as well.Free text input "auth 02"
The result
Regex - all static class calls
The result
Regex - all number from 2 up to 8 digits
The result
Source
- http://www.sapnet.ru/viewtopic.php?p=7706 - this article helped a lot, thanks to the author!
- https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abenregex_syntax_specials.htm - good regular expression intro
Source code
*&---------------------------------------------------------------------*
*& Report /namespace/REPORT_REGEX_SEARCH
*-----------------------------------------------------------------------
* Purpose: Search ABAP source code by regex
*-----------------------------------------------------------------------
REPORT /namespace/report_regex_search MESSAGE-ID 00.
INCLUDE /namespace/report_regex_search_c01.
*******************************************************************
* SCREENS - choose transaction or program
*******************************************************************
SELECTION-SCREEN BEGIN OF BLOCK frame1 WITH FRAME TITLE TEXT-001.
" Transaction
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS: r_trans RADIOBUTTON GROUP grp1 USER-COMMAND flagcommand1.
SELECTION-SCREEN COMMENT 3(60) TEXT-002. " Transaction
SELECTION-SCREEN END OF LINE.
" Program
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS: r_prog RADIOBUTTON GROUP grp1 DEFAULT 'X'.
SELECTION-SCREEN COMMENT 3(60) TEXT-003. " Program
SELECTION-SCREEN END OF LINE.
" Class
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS: r_class RADIOBUTTON GROUP grp1.
SELECTION-SCREEN COMMENT 3(60) TEXT-005. " Class
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN SKIP.
PARAMETERS: p_tcode TYPE tstc-tcode, " Transaction Code
p_prog TYPE trdir-name MATCHCODE OBJECT progname, " Program name
p_class TYPE seoclass-clsname MATCHCODE OBJECT seoclsnamef4. " Class name
SELECTION-SCREEN END OF BLOCK frame1.
SELECTION-SCREEN BEGIN OF BLOCK frame2 WITH FRAME TITLE TEXT-004.
" Free text
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS: r_text RADIOBUTTON GROUP grp2 USER-COMMAND flagcommand2 DEFAULT 'X'.
SELECTION-SCREEN COMMENT 3(60) TEXT-006. " Free text switch
SELECTION-SCREEN END OF LINE.
" Regular expresson
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS: r_regul RADIOBUTTON GROUP grp2.
SELECTION-SCREEN COMMENT 3(60) TEXT-007. " Regular expression switch
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN SKIP.
" Inputs as e.g.:
* '^.+(\d{4}).+$'. " all four digits values in coding
* `^[^\*].+(')(\d{4})(').+$`. " all uncommented lines
* `^[\*].+(')(\d{4})(').+$`. " all commented lines starting with *
* `^.+(\BTRY\B).+$`. " get TRY statement lines, here case insensitive
PARAMETERS p_patern TYPE c LENGTH 100 LOWER CASE. " Pattern to be found
PARAMETERS p_own_cl AS CHECKBOX DEFAULT 'X'. " Process only own namespace classes + Y/Z ones
SELECTION-SCREEN END OF BLOCK frame2.
*******************************************************************
AT SELECTION-SCREEN OUTPUT . " PBO action (hide/show)
*******************************************************************
LOOP AT SCREEN. " Hiding
IF ( r_prog NE 'X' ) AND ( screen-name CS 'p_prog' ).
screen-active = 0.
MODIFY SCREEN.
CONTINUE.
ENDIF.
IF ( r_trans NE 'X' ) AND ( screen-name CS 'p_tcode' ).
screen-active = 0.
MODIFY SCREEN.
CONTINUE.
ENDIF.
IF ( r_class NE 'X' ) AND ( screen-name CS 'p_class' ).
screen-active = 0.
MODIFY SCREEN.
CONTINUE.
ENDIF.
IF ( r_trans NE 'X' ) AND ( r_prog NE 'X' ) AND ( screen-name CS 'p_own_cl' ).
screen-active = 0.
MODIFY SCREEN.
CONTINUE.
ENDIF.
ENDLOOP.
*******************************************************************
AT SELECTION-SCREEN. " PAI check
*******************************************************************
* Get program name out of transaction
IF sy-ucomm EQ 'ONLI'. " Check done only after pressing of submit button
IF r_trans EQ 'X'.
" Check transaction existance
CONDENSE p_tcode NO-GAPS.
CLEAR p_prog.
SELECT SINGLE pgmna
FROM tstc
INTO p_prog
WHERE tcode = p_tcode.
IF sy-subrc NE 0.
MESSAGE e001 WITH 'Transaction does not exist : ' p_tcode.
ENDIF.
ELSEIF r_prog EQ 'X'.
" Check program existance
SELECT SINGLE name
FROM trdir
INTO p_prog
WHERE name = p_prog.
IF sy-subrc NE 0.
MESSAGE e001 WITH 'Program does not exist : ' p_prog.
ENDIF.
ELSEIF r_class EQ 'X'.
CONDENSE p_class NO-GAPS.
IF p_class IS INITIAL.
MESSAGE e001 WITH 'There is no repository class to be processed.'.
ENDIF.
" Check class existance
SELECT SINGLE clsname
FROM seoclass
INTO p_class
WHERE clsname = p_class.
IF sy-subrc NE 0.
MESSAGE e001 WITH 'Repository class does not exist : ' p_class.
ENDIF.
ENDIF.
ENDIF.
*******************************************************************
START-OF-SELECTION.
*******************************************************************
DATA: gv_code_src TYPE c LENGTH 1. " P - program, C - class
IF ( r_trans EQ abap_true ) OR ( r_prog EQ abap_true ).
gv_code_src = 'P'. " = Program
ELSE.
gv_code_src = 'C'. " = Class
* else 'F' = function module - possibly in future etc.
ENDIF.
lcl_main_regex=>self->run(
iv_code_src = gv_code_src " P - program, C - class
iv_regex_src = r_regul " String or Regular expression
iv_pattern = p_patern " Searched pattern
iv_prog = p_prog " Program name
iv_class = p_class " Repository class name
iv_own_cl = p_own_cl " Explore/process only classes from custom namespace (takem from program name) or Z/Y classes
).
*&---------------------------------------------------------------------*
*& Include /namespace/REPORT_REGEX_SEARCH_C01
*&---------------------------------------------------------------------*
CLASS lcl_main_regex DEFINITION CREATE PRIVATE FINAL.
PUBLIC SECTION.
CLASS-DATA
self TYPE REF TO lcl_main_regex.
CLASS-METHODS
class_constructor.
METHODS
run
IMPORTING
iv_code_src TYPE char1
iv_regex_src TYPE abap_bool
iv_pattern TYPE clike
iv_prog TYPE progname
iv_class TYPE seoclsname
iv_own_cl TYPE flag.
PRIVATE SECTION.
TYPES:
BEGIN OF ts_include,
prgname TYPE progname,
END OF ts_include,
BEGIN OF ts_code_line,
src_type TYPE string,
src_name TYPE string,
line_num TYPE i,
src_code TYPE string,
END OF ts_code_line,
tt_include TYPE STANDARD TABLE OF ts_include,
tt_code_textpool TYPE TABLE OF textpool,
tt_code_str TYPE STANDARD TABLE OF string. " Note: edpline (char72) is short for some cases
CONSTANTS:
" Get possible class from data declaration
cv_class_ref TYPE string VALUE '^.{0,}\s+[Rr][Ee][Ff][[:space:]]{1,}[Tt][Oo]\s+(\S*[^,\.\s]).+$',
" Get class out of static method call
cv_class_static TYPE string VALUE '^.{0,}(\S*)(=>).+$',
" Get class/program prefix - custom namespace
cv_namespace_prefix TYPE string VALUE '^.{0,}[/](\S*)[/].+$'.
DATA:
v_total_line_num TYPE i,
v_found_flag TYPE abap_bool,
t_regex_class TYPE STANDARD TABLE OF string,
t_clsname TYPE STANDARD TABLE OF string,
t_target_code_line TYPE STANDARD TABLE OF ts_code_line,
o_ref TYPE REF TO cx_root.
METHODS:
convert_code_edpline
IMPORTING it_code TYPE seop_source
EXPORTING et_code TYPE tt_code_str,
convert_code_textpool
IMPORTING it_code TYPE tt_code_textpool
EXPORTING et_code TYPE tt_code_str,
create_regex
IMPORTING iv_pattern TYPE clike
RETURNING VALUE(rv_regex) TYPE string,
check_class_exist
IMPORTING iv_class TYPE string
iv_own_cl TYPE flag
iv_prog TYPE progname
RETURNING VALUE(rv_exist) TYPE abap_bool,
process_class_includes
IMPORTING
iv_class TYPE string
iv_regex TYPE clike,
get_process_class_source
IMPORTING
iv_regex TYPE clike
iv_class TYPE seoclskey
iv_inctype TYPE c,
get_program_includes
IMPORTING iv_prog TYPE prgname
EXPORTING et_include TYPE tt_include,
process_program
IMPORTING
iv_prog TYPE progname
iv_regex TYPE string
iv_own_cl TYPE flag,
process_class
IMPORTING
iv_class TYPE seoclsname
iv_regex TYPE string,
process_program_includes
IMPORTING
iv_prog TYPE progname
iv_regex TYPE clike
it_include TYPE tt_include,
process_lines
IMPORTING
iv_regex TYPE clike
iv_src_type TYPE clike
iv_src_name TYPE clike
it_src_code TYPE tt_code_str
iv_colect_subclass TYPE abap_bool,
process_final_alv,
regex_classname
IMPORTING
iv_code_line TYPE string,
regex_target_string
IMPORTING
iv_regex TYPE clike
iv_src_type TYPE clike
iv_src_name TYPE clike
iv_line_num TYPE i
iv_code_line TYPE string.
ENDCLASS. "lcl_main_regex DEFINITION
CLASS lcl_main_regex IMPLEMENTATION.
METHOD class_constructor.
CREATE OBJECT self.
APPEND cv_class_ref TO self->t_regex_class.
APPEND cv_class_static TO self->t_regex_class.
ENDMETHOD. "class_constructor
METHOD run.
DATA lv_regex TYPE string.
IF iv_regex_src EQ abap_true.
lv_regex = iv_pattern. " Regular expression
ELSE.
lv_regex = create_regex( iv_pattern = iv_pattern ). " Free string
ENDIF.
IF iv_code_src = 'P'. " = Program
process_program(
iv_prog = iv_prog
iv_regex = lv_regex
iv_own_cl = iv_own_cl
).
ELSEIF iv_code_src = 'C'. " = Class
process_class(
iv_class = iv_class
iv_regex = lv_regex
).
ENDIF.
ENDMETHOD. "run
METHOD convert_code_edpline.
DATA lv_code TYPE string.
CLEAR et_code[].
FIELD-SYMBOLS <f_code> LIKE LINE OF it_code.
LOOP AT it_code ASSIGNING <f_code>.
CLEAR lv_code.
lv_code = <f_code>. " edpline to string
APPEND lv_code TO et_code.
ENDLOOP.
ENDMETHOD.
METHOD convert_code_textpool.
DATA lv_code TYPE string.
CLEAR et_code[].
FIELD-SYMBOLS <f_code> LIKE LINE OF it_code.
LOOP AT it_code ASSIGNING <f_code>.
CLEAR lv_code.
lv_code = <f_code>-entry.
APPEND lv_code TO et_code.
ENDLOOP.
ENDMETHOD.
METHOD create_regex.
DATA:
lt_line TYPE STANDARD TABLE OF string,
lv_pattern TYPE string.
lv_pattern = iv_pattern.
CONDENSE lv_pattern.
SPLIT lv_pattern AT space INTO TABLE lt_line.
rv_regex = '^'.
FIELD-SYMBOLS: <f_line> LIKE LINE OF lt_line.
LOOP AT lt_line ASSIGNING <f_line>.
" Escape stars: e.g for searchings like: "SELECT *"
IF <f_line> EQ '*'.
<f_line> = '\*'.
ENDIF.
CONCATENATE rv_regex '.{0,}(' <f_line> '){1,}' INTO rv_regex.
ENDLOOP.
CONCATENATE rv_regex '.{0,}$' INTO rv_regex.
ENDMETHOD.
METHOD check_class_exist.
DATA:
lv_class TYPE seoclsname,
lv_prefix_cl TYPE string,
lv_prefix_prg TYPE string.
rv_exist = abap_false.
lv_class = iv_class.
TRANSLATE lv_class TO UPPER CASE.
" Check class custom/own namespace
IF iv_own_cl EQ abap_true.
CLEAR lv_prefix_cl.
FIND REGEX cv_namespace_prefix
IN iv_class IGNORING CASE
SUBMATCHES lv_prefix_cl.
CONDENSE lv_prefix_cl.
CLEAR lv_prefix_prg.
FIND REGEX cv_namespace_prefix
IN iv_prog IGNORING CASE
SUBMATCHES lv_prefix_prg.
CONDENSE lv_prefix_prg.
TRANSLATE lv_prefix_prg TO UPPER CASE.
TRANSLATE lv_prefix_cl TO UPPER CASE.
IF ( lv_prefix_prg IS NOT INITIAL ) AND ( lv_prefix_cl IS NOT INITIAL )
AND ( lv_prefix_prg NE lv_prefix_cl ).
RETURN.
ENDIF.
" Check Z/Y classes
IF ( lv_prefix_cl IS INITIAL ) AND ( lv_class NP 'Z*' ) AND ( lv_class NP 'Y*' ).
RETURN.
ENDIF.
ENDIF.
" Check class existence in database
SELECT COUNT( * )
FROM seoclass
WHERE clsname = lv_class.
IF sy-subrc EQ 0.
rv_exist = abap_true.
ENDIF.
ENDMETHOD.
METHOD process_class_includes.
" Inspiration taken from: http://www.sapnet.ru/viewtopic.php?p=7706
DATA:
lv_classkey TYPE seoclskey,
lv_class_src TYPE string,
lt_text TYPE TABLE OF textpool,
lt_types TYPE seoo_types_r,
lt_include TYPE seop_methods_w_include,
lt_source TYPE seop_source,
ls_typkey TYPE seocmpkey,
lt_code_edp TYPE seop_source,
lt_code_str TYPE tt_code_str,
lv_include_name TYPE programm.
FIELD-SYMBOLS:
<fs_type> TYPE seoo_type_r,
<fs_include> TYPE LINE OF seop_methods_w_include.
lv_classkey = iv_class.
TRANSLATE lv_classkey TO UPPER CASE.
" Get class description
CALL FUNCTION 'SEO_CLASS_TYPEINFO_GET'
EXPORTING
clskey = lv_classkey
version = seoc_version_active
with_descriptions = 'X'
IMPORTING
types = lt_types
EXCEPTIONS
not_existing = 1
is_interface = 2
model_only = 3
OTHERS = 4.
IF sy-subrc NE 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
" Gathering together internal type source
LOOP AT lt_types ASSIGNING <fs_type>.
ls_typkey-clsname = <fs_type>-clsname.
ls_typkey-cmpname = <fs_type>-cmpname.
CLEAR lt_code_edp[].
CALL FUNCTION 'SEO_CLASS_GET_TYPE_SOURCE'
EXPORTING
typkey = ls_typkey
IMPORTING
source = lt_code_edp
EXCEPTIONS
_internal_class_not_existing = 1
not_existing = 2
not_edited = 3
OTHERS = 4.
CHECK sy-subrc = 0 AND lt_code_edp[] IS NOT INITIAL.
convert_code_edpline(
EXPORTING it_code = lt_code_edp[]
IMPORTING et_code = lt_code_str
).
CLEAR lv_class_src.
CONCATENATE <fs_type>-clsname <fs_type>-cmpname INTO lv_class_src.
CONDENSE lv_class_src.
process_lines(
iv_regex = iv_regex
iv_src_type = 'CLASS_DEF:'
iv_src_name = lv_class_src
it_src_code = lt_code_str
iv_colect_subclass = abap_false
).
ENDLOOP.
FREE lt_code_str.
FREE lt_code_edp[].
" Extract local definitions (classes, macros)
CALL FUNCTION 'SEO_CLASS_GET_INCLUDE_BY_NAME'
EXPORTING
clskey = lv_classkey
limu = seok_limu_locals
IMPORTING
progname = lv_include_name.
get_process_class_source(
iv_regex = iv_regex
iv_class = lv_classkey
iv_inctype = lv_include_name
).
get_process_class_source(
iv_regex = iv_regex
iv_class = lv_classkey
iv_inctype = seop_ext_class_locals_def
).
get_process_class_source(
iv_regex = iv_regex
iv_class = lv_classkey
iv_inctype = seop_ext_class_locals_imp
).
get_process_class_source(
iv_regex = iv_regex
iv_class = lv_classkey
iv_inctype = seop_ext_class_macros
).
" Process texts
CLEAR lv_include_name.
CALL FUNCTION 'SEO_CLASS_GET_INCLUDE_BY_NAME'
EXPORTING
clskey = lv_classkey
IMPORTING
progname = lv_include_name.
DATA lv_lang TYPE spras.
SELECT spras FROM t002 INTO lv_lang.
REFRESH lt_text.
READ TEXTPOOL lv_include_name INTO lt_text LANGUAGE lv_lang.
CHECK sy-subrc = 0.
convert_code_textpool(
EXPORTING it_code = lt_text
IMPORTING et_code = lt_code_str
).
process_lines(
iv_regex = iv_regex
iv_src_type = 'CLASS_TEXT:'
iv_src_name = lv_classkey
it_src_code = lt_code_str
iv_colect_subclass = abap_false
).
ENDSELECT.
" Load all method includes
CALL FUNCTION 'SEO_CLASS_GET_METHOD_INCLUDES'
EXPORTING
clskey = lv_classkey
IMPORTING
includes = lt_include
EXCEPTIONS
_internal_class_not_existing = 1
OTHERS = 2.
IF sy-subrc NE 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
LOOP AT lt_include ASSIGNING <fs_include>.
CLEAR lt_source[].
CALL FUNCTION 'SEO_METHOD_GET_SOURCE'
EXPORTING
mtdkey = <fs_include>-cpdkey
state = 'A'
IMPORTING
source = lt_source
EXCEPTIONS
_internal_method_not_existing = 1
_internal_class_not_existing = 2
version_not_existing = 3
inactive_new = 4
inactive_deleted = 5
OTHERS = 6.
CHECK sy-subrc = 0.
convert_code_edpline(
EXPORTING it_code = lt_source[]
IMPORTING et_code = lt_code_str
).
process_lines(
iv_regex = iv_regex
iv_src_type = 'CLASS_INC2:'
iv_src_name = <fs_include>-cpdkey
it_src_code = lt_code_str
iv_colect_subclass = abap_false
).
ENDLOOP.
IF sy-subrc NE 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDMETHOD.
METHOD get_process_class_source.
DATA:
lt_code_edp TYPE seop_source,
lt_code_str TYPE tt_code_str,
lv_class_src TYPE string.
CALL FUNCTION 'SEO_CLASS_GET_INCLUDE_SOURCE'
EXPORTING
clskey = iv_class
inctype = iv_inctype
IMPORTING
source = lt_code_edp
EXCEPTIONS
_internal_class_not_existing = 0
not_existing = 0
OTHERS = 0.
convert_code_edpline(
EXPORTING it_code = lt_code_edp
IMPORTING et_code = lt_code_str
).
CONCATENATE iv_class iv_inctype INTO lv_class_src.
CONDENSE lv_class_src.
process_lines(
iv_regex = iv_regex
iv_src_type = 'CLASS_INC:'
iv_src_name = lv_class_src
it_src_code = lt_code_str
iv_colect_subclass = abap_false
).
FREE lt_code_edp.
FREE lt_code_str.
ENDMETHOD.
METHOD get_program_includes.
" Get include list of program
CALL FUNCTION 'GET_INCLUDETAB'
EXPORTING
progname = iv_prog
TABLES
incltab = et_include.
" Add main program itself
APPEND iv_prog TO et_include.
ENDMETHOD.
METHOD process_program.
DATA lt_include TYPE STANDARD TABLE OF ts_include.
CLEAR t_clsname.
get_program_includes(
EXPORTING iv_prog = iv_prog
IMPORTING et_include = lt_include
).
process_program_includes(
iv_prog = iv_prog
iv_regex = iv_regex
it_include = lt_include
).
" Process program repository classes
FIELD-SYMBOLS <f_class> LIKE LINE OF t_clsname.
LOOP AT t_clsname ASSIGNING <f_class>.
IF check_class_exist(
iv_class = <f_class>
iv_own_cl = iv_own_cl
iv_prog = iv_prog
) EQ abap_true.
process_class_includes(
iv_class = <f_class>
iv_regex = iv_regex
).
ENDIF.
ENDLOOP.
process_final_alv( ).
ENDMETHOD.
METHOD process_class.
DATA lv_class TYPE string.
lv_class = iv_class.
process_class_includes(
iv_class = lv_class
iv_regex = iv_regex
).
process_final_alv( ).
ENDMETHOD.
METHOD process_program_includes.
DATA:
lv_srctype TYPE string,
lt_code TYPE tt_code_str.
FIELD-SYMBOLS:
<f_include> LIKE LINE OF it_include.
" Get includes content
LOOP AT it_include ASSIGNING <f_include>.
" Set source type
CLEAR lv_srctype.
IF <f_include>-prgname EQ iv_prog.
lv_srctype = 'MAIN_PROG:'.
ELSE.
lv_srctype = 'INCLUDE:'.
ENDIF.
" Load code lines
READ REPORT <f_include>-prgname INTO lt_code.
process_lines(
iv_regex = iv_regex
iv_src_type = lv_srctype
iv_src_name = <f_include>-prgname
it_src_code = lt_code
iv_colect_subclass = abap_true
).
FREE lt_code[].
ENDLOOP.
ENDMETHOD.
METHOD process_lines.
DATA:
lv_line_num TYPE i.
FIELD-SYMBOLS:
<f_code_line> LIKE LINE OF it_src_code.
LOOP AT it_src_code ASSIGNING <f_code_line>.
" Line counters
lv_line_num = lv_line_num + 1.
v_total_line_num = v_total_line_num + 1.
" Does string match the pattern for class declaration or static usage?
IF iv_colect_subclass EQ abap_true.
regex_classname( iv_code_line = <f_code_line> ).
ENDIF.
" Does string match the regex pattern?
regex_target_string(
iv_regex = iv_regex
iv_src_type = iv_src_type
iv_src_name = iv_src_name
iv_line_num = lv_line_num
iv_code_line = <f_code_line>
).
ENDLOOP. " lines
ENDMETHOD.
METHOD process_final_alv.
IF v_found_flag NE abap_true.
WRITE 'Pattern WAS NOT FOUND within the source code.'.
ELSE.
DATA:
lo_salv TYPE REF TO cl_salv_table,
lo_cols TYPE REF TO cl_salv_columns,
lo_col TYPE REF TO cl_salv_column.
TRY.
CALL METHOD cl_salv_table=>factory
EXPORTING
list_display = if_salv_c_bool_sap=>true
IMPORTING
r_salv_table = lo_salv
CHANGING
t_table = t_target_code_line.
CATCH cx_root INTO o_ref.
WRITE:/ 'ALV error occured : ', o_ref->get_text( ).
RETURN.
ENDTRY.
lo_cols = lo_salv->get_columns( ).
lo_cols->set_optimize( if_salv_c_bool_sap=>true ).
TRY.
lo_col = lo_cols->get_column( 'SRC_TYPE' ).
lo_col->set_medium_text( 'Source' ).
lo_col = lo_cols->get_column( 'SRC_NAME' ).
lo_col->set_medium_text( 'Name' ).
lo_col = lo_cols->get_column( 'LINE_NUM' ).
lo_col->set_medium_text( 'Line' ).
lo_col = lo_cols->get_column( 'SRC_CODE' ).
lo_col->set_medium_text( 'Coding' ).
CATCH cx_root INTO o_ref.
WRITE:/ 'ALV columns error occured : ', o_ref->get_text( ).
RETURN.
ENDTRY.
lo_salv->display( ).
ENDIF.
WRITE:/,/ 'Total number of explored lines: ', v_total_line_num.
ENDMETHOD.
METHOD regex_classname.
DATA:
lv_clsname TYPE string.
FIELD-SYMBOLS:
<f_regex_class> LIKE LINE OF t_regex_class.
LOOP AT t_regex_class ASSIGNING <f_regex_class>.
CLEAR lv_clsname.
FIND REGEX <f_regex_class>
IN iv_code_line IGNORING CASE
SUBMATCHES lv_clsname.
CONDENSE lv_clsname.
IF lv_clsname IS NOT INITIAL.
APPEND lv_clsname TO t_clsname.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD regex_target_string.
DATA:
lo_matcher TYPE REF TO cl_abap_matcher,
lv_match TYPE c LENGTH 1,
lv_regex TYPE string,
ls_target_line TYPE ts_code_line.
" Input searched regex
MOVE iv_regex TO lv_regex.
" Does string match the regex pattern?
lv_match = abap_false.
TRY.
FREE lo_matcher.
lo_matcher = cl_abap_matcher=>create(
pattern = lv_regex
ignore_case = abap_true
text = iv_code_line
).
lv_match = lo_matcher->match( ).
CATCH cx_root INTO o_ref.
WRITE:/ 'Input regex error occured : ', o_ref->get_text( ).
RETURN.
ENDTRY.
IF lv_match EQ abap_true.
CLEAR ls_target_line.
ls_target_line-src_type = iv_src_type.
ls_target_line-src_name = iv_src_name.
ls_target_line-line_num = iv_line_num.
ls_target_line-src_code = iv_code_line.
CONDENSE ls_target_line-src_type.
CONDENSE ls_target_line-src_name.
APPEND ls_target_line TO t_target_code_line.
v_found_flag = abap_true. " General flag
ENDIF.
ENDMETHOD.
ENDCLASS.