Source Scan
Source Scan
---*
* Scan a set of source code for a particular string
*-------------------------------------------------------------------
---*
REPORT rs_abap_source_scan MESSAGE-ID eu.
TYPE-POOLS:
slis,
sscr.
TABLES:
seoclasstx,
tadir,
tlibt,
d020s,
trdir.
CLASS:
lcl_source_scan DEFINITION DEFERRED.
DATA:
lo_sscan TYPE REF TO lcl_source_scan,
lv_sstring TYPE text255,
lv_appl TYPE taplt-appl.
*-------------------------------------------------------------------
---*
* CLASS lcx_scan_exceptions DEFINITION
*-------------------------------------------------------------------
---*
* Exceptions for source scanning
*-------------------------------------------------------------------
---*
CLASS lcx_scan_exceptions DEFINITION INHERITING FROM cx_static_check
FINAL.
ENDCLASS. "lcx_scan_exceptions DEFINITION
*-------------------------------------------------------------------
---*
* CLASS lcl_source_scan DEFINITION
*-------------------------------------------------------------------
---*
* ABAP source scanner
*-------------------------------------------------------------------
---*
CLASS lcl_source_scan DEFINITION FINAL.
PUBLIC SECTION.
METHODS:
constructor,
f4_class
CHANGING
cv_class_name TYPE clike,
f4_function_group
IMPORTING
iv_group_name TYPE clike,
f4_repname
CHANGING
cv_repname TYPE clike,
pbo,
start.
PROTECTED SECTION.
TYPES:
BEGIN OF ty_dynpro,
repname LIKE d020s-prog,
dynnr LIKE d020s-dnum,
END OF ty_dynpro.
TYPES:
BEGIN OF ty_ls_objname,
report TYPE sy-repid,
dynnr TYPE sy-dynnr,
END OF ty_ls_objname.
DATA:
go_alv TYPE REF TO cl_salv_hierseq_table,
gv_hit_count TYPE i,
gv_sstring TYPE string,
gv_dynp_found TYPE xfeld,
gv_vers_found TYPE xfeld,
gt_dynpro TYPE STANDARD TABLE OF ty_dynpro,
gt_object TYPE STANDARD TABLE OF tadir-obj_name,
gt_vrsd TYPE HASHED TABLE OF vrsd
WITH UNIQUE KEY objname versno,
gt_source TYPE abaptxt255_tab,
gv_report TYPE syrepid,
gv_dynpro TYPE sydynnr,
BEGIN OF gs_alv_header,
repname TYPE tadir-obj_name,
dynnr TYPE sy-dynnr,
expand TYPE xfeld,
versno TYPE vrsd-versno,
END OF gs_alv_header,
BEGIN OF gs_alv_item,
repname TYPE sy-repid,
dynnr TYPE sy-dynnr,
versno TYPE vrsd-versno,
line_no TYPE rsrow,
text TYPE text255,
hit TYPE xfeld,
cell_color TYPE lvc_t_scol,
END OF gs_alv_item,
CONSTANTS:
gc_x TYPE xfeld VALUE 'X'.
METHODS:
add_to_hitlist
IMPORTING
iv_report TYPE clike
iv_dynpro TYPE clike OPTIONAL
iv_source_line TYPE clike
iv_tabix TYPE sy-tabix
iv_hit TYPE xfeld
iv_versno TYPE vrsd-versno,
call_abap_editor
IMPORTING
is_alv_item LIKE gs_alv_item,
call_screen_painter
IMPORTING
is_alv_item LIKE gs_alv_item,
display,
display_abap_version
IMPORTING
is_alv_item LIKE gs_alv_item,
display_screen_painter_version
IMPORTING
is_alv_item LIKE gs_alv_item,
display_version_management
IMPORTING
is_alv_header LIKE gs_alv_header,
get_alv_instance,
get_dynpro_flow_logic
IMPORTING
iv_report TYPE clike
iv_dynpro TYPE clike
RETURNING VALUE(rt_dflow) TYPE abaptxt255_tab,
get_hit_set
IMPORTING
iv_report TYPE clike
iv_dynpro TYPE clike OPTIONAL
it_abap TYPE abaptxt255_tab
iv_tabix TYPE sy-tabix
iv_versno TYPE vrsd-versno,
get_version_numbers
IMPORTING
iv_report TYPE clike
iv_dynpro TYPE clike OPTIONAL
RETURNING VALUE(rt_vrsd) LIKE gt_vrsd,
get_dynpros,
get_source_names,
get_source_by_version
IMPORTING
iv_report TYPE clike
iv_dynpro TYPE clike OPTIONAL
iv_versno TYPE vrsd-versno
RETURNING VALUE(rt_abap) TYPE abaptxt255_tab,
get_report_names,
get_function_names,
get_class_names,
get_interface_names,
get_includes,
search_abap_source RAISING lcx_scan_exceptions,
search_dynpro_source RAISING lcx_scan_exceptions,
set_alv_attributes,
on_link_click
FOR EVENT link_click OF cl_salv_events_hierseq
IMPORTING
sender
level
row
column.
*-------------------------------------------------------------------
---*
* CLASS lcl_source_scan IMPLEMENTATION
*-------------------------------------------------------------------
---*
* ABAP source scanner
*-------------------------------------------------------------------
---*
CLASS lcl_source_scan IMPLEMENTATION.
METHOD display_screen_painter_version.
DATA:
lv_object_name TYPE versobjnam,
ls_infolna TYPE vrsinfolna,
ls_infolnb TYPE vrsinfolnb,
ls_vrsd LIKE LINE OF gt_vrsd,
ls_object_name TYPE ty_ls_objname.
ls_object_name-report = is_alv_item-repname.
ls_object_name-dynnr = is_alv_item-dynnr.
lv_object_name = ls_object_name.
ls_infolna = lv_object_name.
MOVE-CORRESPONDING ls_vrsd TO ls_infolnb.
METHOD display_abap_version.
DATA:
lt_trdir TYPE STANDARD TABLE OF trdir,
lv_object_name TYPE versobjnam,
lv_title TYPE sy-title,
lt_abap TYPE abaptxt255_tab.
lv_object_name = is_alv_item-repname.
CONCATENATE 'Programm:'(004)
is_alv_item-repname
'Version'(005)
is_alv_item-versno
INTO lv_title SEPARATED BY space.
ENDMETHOD. "display_abap_version
METHOD call_screen_painter.
CALL FUNCTION 'RS_SCRP'
EXPORTING
abl_line = is_alv_item-line_no
dynnr = is_alv_item-dynnr
progname = is_alv_item-repname
wanted_mode = 'SHOW'
EXCEPTIONS
OTHERS = 0.
ENDMETHOD. "call_screen_painter
METHOD call_abap_editor.
CALL FUNCTION 'EDITOR_PROGRAM'
EXPORTING
appid = 'PG'
display = gc_x
program = is_alv_item-repname
line = is_alv_item-line_no
topline = is_alv_item-line_no
EXCEPTIONS
OTHERS = 0.
ENDMETHOD. "call_abap_editor
METHOD display_version_management.
IF is_alv_header-dynnr IS INITIAL.
* call version management for programs
CALL FUNCTION 'RS_PROGRAM_VERSIONS'
EXPORTING
progname = is_alv_header-repname
EXCEPTIONS
OTHERS = 0.
ELSE.
CALL FUNCTION 'RS_SCRP_VERSION'
EXPORTING
dynnr = is_alv_header-dynnr
progname = is_alv_header-repname
no_update = gc_x.
ENDIF.
ENDMETHOD. "display_version_management
METHOD constructor.
DATA:
ls_restrict TYPE sscr_restrict,
ls_opt_list TYPE sscr_opt_list,
ls_association TYPE sscr_ass.
ls_opt_list-name = 'RESTRICT'.
ls_opt_list-options-cp = gc_x.
ls_opt_list-options-eq = gc_x.
ls_association-kind = 'S'.
ls_association-name = 'SSTRING'.
ls_association-sg_main = 'I'.
ls_association-op_main = ls_association-op_addy = 'RESTRICT'.
ENDMETHOD. "constructor
METHOD get_dynpro_flow_logic.
DATA: ls_dhead TYPE d020s,
lt_dfield TYPE STANDARD TABLE OF d021s,
lt_dflow TYPE STANDARD TABLE OF d022s,
lt_dmatch TYPE STANDARD TABLE OF d023s,
BEGIN OF ls_dynp_id,
prog TYPE d020s-prog,
dnum TYPE d020s-dnum,
END OF ls_dynp_id.
ls_dynp_id-prog = iv_report.
ls_dynp_id-dnum = iv_dynpro.
rt_dflow = lt_dflow.
ENDMETHOD. "get_dynpro_flow_logic
METHOD on_link_click.
DATA:
ls_alv_header LIKE LINE OF gt_alv_header,
ls_alv_item LIKE LINE OF gt_alv_item.
CASE level.
WHEN '1'.
READ TABLE gt_alv_header INDEX row INTO ls_alv_header.
CHECK sy-subrc IS INITIAL.
display_version_management( ls_alv_header ).
WHEN '2'.
READ TABLE gt_alv_item INDEX row INTO ls_alv_item.
CHECK sy-subrc IS INITIAL.
IF ls_alv_item-dynnr IS INITIAL.
IF ls_alv_item-versno IS INITIAL.
call_abap_editor( ls_alv_item ).
ELSE.
display_abap_version( ls_alv_item ).
ENDIF.
METHOD set_alv_attributes.
DATA:
lo_layout TYPE REF TO cl_salv_layout,
lo_events TYPE REF TO cl_salv_events_hierseq,
lo_functions TYPE REF TO cl_salv_functions_list,
lo_level TYPE REF TO cl_salv_hierseq_level,
lo_column TYPE REF TO cl_salv_column_hierseq,
lo_columns TYPE REF TO cl_salv_columns_hierseq,
lt_columns TYPE salv_t_column_ref,
ls_columns LIKE LINE OF lt_columns,
lo_settings TYPE REF TO cl_salv_display_settings,
lv_title TYPE lvc_title,
lv_hits TYPE lvc_title,
ls_color TYPE lvc_s_colo,
ls_layout TYPE salv_s_layout_key,
lt_functions TYPE salv_t_ui_func.
* Layout
ls_layout-report = sy-repid.
ls_layout-handle = 'SCAN'.
lo_layout = go_alv->get_layout( ).
lo_layout->set_key( ls_layout ).
lo_layout->set_save_restriction( ).
* Function keys/buttons
lo_functions = go_alv->get_functions( ).
lo_functions->set_all( gc_x ).
* Display settings
lo_settings = go_alv->get_display_settings( ).
* Title
lv_hits = gv_hit_count.
SHIFT lv_hits LEFT DELETING LEADING space.
CONCATENATE lv_hits
'Treffer'(001)
INTO lv_hits SEPARATED BY space.
CONCATENATE lv_title
gv_sstring
INTO lv_title SEPARATED BY space.
CONCATENATE lv_title
lv_hits
INTO lv_title SEPARATED BY ' - '.
lo_settings->set_list_header( lv_title ).
* Event handling
lo_events = go_alv->get_event( ).
SET HANDLER on_link_click FOR lo_events.
* Field catalog
TRY.
* Field catalog/columns - header table
lo_columns = go_alv->get_columns( '1' ).
lt_columns = lo_columns->get( ).
TRY.
lo_columns->set_expand_column( 'EXPAND' ).
CATCH cx_salv_data_error.
ENDTRY.
WHEN 'DYNNR'.
IF gv_dynp_found IS INITIAL.
ls_columns-r_column->set_technical( ).
ELSE.
ls_columns-r_column->set_output_length( '15' ).
ENDIF.
WHEN 'VERSNO'.
IF gv_vers_found IS INITIAL.
ls_columns-r_column->set_technical( ).
ELSE.
ls_columns-r_column->set_leading_zero( gc_x ).
ls_columns-r_column->set_output_length( '15' ).
TRY.
lo_column ?= ls_columns-r_column.
lo_column->set_cell_type(
if_salv_c_cell_type=>hotspot ).
CATCH cx_sy_move_cast_error.
ENDTRY.
ENDIF.
ENDCASE.
ENDLOOP.
TRY.
lo_columns->set_color_column( 'CELL_COLOR' ).
CATCH cx_salv_data_error.
ENDTRY.
lt_columns = lo_columns->get( ).
WHEN 'VERSNO'.
ls_columns-r_column->set_technical( ).
WHEN 'CELL_COLOR'.
ls_columns-r_column->set_technical( ).
WHEN 'HIT'.
ls_columns-r_column->set_technical( ).
WHEN 'LINE_NO'.
ls_color-col = '4'.
TRY.
lo_column ?= ls_columns-r_column.
lo_column->set_color( ls_color ).
lo_column->set_leading_zero( gc_x ).
CATCH cx_sy_move_cast_error.
ENDTRY.
WHEN 'TEXT'.
TRY.
lo_column ?= ls_columns-r_column.
lo_column->set_cell_type(
if_salv_c_cell_type=>hotspot ).
CATCH cx_sy_move_cast_error.
ENDTRY.
ENDCASE.
ENDLOOP.
CATCH cx_salv_not_found.
ENDTRY.
ENDMETHOD. "set_alv_attributes
METHOD get_alv_instance.
DATA:
lt_alv_bind TYPE salv_t_hierseq_binding,
ls_alv_bind LIKE LINE OF lt_alv_bind.
TRY.
CALL METHOD cl_salv_hierseq_table=>factory
EXPORTING
t_binding_level1_level2 = lt_alv_bind
IMPORTING
r_hierseq = go_alv
CHANGING
t_table_level1 = gt_alv_header
t_table_level2 = gt_alv_item.
CATCH cx_salv_data_error.
CATCH cx_salv_not_found.
ENDTRY.
ENDMETHOD. "get_alv_instance
METHOD f4_repname.
CALL FUNCTION 'REPOSITORY_INFO_SYSTEM_F4'
EXPORTING
object_type = 'PROG'
object_name = cv_repname
suppress_selection = 'X'
IMPORTING
object_name_selected = cv_repname
EXCEPTIONS
cancel = 0.
ENDMETHOD.
"f4_repname
METHOD f4_function_group.
DATA:
lv_fname TYPE dynfnam.
lv_fname = iv_group_name.
ENDMETHOD. "f4_function_group
METHOD f4_class.
CALL FUNCTION 'F4_DD_ALLTYPES'
EXPORTING
object = cv_class_name
suppress_selection = gc_x
display_only = space
only_types_for_clifs = gc_x
IMPORTING
result = cv_class_name.
ENDMETHOD.
"f4_class
METHOD display.
IF gv_hit_count IS INITIAL.
MESSAGE s326 WITH gv_sstring.
RETURN.
ENDIF.
IF sy-batch IS INITIAL.
text = |DISPLAY { gv_hit_count } HITS...|.
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
text = text.
ENDIF.
get_alv_instance( ).
CHECK go_alv IS NOT INITIAL.
set_alv_attributes( ).
go_alv->display( ).
ENDMETHOD. "display
METHOD add_to_hitlist.
DATA:
ls_col LIKE LINE OF gs_alv_item-cell_color.
gs_alv_item-repname = iv_report.
gs_alv_item-dynnr = iv_dynpro.
gs_alv_item-line_no = iv_tabix.
gs_alv_item-versno = iv_versno.
gs_alv_item-text = iv_source_line.
CLEAR gs_alv_item.
ENDMETHOD. "add_to_hitlist
METHOD get_hit_set.
DATA: lv_end TYPE i,
lv_start TYPE i,
lv_xtabix TYPE sy-tabix,
lv_hitline TYPE xfeld.
FIELD-SYMBOLS:
<lv_abap> TYPE any.
lv_start = iv_tabix - plusminu .
lv_end = iv_tabix + plusminu.
IF lv_start < 1.
lv_start = 1.
ENDIF.
lv_xtabix = sy-tabix.
IF lv_start = iv_tabix.
lv_hitline = gc_x.
ELSE.
CLEAR lv_hitline.
ENDIF.
ADD 1 TO lv_start.
ENDWHILE.
ENDMETHOD. "get_hit_set
METHOD get_source_by_version.
DATA:
lv_object_name TYPE versobjnam,
ls_object_name TYPE ty_ls_objname,
lt_trdir TYPE STANDARD TABLE OF trdir,
lt_d022s TYPE STANDARD TABLE OF d022s.
IF iv_dynpro IS INITIAL.
lv_object_name = iv_report.
lv_object_name = ls_object_name.
ENDIF.
ENDMETHOD. "get_source_by_version
METHOD get_version_numbers.
DATA:
ls_objname TYPE ty_ls_objname,
lv_objtype TYPE vrsd-objtype,
lv_objname TYPE versobjnam,
lv_versno TYPE versno,
lt_vrsn TYPE STANDARD TABLE OF vrsn,
lt_vrsd TYPE STANDARD TABLE OF vrsd.
ls_objname-report = iv_report.
ls_objname-dynnr = iv_dynpro.
lv_objname = ls_objname.
IF iv_dynpro IS INITIAL.
lv_objtype = 'REPS'.
ELSE.
lv_objtype = 'DYNP'.
ENDIF.
rt_vrsd = lt_vrsd.
SORT rt_vrsd.
ENDMETHOD. "get_version_Numbers
METHOD search_abap_source.
DATA:
percentage TYPE i,
old_percentage TYPE i VALUE -1,
text TYPE c LENGTH 150.
IF sy-batch IS INITIAL.
percentage = sy-tabix * 100 / lines( gt_object ).
text = |SEARCH ABAP SOURCES ({ sy-tabix }/{ lines( gt_object
) })...|.
search_source( ).
ENDLOOP.
FREE gt_object.
ENDMETHOD.
METHOD search_source.
DATA:
lt_source_vers TYPE abaptxt255_tab,
lv_string_found TYPE xfeld,
lt_vrsd TYPE STANDARD TABLE OF vrsd,
ls_vrsd LIKE LINE OF lt_vrsd,
lv_number TYPE i,
lv_index TYPE i,
lt_results TYPE match_result_tab,
ls_result LIKE LINE OF lt_results,
ls_sstring LIKE LINE OF sstring.
IF p_vers IS INITIAL.
lv_number = 1.
ELSE.
lt_vrsd = get_version_numbers( iv_report = gv_report
iv_dynpro = gv_dynpro ).
DO lv_number TIMES.
CLEAR lv_string_found.
IF sy-index = 1.
CLEAR ls_vrsd.
ELSE.
lv_index = sy-index - 1.
READ TABLE lt_vrsd INDEX lv_index INTO ls_vrsd.
CHECK sy-subrc IS INITIAL.
IF p_regex IS INITIAL.
FIND ALL OCCURRENCES OF ls_sstring-low IN TABLE gt_source
IN CHARACTER MODE
IGNORING CASE
RESULTS lt_results.
ELSE.
TRY.
FIND ALL OCCURRENCES OF REGEX ls_sstring-low IN TABLE
gt_source
IN CHARACTER MODE
IGNORING CASE
RESULTS lt_results.
CATCH cx_sy_regex.
* invalid regex -> stop processing
MESSAGE s384 WITH ls_sstring-low DISPLAY LIKE 'E'.
RAISE EXCEPTION TYPE lcx_scan_exceptions.
ENDTRY.
ENDIF.
lv_string_found = gc_x.
ENDLOOP.
IF lv_string_found IS NOT INITIAL.
* Add ALV header entry
CLEAR gs_alv_header.
gs_alv_header-repname = gv_report.
gs_alv_header-dynnr = gv_dynpro.
gs_alv_header-versno = ls_vrsd-versno.
APPEND gs_alv_header TO gt_alv_header.
ENDMETHOD.
METHOD search_dynpro_source.
IF sy-batch IS INITIAL.
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
text = 'SEARCH DYNPRO SOURCES...'.
ENDIF.
gv_report = ls_dynpro-repname.
gv_dynpro = ls_dynpro-dynnr.
search_source( ).
ENDLOOP.
ENDMETHOD.
METHOD get_dynpros.
CHECK gt_object IS NOT INITIAL.
METHOD get_includes.
DATA:
lt_inc TYPE STANDARD TABLE OF tadir-obj_name,
lt_inc_tmp LIKE lt_inc,
lv_program TYPE sy-repid,
lv_obj TYPE tadir-obj_name,
class_name TYPE seoclsname,
class_includes TYPE seoincl_t.
class_name = lv_obj(30).
TRANSLATE class_name USING '= '.
cl_oo_classname_service=>get_all_class_includes(
EXPORTING class_name = class_name
RECEIVING result = class_includes
EXCEPTIONS OTHERS = 0
).
DELETE class_includes WHERE table_line+30(2) = 'CS' OR
table_line+30(2) = 'CP'.
APPEND LINES OF class_includes TO lt_inc.
lv_obj+31(1) = 'U'.
APPEND lv_obj TO lt_inc.
ENDIF.
REFRESH lt_inc_tmp.
lv_program = lv_obj.
SORT lt_inc.
DELETE ADJACENT DUPLICATES FROM lt_inc.
ENDMETHOD.
METHOD get_report_names.
SELECT obj_name INTO TABLE gt_object
FROM tadir
WHERE pgmid = 'R3TR'
AND object = 'PROG'
AND devclass IN devclass. "#EC
CI_GENBUFF
ENDMETHOD. "get_report_names
METHOD get_function_names.
DATA:
lt_obj TYPE STANDARD TABLE OF tadir-obj_name,
lv_obj TYPE tadir-obj_name,
lv_fgroup TYPE rs38l-area,
lv_program TYPE progname.
FIELD-SYMBOLS:
<lv_obj> LIKE LINE OF lt_obj.
lv_obj = lv_program.
APPEND lv_obj TO gt_object.
ENDLOOP.
ENDMETHOD. "get_function_names
METHOD get_class_names.
DATA lt_obj TYPE STANDARD TABLE OF tadir-obj_name.
DATA ls_obj TYPE tadir-obj_name.
ENDMETHOD.
METHOD get_interface_names.
DATA lt_obj TYPE STANDARD TABLE OF tadir-obj_name.
DATA ls_obj TYPE tadir-obj_name.
SELECT obj_name INTO TABLE lt_obj
FROM tadir
WHERE pgmid = 'R3TR'
AND object = 'INTF'
AND devclass IN devclass
AND obj_name IN p_class. "#EC
CI_GENBUFF
ENDMETHOD.
METHOD get_source_names.
IF repname[] IS NOT INITIAL OR
cnam[] IS NOT INITIAL OR
unam[] IS NOT INITIAL OR
subc[] IS NOT INITIAL OR
appl[] IS NOT INITIAL.
IF rb_code IS INITIAL.
get_dynpros( ).
ENDIF.
ENDMETHOD. "get_source_names
METHOD start.
DATA:
ls_sstring LIKE LINE OF sstring[].
p_regex = gc_x.
ENDIF.
IF sy-batch IS INITIAL.
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
text = 'GET INCLUDES...'.
ENDIF.
get_source_names( ).
get_includes( ).
IF rb_dyn IS INITIAL.
TRY.
search_abap_source( ).
CATCH lcx_scan_exceptions.
RETURN.
ENDTRY.
ENDIF.
IF rb_code IS INITIAL.
TRY.
search_dynpro_source( ).
CATCH lcx_scan_exceptions.
RETURN.
ENDTRY.
ENDIF.
display( ).
ENDMETHOD. "start
METHOD pbo.
DATA ls_screen TYPE screen.
REFRESH sstring[].
CLEAR sstring.
CLEAR p_regex.
INITIALIZATION.
CREATE OBJECT lo_sscan.
a05 = 'Suchbegriff'(a05).
a10 = 'Report/Dynpro Selektion'(a10).
a11 = 'Paket Selektion'(a11).
a12 = 'Funktionsgruppen Selektion'(a12).
a13 = 'Klassen Selektion'(a13).
a20 = 'Suchkriterien'(a20).
a30 = 'Suchbereich'(a30).
AT SELECTION-SCREEN OUTPUT.
lo_sscan->pbo( ).
START-OF-SELECTION.
lo_sscan->start( ).