ABAPdoc documentation on class/method/data definition and report headers is reported (html-style)
"!
A group can have a description
"!
Components can have:
"!
(a set of) #hashtag words
"!
ABAPdoc style comments, embedded in the ZONE script
"!
Reviews, where a user describes why something is good or not so good
"!
Labeled links as URL for documentation references
"!
A component of type class can have a list of method names (to filter out methods that are not relevant to list)
"!
REPORT zone.
DATA gv_okcode TYPE sy-ucomm.
DATA gt_documentheader TYPE STANDARD TABLE OF char255.
DATA: BEGIN OF gs_images,
logo TYPE c LENGTH 170,
background TYPE c LENGTH 170,
END OF gs_images.
CLASS lcl_event_receiver DEFINITION.
PUBLIC SECTION.
CLASS-METHODS handle_sapevent FOR EVENT sapevent OF cl_gui_html_viewer
IMPORTING getdata query_table.
ENDCLASS.
CLASS lcl_document_groups DEFINITION DEFERRED.
CLASS lcl_component_documentor DEFINITION.
PUBLIC SECTION.
CONSTANTS: co_undetermined TYPE c LENGTH 20 VALUE '~???~',
co_field_error TYPE c LENGTH 25 VALUE '(no description)'.
TYPES: BEGIN OF gty_docline,
linenr TYPE i,
content TYPE string,
END OF gty_docline.
TYPES: gty_doclines TYPE SORTED TABLE OF gty_docline WITH UNIQUE KEY linenr.
TYPES: BEGIN OF gty_parameter,
linenr TYPE i,
parameter TYPE string,
pardecltyp TYPE seopardecl, "0=importing, 1=exporting, 2= changing, 3= returning, 9=exception
datatype TYPE string,
optional TYPE boolean,
END OF gty_parameter.
TYPES: gty_parameters TYPE SORTED TABLE OF gty_parameter WITH UNIQUE KEY linenr.
TYPES: BEGIN OF gty_class_details,
author TYPE vseoclass-author,
createdon TYPE vseoclass-createdon,
changedby TYPE vseoclass-changedby,
changedon TYPE vseoclass-changedon,
superclass TYPE seoclsname,
interfaces TYPE string,
linecount TYPE int4,
methods TYPE int4,
redefinitions TYPE int4,
filter_on_methods TYPE boolean,
message TYPE string,
END OF gty_class_details.
TYPES: BEGIN OF gty_report_details,
cnam TYPE trdir-cnam,
cdat TYPE trdir-cdat,
unam TYPE trdir-unam,
udat TYPE trdir-udat,
includes TYPE SORTED TABLE OF char80 WITH UNIQUE KEY table_line,
linecount TYPE sy-dbcnt,
END OF gty_report_details.
TYPES: BEGIN OF gty_function_details,
author TYPE tadir-author,
created_on TYPE tadir-created_on,
area TYPE enlfdir-area,
linecount TYPE sy-dbcnt,
hitcount TYPE sy-dbcnt,
END OF gty_function_details.
TYPES: BEGIN OF gty_table_details,
created_by TYPE e070-as4user,
created_on TYPE e070-as4date,
changed_by TYPE dd02l-as4user,
changed_on TYPE dd02l-as4date,
maintenance TYPE boolean,
dd03l TYPE SORTED TABLE OF dd03l WITH UNIQUE KEY position fieldname,
END OF gty_table_details.
TYPES: BEGIN OF gty_component,
component_type TYPE string,
component_name TYPE string,
description TYPE string,
abapdoc TYPE gty_doclines,
attvalue TYPE string,
parameters TYPE gty_parameters,
read_only TYPE boolean,
method_hitcount TYPE sy-dbcnt,
class TYPE gty_class_details,
report TYPE gty_report_details,
function TYPE gty_function_details,
table TYPE gty_table_details,
devclass TYPE tadir-devclass,
devclass_text TYPE tdevct-ctext,
redefinition TYPE boolean,
END OF gty_component.
TYPES: BEGIN OF gty_user,
user TYPE sy-uname,
fullname TYPE bapiaddr3-fullname,
END OF gty_user.
TYPES: BEGIN OF ty_devclass,
devclass TYPE tdevc-devclass,
parentcl TYPE tdevc-parentcl,
ctext_E TYPE tdevct-ctext,
ctext_N TYPE tdevct-ctext,
relevant TYPE boolean,
objectcounter TYPE int2,
tadircounter TYPE int2,
END OF ty_devclass.
CLASS-DATA gt_devclass TYPE SORTED TABLE OF ty_devclass WITH UNIQUE KEY devclass
WITH UNIQUE SORTED KEY via_parents COMPONENTS parentcl devclass.
DATA gt_abap TYPE STANDARD TABLE OF string.
DATA gt_components TYPE STANDARD TABLE OF gty_component.
CLASS-DATA gt_users TYPE SORTED TABLE OF gty_user WITH UNIQUE KEY user.
METHODS constructor IMPORTING iv_only_methods TYPE string iv_type TYPE string iv_name TYPE string iv_abapdoc TYPE string.
CLASS-METHODS get_zone_version RETURNING VALUE(rv_version_str) TYPE string.
CLASS-METHODS get_username IMPORTING iv_user TYPE sy-uname RETURNING VALUE(rv_fullname) TYPE bapiaddr3-fullname.
CLASS-METHODS get_sap_description
IMPORTING fieldreference TYPE any
language TYPE sy-langu DEFAULT sy-langu
RETURNING VALUE(description) TYPE text80.
CLASS-METHODS read_developmentclasses.
PRIVATE SECTION.
METHODS complex_definitions IMPORTING component_type TYPE string start_tabix TYPE sy-tabix.
METHODS string_to_abapdoc IMPORTING iv_string TYPE string RETURNING VALUE(rt_abapdoc) TYPE gty_doclines.
METHODS read_class IMPORTING iv_classname TYPE seoclsname iv_only_methods TYPE string iv_abapdoc TYPE string.
METHODS read_report IMPORTING iv_report TYPE sy-repid iv_abapdoc TYPE string.
METHODS read_table IMPORTING iv_table TYPE string iv_abapdoc TYPE string.
METHODS read_function IMPORTING iv_function TYPE string iv_abapdoc TYPE string.
ENDCLASS.
CLASS lcl_document_groups DEFINITION.
PUBLIC SECTION.
TYPES: BEGIN OF gty_link,
label TYPE string,
link TYPE string,
END OF gty_link.
TYPES: BEGIN OF gty_review,
date TYPE d,
uname TYPE sy-uname,
username TYPE string,
rating TYPE n LENGTH 1, "0 to 5 stars
summary TYPE string,
remarks TYPE string,
END OF gty_review.
TYPES: BEGIN OF gty_playlistentry,
object_type TYPE string,
object_name TYPE string,
tagwords TYPE string,
only_methods TYPE string, "Comma delimited list of method names that should be presented
abapdoc TYPE string,
links TYPE SORTED TABLE OF gty_link WITH UNIQUE KEY label link,
reviews TYPE SORTED TABLE OF gty_review WITH UNIQUE KEY date uname,
END OF gty_playlistentry.
TYPES gty_playlist TYPE STANDARD TABLE OF gty_playlistentry.
TYPES: BEGIN OF gty_group_object,
id TYPE sy-tabix,
object_type TYPE string,
object_name TYPE string,
components TYPE REF TO lcl_component_documentor,
links TYPE SORTED TABLE OF gty_link WITH UNIQUE KEY label link,
tagwords TYPE string,
reviews TYPE SORTED TABLE OF gty_review WITH UNIQUE KEY date uname,
created TYPE d,
changed TYPE d,
END OF gty_group_object.
TYPES: BEGIN OF gty_group,
description TYPE string,
summary TYPE string,
objects TYPE SORTED TABLE OF gty_group_object WITH UNIQUE KEY id,
created TYPE d,
changed TYPE d,
END OF gty_group.
TYPES: BEGIN OF gty_content,
label TYPE string,
value TYPE string,
username TYPE sy-uname,
datevalue TYPE d,
END OF gty_content.
TYPES: gty_content_tt TYPE STANDARD TABLE OF gty_content.
"SVG image repository
DATA gt_svg_class TYPE STANDARD TABLE OF char255.
DATA gt_svg_report TYPE STANDARD TABLE OF char255.
DATA gt_svg_function TYPE STANDARD TABLE OF char255.
DATA gt_svg_table TYPE STANDARD TABLE OF char255.
DATA gv_svg_mini_icon TYPE char255.
DATA gv_svg_mini_icon2 TYPE char255.
DATA gt_svg_exporting TYPE STANDARD TABLE OF char255.
DATA gt_svg_importing TYPE STANDARD TABLE OF char255.
DATA gt_svg_changing TYPE STANDARD TABLE OF char255.
DATA gt_svg_returning TYPE STANDARD TABLE OF char255.
DATA gt_svg_parameter TYPE STANDARD TABLE OF char255.
DATA gt_svg_selectoption TYPE STANDARD TABLE OF char255.
DATA gt_svg_exception TYPE STANDARD TABLE OF char255.
DATA gt_svg_screw TYPE STANDARD TABLE OF char255.
DATA gt_svg_star_empty TYPE STANDARD TABLE OF char255.
DATA gt_svg_star TYPE STANDARD TABLE OF char255.
DATA gt_svg_lapse TYPE STANDARD TABLE OF char255.
DATA go_html_control TYPE REF TO cl_gui_html_viewer.
DATA go_container TYPE REF TO cl_gui_custom_container.
DATA gt_myevents TYPE cntl_simple_events.
DATA go_event_receiver TYPE REF TO lcl_event_receiver.
DATA gt_html TYPE STANDARD TABLE OF char255.
DATA gv_url TYPE c LENGTH 200.
DATA: BEGIN OF gs_counters,
groups TYPE i,
objects TYPE i,
classes TYPE i,
methods TYPE i,
classmethods TYPE i,
tables TYPE i,
reports TYPE i,
functions TYPE i,
END OF gs_counters.
CLASS-DATA gt_groups TYPE STANDARD TABLE OF gty_group.
CLASS-DATA gv_id TYPE sy-tabix.
CLASS-METHODS set_group IMPORTING iv_description TYPE string iv_summary TYPE string DEFAULT '' it_playlist TYPE gty_playlist.
METHODS string_to_html IMPORTING iv_string TYPE string.
METHODS set_html_style.
METHODS set_svg_images.
METHODS set_age_color IMPORTING iv_date TYPE d RETURNING VALUE(rv_color) TYPE char10.
METHODS harvest_counters.
METHODS harvest_developmentclasses.
METHODS print_developmentclass IMPORTING iv_level TYPE int2
iv_devclass TYPE lcl_component_documentor=>ty_devclass.
METHODS harvest_dates.
METHODS set_abapdoc IMPORTING it_abapdoc TYPE lcl_component_documentor=>gty_doclines.
METHODS set_group_header IMPORTING iv_groupnr TYPE sy-tabix is_group TYPE gty_group.
CLASS-METHODS get_date_summary IMPORTING iv_date TYPE d RETURNING VALUE(rv_result) TYPE string.
METHODS set_all_tagwords IMPORTING is_group TYPE gty_group.
METHODS set_tagwords IMPORTING iv_tagwords TYPE string.
METHODS set_parameter_svg IMPORTING iv_parameter_type TYPE any.
METHODS set_links IMPORTING is_object TYPE gty_group_object.
METHODS set_reviews IMPORTING is_object TYPE gty_group_object.
METHODS set_object_header IMPORTING is_object TYPE gty_group_object.
METHODS set_group_detail IMPORTING iv_created_by TYPE sy-uname iv_created_on TYPE sy-datum it_content TYPE gty_content_tt.
METHODS filter_focus IMPORTING iv_devclass TYPE devclass.
METHODS zone_reporter.
PRIVATE SECTION.
METHODS mini_dot_as_svg
IMPORTING iv_object_type TYPE string
iv_medium TYPE boolean DEFAULT abap_false
RETURNING VALUE(rv_colored_dot) TYPE char255.
ENDCLASS.
CLASS lcl_event_receiver IMPLEMENTATION.
METHOD handle_sapevent.
DATA lv_devclass TYPE devclass.
SPLIT getdata AT '=' INTO TABLE DATA(lt_tokens).
lv_devclass = COND #( WHEN lines( lt_tokens ) = 2 THEN lt_tokens[ 2 ] ELSE '' ).
"Execute a refresh
SUBMIT zone WITH pa_devcl = lv_devclass.
ENDMETHOD.
ENDCLASS.
CLASS lcl_component_documentor IMPLEMENTATION.
METHOD constructor.
CASE iv_type.
WHEN 'CLASS'.
read_class( iv_classname = |{ iv_name }| iv_only_methods = iv_only_methods iv_abapdoc = iv_abapdoc ).
WHEN 'REPORT'.
read_report( iv_report = |{ iv_name }| iv_abapdoc = iv_abapdoc ).
WHEN 'TABLE'.
read_table( iv_table = |{ iv_name }| iv_abapdoc = iv_abapdoc ).
WHEN 'FUNCTION'.
read_function( iv_function = |{ iv_name }| iv_abapdoc = iv_abapdoc ).
ENDCASE.
ENDMETHOD.
METHOD complex_definitions.
DATA lv_finish_tabix TYPE sy-tabix.
DATA lt_cleanabap TYPE STANDARD TABLE OF string.
DATA lv_cleanabapline TYPE string.
DATA lv_structurevariabele TYPE string.
DATA lt_abapdoc TYPE gty_doclines.
DATA lv_component_type TYPE string.
DATA lv_value TYPE string.
FIELD-SYMBOLS TYPE gty_component.
lv_component_type = to_upper( component_type ).
REPLACE ':' IN lv_component_type WITH ''.
"Focus on the coding between : and . - first find the . (dot)
LOOP AT gt_abap FROM start_tabix INTO DATA(lv_abapline).
DATA(lv_loop_tabix) = sy-tabix.
SHIFT lv_abapline LEFT DELETING LEADING space.
"Opening line: remove the component_type
IF lv_loop_tabix = start_tabix.
SHIFT lv_abapline LEFT BY strlen( component_type ) PLACES.
ENDIF.
CONDENSE lv_abapline.
" ABAP doc comments
IF strlen( lv_abapline ) > 3 AND lv_abapline(2) = '"!'.
APPEND lv_abapline TO lt_cleanabap.
CONTINUE.
ENDIF.
SPLIT lv_abapline AT '"' INTO lv_abapline DATA(lv_comments). "Strip comments
lv_cleanabapline = |{ lv_cleanabapline } { lv_abapline }|.
IF lv_cleanabapline CA '.,'.
SHIFT lv_cleanabapline LEFT DELETING LEADING space.
"Cut out the TYPE definition
SPLIT lv_cleanabapline AT space INTO TABLE DATA(lt_tokens).
IF lines( lt_tokens ) > 2.
IF to_upper( lt_tokens[ 2 ] ) = 'TYPE'.
"TYPE REF TO
IF to_upper( lt_tokens[ 3 ] ) = 'REF'.
DELETE lt_tokens FROM 2 TO 5.
ELSE.
DELETE lt_tokens FROM 2 TO 3.
ENDIF.
ELSEIF to_upper( lt_tokens[ 2 ] ) = 'FOR' OR to_upper( lt_tokens[ 2 ] ) = 'LIKE'.
DELETE lt_tokens FROM 2 TO 3.
ENDIF.
ENDIF.
CLEAR lv_cleanabapline.
LOOP AT lt_tokens INTO DATA(lv_token).
CONCATENATE lv_cleanabapline lv_token INTO lv_cleanabapline SEPARATED BY space.
ENDLOOP.
SHIFT lv_cleanabapline LEFT DELETING LEADING space.
REPLACE ',' IN lv_cleanabapline WITH ''.
APPEND lv_cleanabapline TO lt_cleanabap.
CLEAR lv_cleanabapline.
ENDIF.
IF lv_abapline CS '.'.
lv_finish_tabix = sy-tabix.
EXIT.
ENDIF.
ENDLOOP.
LOOP AT lt_cleanabap INTO lv_cleanabapline.
IF strlen( lv_cleanabapline ) > 2 AND lv_cleanabapline(2) = '"!'.
INSERT VALUE gty_docline( linenr = lines( lt_abapdoc ) content = lv_cleanabapline+2 ) INTO TABLE lt_abapdoc.
CONTINUE.
ENDIF.
SPLIT lv_cleanabapline AT space INTO TABLE lt_tokens.
CASE lv_component_type.
WHEN 'SELECT-OPTIONS' OR 'PARAMETERS'.
WHEN OTHERS.
IF to_upper( lt_tokens[ 1 ] ) = 'BEGIN'.
lv_structurevariabele = |{ to_upper( lt_tokens[ 3 ] ) }|.
APPEND VALUE gty_component(
component_type = lv_component_type
component_name = lv_structurevariabele ) TO gt_components ASSIGNING .
APPEND LINES OF lt_abapdoc TO -abapdoc.
CLEAR lt_abapdoc.
* lv_structurevariabele = ' '.
CLEAR lv_structurevariabele.
CONTINUE.
ENDIF.
IF to_upper( lt_tokens[ 1 ] ) = 'END'.
CLEAR lv_structurevariabele.
CONTINUE.
ENDIF.
ENDCASE.
lv_value = COND #( WHEN ( lines( lt_tokens ) >= 3 ) AND ( to_upper( lt_tokens[ 2 ] ) = 'VALUE' ) THEN lt_tokens[ 3 ] ELSE '' ).
APPEND VALUE gty_component(
component_type = lv_component_type
component_name = |{ lv_structurevariabele }{ to_upper( lt_tokens[ 1 ] ) }|
attvalue = lv_value ) TO gt_components ASSIGNING .
APPEND LINES OF lt_abapdoc TO -abapdoc.
CLEAR lt_abapdoc.
ENDLOOP.
IF lv_finish_tabix > 0. "Structure too complex if no end line available
lv_finish_tabix = lv_finish_tabix + start_tabix.
"Clean up the block of coding that was interpreted - to ensure the regular processing remains
LOOP AT gt_abap FROM start_tabix TO lv_finish_tabix ASSIGNING FIELD-SYMBOL().
CLEAR .
ENDLOOP.
ENDIF.
ENDMETHOD.
METHOD string_to_abapdoc.
DATA lt_string_components TYPE STANDARD TABLE OF swastrtab.
CHECK strlen( iv_string ) > 0.
CALL FUNCTION 'SWA_STRING_SPLIT'
EXPORTING
input_string = iv_string
max_component_length = 70
TABLES
string_components = lt_string_components.
LOOP AT lt_string_components INTO DATA(ls_string_component).
APPEND VALUE #( linenr = lines( rt_abapdoc ) content = ls_string_component-str ) TO rt_abapdoc.
ENDLOOP.
ENDMETHOD.
METHOD get_zone_version.
SELECT SINGLE unam, udat FROM trdir INTO @DATA(ls_trdir) WHERE name = 'ZONE_SCRIPT'.
IF ls_trdir-udat = sy-datum.
rv_version_str =
|Last zone_script update today by { get_username( ls_trdir-unam ) } ({ ls_trdir-unam })|.
ELSE.
rv_version_str =
|Last zone_script update on { ls_trdir-udat DATE = USER } ({ lcl_document_groups=>get_date_summary( iv_date = ls_trdir-udat ) }) | &&
| by { get_username( ls_trdir-unam ) } ({ ls_trdir-unam })|.
ENDIF.
rv_version_str = |{ rv_version_str } (click to refresh)|.
ENDMETHOD.
METHOD get_username.
DATA ls_address TYPE bapiaddr3.
DATA lt_return TYPE STANDARD TABLE OF bapiret2.
READ TABLE gt_users WITH KEY user = iv_user INTO DATA(ls_user).
IF sy-subrc <> 0.
CALL FUNCTION 'BAPI_USER_GET_DETAIL'
EXPORTING
username = iv_user
IMPORTING
address = ls_address
TABLES
return = lt_return.
ls_user = VALUE #( user = iv_user fullname = ls_address-fullname ).
INSERT ls_user INTO TABLE gt_users.
ENDIF.
rv_fullname = ls_user-fullname.
ENDMETHOD.
METHOD get_sap_description.
DATA: lv_tabname TYPE c LENGTH 20,
lv_fieldname TYPE c LENGTH 25,
lv_description TYPE dd03t-ddtext,
lv_rollname TYPE dd03l-rollname.
* Fetch SAP description if possible:
CLEAR lv_description.
IF NOT fieldreference IS INITIAL.
lv_description = co_undetermined.
SPLIT fieldreference AT '-' INTO lv_tabname lv_fieldname.
IF NOT lv_fieldname IS INITIAL.
SELECT ddtext FROM dd03t INTO lv_description
UP TO 1 ROWS
WHERE tabname = lv_tabname AND
fieldname = lv_fieldname AND
as4local = 'A' AND
ddlanguage = language.
ENDSELECT.
IF sy-subrc <> 0 OR lv_description IS INITIAL.
SELECT rollname FROM dd03l INTO lv_rollname
UP TO 1 ROWS
WHERE tabname = lv_tabname AND
fieldname = lv_fieldname AND
as4local = 'A' AND as4vers = 0000.
ENDSELECT.
IF sy-subrc = 0.
SELECT SINGLE scrtext_l FROM dd04t INTO @DATA(lv_scrtext_l)
WHERE rollname = @lv_rollname AND
ddlanguage = @language AND
as4local = 'A' AND as4vers = 0000.
IF sy-subrc = 0.
lv_description = lv_scrtext_l.
ELSE.
lv_description = co_field_error.
ENDIF.
ENDIF.
ENDIF.
ELSE.
* Structure name ?
SELECT ddtext FROM dd02t INTO lv_description
UP TO 1 ROWS
WHERE tabname = lv_tabname AND
as4local = 'A' AND
ddlanguage = language.
ENDSELECT.
IF sy-subrc = 0.
CONCATENATE 'Structure' lv_description INTO lv_description SEPARATED BY space.
ENDIF.
ENDIF.
ENDIF.
description = lv_description.
REPLACE ALL OCCURRENCES OF '"' IN description WITH '#'.
ENDMETHOD.
METHOD read_class.
DATA lv_classname TYPE seoclskey.
DATA lt_abapdoc TYPE gty_doclines.
DATA lo_cls TYPE REF TO if_oo_class_incl_naming.
DATA lv_moving_component_type TYPE string.
DATA lt_only_methods TYPE SORTED TABLE OF string WITH UNIQUE KEY table_line.
DATA lv_lines TYPE sy-index.
DATA lv_helper TYPE c LENGTH 100.
FIELD-SYMBOLS TYPE gty_component.
IF NOT iv_abapdoc IS INITIAL.
APPEND LINES OF string_to_abapdoc( iv_abapdoc ) TO lt_abapdoc.
ENDIF.
IF NOT iv_only_methods IS INITIAL.
SPLIT to_upper( iv_only_methods ) AT ',' INTO TABLE DATA(lt_tokens).
LOOP AT lt_tokens INTO DATA(lv_token).
CONDENSE lv_token NO-GAPS.
READ TABLE lt_only_methods WITH KEY table_line = lv_token TRANSPORTING NO FIELDS.
IF sy-subrc <> 0.
INSERT lv_token INTO TABLE lt_only_methods.
ENDIF.
ENDLOOP.
ENDIF.
"Class interrogation - is this a valid class ? Gather details:
TRY.
DATA(lo_oo_class) = cl_oo_class=>get_instance( clsname = iv_classname ).
DATA(lo_oo_class2) = NEW cl_oo_class( clsname = iv_classname ).
lv_classname = iv_classname.
* Source for this technique: report dsmy_class_output
CALL METHOD cl_oo_include_naming=>get_instance_by_cifkey
EXPORTING
cifkey = lv_classname
RECEIVING
cifref = DATA(lo_cif)
EXCEPTIONS
OTHERS = 1.
lo_cls ?= lo_cif.
READ REPORT lo_cls->main_source INTO gt_abap.
IF sy-subrc <> 0.
DATA(lv_message) = 'Inaccurate line count - main source unavailable'.
ENDIF.
lv_lines = lines( gt_abap ).
READ REPORT lo_cls->public_section INTO gt_abap.
"Translate the public section of the class to a list of constants and methods
LOOP AT gt_abap INTO DATA(lv_abapline).
DATA(lv_loop_tabix) = sy-tabix.
SHIFT lv_abapline LEFT DELETING LEADING space.
DATA(lv_abaplineupper) = to_upper( lv_abapline ).
SPLIT lv_abaplineupper AT '.' INTO lv_abaplineupper DATA(lv_dummy).
SPLIT lv_abaplineupper AT space INTO TABLE DATA(lt_abapline_tokens).
"Abap DOC comments are for a statement that follows the comments. To ensure comments
"are not added to a statement by accident, some checks are applied:
IF strlen( lv_abapline ) = 0.
CLEAR lt_abapdoc.
ELSEIF strlen( lv_abapline ) > 3 AND lv_abapline(2) <> '"!' AND NOT lv_dummy IS INITIAL.
CLEAR lt_abapdoc.
ENDIF.
" ABAP doc comments
IF strlen( lv_abapline ) > 3 AND lv_abapline(2) = '"!'.
INSERT VALUE gty_docline( linenr = lines( lt_abapdoc ) content = lv_abapline+2 ) INTO TABLE lt_abapdoc.
ELSEIF
( lines( lt_abapline_tokens ) >= 1 ) AND
( ( strlen( lv_abaplineupper ) >= 10 AND lv_abaplineupper(10) = 'CONSTANTS:' ) OR
( strlen( lv_abaplineupper ) >= 5 AND lv_abaplineupper(5) = 'DATA:' ) OR
( strlen( lv_abaplineupper ) >= 11 AND lv_abaplineupper(11) = 'CLASS-DATA:' ) ).
"Constants and attribute definitions with : are catered for differently. Multiple coding lines are
"interpreted and required information is extracted. The extractor can clear gt_abap lines
complex_definitions( component_type = lt_abapline_tokens[ 1 ] start_tabix = lv_loop_tabix ).
"Attribute definitions (DATA and CLASS-DATA)
ELSEIF ( lines( lt_abapline_tokens ) > 1 ) AND
NOT lv_moving_component_type IS INITIAL.
READ TABLE lo_oo_class->attributes INTO DATA(ls_attribute_details)
WITH KEY clsname = lv_classname cmpname = lt_abapline_tokens[ 1 ].
IF sy-subrc = 0.
APPEND VALUE gty_component(
component_type = lv_moving_component_type
component_name = ls_attribute_details-cmpname
attvalue = ls_attribute_details-attvalue
read_only = ls_attribute_details-attrdonly ) TO gt_components ASSIGNING .
APPEND LINES OF lt_abapdoc TO -abapdoc.
ENDIF.
CLEAR lt_abapdoc.
ELSEIF
( lines( lt_abapline_tokens ) > 1 ) AND
( ( strlen( lv_abaplineupper ) > 9 AND lv_abaplineupper(9) = 'CONSTANTS' ) OR
( strlen( lv_abaplineupper ) > 4 AND lv_abaplineupper(4) = 'DATA' ) OR
( strlen( lv_abaplineupper ) > 10 AND lv_abaplineupper(10) = 'CLASS-DATA' ) ).
READ TABLE lo_oo_class->attributes INTO ls_attribute_details
WITH KEY clsname = lv_classname cmpname = lt_abapline_tokens[ 2 ].
IF sy-subrc = 0.
APPEND VALUE gty_component(
component_type = lt_abapline_tokens[ 1 ]
component_name = ls_attribute_details-cmpname
attvalue = ls_attribute_details-attvalue
read_only = ls_attribute_details-attrdonly ) TO gt_components ASSIGNING .
APPEND LINES OF lt_abapdoc TO -abapdoc.
ENDIF.
CLEAR lt_abapdoc.
"CLASS METHOD definition as well as METHOD definition
ELSEIF
( strlen( lv_abaplineupper ) > 12 AND lv_abaplineupper(12) = 'CLASS-METHOD' ) OR
( strlen( lv_abaplineupper ) > 6 AND lv_abaplineupper(6) = 'METHOD' ).
READ TABLE lo_oo_class->methods INTO DATA(ls_method_details)
WITH KEY clsname = lv_classname cmpname = lt_abapline_tokens[ 2 ].
IF sy-subrc = 0.
IF lines( lt_only_methods ) > 0.
READ TABLE lt_only_methods WITH KEY table_line = to_upper( lt_abapline_tokens[ 2 ] ) TRANSPORTING NO FIELDS.
IF sy-subrc <> 0.
CLEAR lt_abapdoc.
CONTINUE.
ENDIF.
ENDIF.
APPEND VALUE gty_component(
component_type = lt_abapline_tokens[ 1 ]
component_name = ls_method_details-cmpname ) TO gt_components ASSIGNING .
APPEND LINES OF lt_abapdoc TO -abapdoc.
"Determine method hitcount (number of times it is called)
DATA(lv_reference) = |{ iv_classname }\\ME:{ -component_name }|.
SELECT COUNT(*) FROM wbcrossgt INTO @-method_hitcount
WHERE otype = 'ME' AND name = @lv_reference.
"Add method parameters - in sequence of type
DO 4 TIMES.
LOOP AT lo_oo_class->method_parameters INTO DATA(ls_method_parameter_details)
WHERE clsname = ls_method_details-clsname AND cmpname = ls_method_details-cmpname AND
pardecltyp = ( sy-index - 1 ).
INSERT VALUE gty_parameter(
linenr = lines( -parameters )
parameter = ls_method_parameter_details-sconame
pardecltyp = ls_method_parameter_details-pardecltyp
datatype = ls_method_parameter_details-type
optional = ls_method_parameter_details-paroptionl ) INTO TABLE -parameters.
ENDLOOP.
ENDDO.
"Exceptions
LOOP AT lo_oo_class->method_exceptions INTO DATA(ls_method_exception_details)
WHERE clsname = ls_method_details-clsname AND cmpname = ls_method_details-cmpname.
INSERT VALUE gty_parameter(
linenr = lines( -parameters )
parameter = ls_method_exception_details-sconame
pardecltyp = 9 ) INTO TABLE -parameters.
ENDLOOP.
ELSE.
"Method is a redefinition
READ TABLE lo_oo_class2->redefinitions INTO DATA(ls_refefinition_details)
WITH KEY clsname = lv_classname mtdname = lt_abapline_tokens[ 2 ].
IF sy-subrc = 0.
IF lines( lt_only_methods ) > 0.
READ TABLE lt_only_methods WITH KEY table_line = to_upper( lt_abapline_tokens[ 2 ] ) TRANSPORTING NO FIELDS.
IF sy-subrc <> 0.
CLEAR lt_abapdoc.
CONTINUE.
ENDIF.
ENDIF.
APPEND VALUE gty_component(
component_type = lt_abapline_tokens[ 1 ]
component_name = ls_refefinition_details-mtdname
parameters = value #( ( linenr = 1 parameter = '?' pardecltyp = '2' ) )
redefinition = abap_true
) TO gt_components ASSIGNING .
APPEND LINES OF lt_abapdoc TO -abapdoc.
"Determine method hitcount (number of times it is called)
lv_reference = |{ iv_classname }\\ME:{ -component_name }|.
SELECT COUNT(*) FROM wbcrossgt INTO @-method_hitcount
WHERE otype = 'ME' AND name = @lv_reference.
ENDIF.
ENDIF.
CLEAR lt_abapdoc.
"CLASS definition
ELSEIF strlen( lv_abaplineupper ) > 5 AND lv_abaplineupper(5) = 'CLASS'.
IF lt_abapline_tokens[ 1 ] = 'CLASS' AND lt_abapline_tokens[ 3 ] = 'DEFINITION'.
DATA lv_clsname TYPE vseoclass-clsname.
lv_clsname = lv_classname.
APPEND VALUE gty_component(
component_type = lt_abapline_tokens[ 1 ]
component_name = lv_classname
class-superclass = lo_oo_class2->superclass
class-methods = lines( lo_oo_class->methods )
class-redefinitions = lines( lo_oo_class2->redefinitions )
) TO gt_components ASSIGNING .
LOOP AT lo_oo_class2->implementings INTO DATA(ls_implementing).
IF -class-interfaces IS INITIAL.
-class-interfaces = ls_implementing-refclsname.
ELSE.
-class-interfaces = |{ -class-interfaces }, { ls_implementing-refclsname }|.
ENDIF.
ENDLOOP.
-class-filter_on_methods = COND #( WHEN iv_only_methods IS INITIAL THEN abap_false ELSE abap_true ).
SELECT SINGLE descript, author, createdon, changedby, changedon
FROM vseoclass
INTO ( @-description, @-class-author, @-class-createdon,
@-class-changedby, @-class-changedon )
WHERE clsname = @lv_clsname.
-class-linecount = lv_lines.
-class-message = lv_message.
"Some effort to find an accurate last changed date (and user) - based on STMS
lv_helper = |{ lv_clsname }%|.
SELECT h~as4date, h~as4user FROM e070 AS h
INNER JOIN e071 AS o ON o~trkorr = h~trkorr
UP TO 1 ROWS INTO @DATA(ls_stms)
WHERE ( o~obj_name = @lv_clsname AND o~object IN ( 'CLAS', 'CLSD', 'CPUB' ) ) OR
( o~obj_name LIKE @lv_helper AND o~object IN ( 'METH' ) )
ORDER BY h~as4date DESCENDING, h~as4time DESCENDING.
ENDSELECT.
IF sy-subrc = 0.
-class-changedby = ls_stms-as4user.
-class-changedon = ls_stms-as4date.
ENDIF.
APPEND LINES OF lt_abapdoc TO -abapdoc.
SELECT SINGLE devclass FROM tadir INTO @-devclass
WHERE pgmid = 'R3TR' AND object = 'CLAS' AND obj_name = @-component_name.
IF sy-subrc = 0.
SELECT SINGLE ctext FROM tdevct INTO @-devclass_text
WHERE devclass = @-devclass AND spras = @sy-langu.
IF sy-subrc <> 0.
SELECT SINGLE ctext FROM tdevct INTO @-devclass_text
WHERE devclass = @-devclass AND spras <> @sy-langu.
ENDIF.
ENDIF.
ENDIF.
CLEAR lt_abapdoc.
ENDIF.
ENDLOOP.
CATCH cx_class_not_existent.
"skipped: not a class
ENDTRY.
ENDMETHOD.
METHOD read_report.
DATA lt_abapdoc TYPE gty_doclines.
DATA lt_includes TYPE STANDARD TABLE OF char80.
DATA lv_REPORT_tagged TYPE boolean.
DATA lt_abap TYPE STANDARD TABLE OF string.
DATA lt_RSEL_INFO TYPE STANDARD TABLE OF rsel_info.
FIELD-SYMBOLS TYPE gty_component.
IF NOT iv_abapdoc IS INITIAL.
APPEND LINES OF string_to_abapdoc( iv_abapdoc ) TO lt_abapdoc.
ENDIF.
READ REPORT iv_report INTO gt_abap.
"The report logic is interpreted for it's ABAPdoc comments
LOOP AT gt_abap INTO DATA(lv_abapline).
DATA(lv_loop_tabix) = sy-tabix.
SHIFT lv_abapline LEFT DELETING LEADING space.
DATA(lv_abaplineupper) = to_upper( lv_abapline ).
SPLIT lv_abaplineupper AT '.' INTO lv_abaplineupper DATA(lv_dummy).
SPLIT lv_abaplineupper AT space INTO TABLE DATA(lt_abapline_tokens).
DELETE lt_abapline_tokens WHERE table_line = ''.
" ABAP doc comments
IF strlen( lv_abaplineupper ) > 3 AND lv_abaplineupper(2) = '"!'.
INSERT VALUE gty_docline( linenr = lines( lt_abapdoc ) content = lv_abapline+3 ) INTO TABLE lt_abapdoc.
" Report definitie
ELSEIF ( strlen( lv_abaplineupper ) > 6 AND lv_abaplineupper(6) = 'REPORT' ) AND lv_REPORT_tagged = abap_false.
lv_REPORT_tagged = abap_true.
APPEND VALUE gty_component(
component_type = lt_abapline_tokens[ 1 ]
component_name = lt_abapline_tokens[ 2 ]
report-linecount = lines( gt_abap ) ) TO gt_components ASSIGNING .
SELECT SINGLE cnam, cdat, unam, udat FROM trdir INTO
(@-report-cnam, @-report-cdat,
@-report-unam, @-report-udat)
WHERE name = @-component_name.
SELECT SINGLE text FROM trdirt INTO @-description
WHERE name = @-component_name AND sprsl = @sy-langu.
IF sy-subrc <> 0.
SELECT text FROM trdirt INTO @-description
WHERE name = @-component_name.
ENDSELECT.
ENDIF.
SELECT SINGLE devclass FROM tadir INTO @-devclass
WHERE pgmid = 'R3TR' AND object = 'PROG' AND obj_name = @-component_name.
IF sy-subrc = 0.
SELECT SINGLE ctext FROM tdevct INTO @-devclass_text
WHERE devclass = @-devclass AND spras = @sy-langu.
IF sy-subrc <> 0.
SELECT SINGLE ctext FROM tdevct INTO @-devclass_text
WHERE devclass = @-devclass AND spras <> @sy-langu.
ENDIF.
ENDIF.
CALL FUNCTION 'GET_INCLUDETAB'
EXPORTING
progname = -component_name
TABLES
incltab = lt_includes.
"Update the program line counter with include lines
LOOP AT lt_includes INTO DATA(lv_include).
READ REPORT lv_include INTO lt_abap.
-report-linecount = -report-linecount + lines( lt_abap ).
ENDLOOP.
INSERT LINES OF lt_includes INTO TABLE -report-includes.
CALL FUNCTION 'RS_SELECTIONS_DESCRIPTION_RFC'
EXPORTING
report = iv_report
default_values = ' '
TABLES
field_info = lt_RSEL_INFO
EXCEPTIONS
OTHERS = 0.
LOOP AT lt_RSEL_INFO INTO DATA(ls_RSEL_INFO).
APPEND VALUE gty_parameter(
linenr = lines( -parameters )
pardecltyp = COND #( WHEN ls_RSEL_INFO-kind = 'P' THEN '6' ELSE '7' )
parameter = ls_RSEL_INFO-name ) TO -parameters.
ENDLOOP.
APPEND LINES OF lt_abapdoc TO -abapdoc.
CLEAR lt_abapdoc.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD read_table.
DATA lt_abapdoc TYPE gty_doclines.
IF NOT iv_abapdoc IS INITIAL.
APPEND LINES OF string_to_abapdoc( iv_abapdoc ) TO lt_abapdoc.
ENDIF.
SELECT SINGLE ddtext FROM dd02t INTO @DATA(ls_description)
WHERE tabname = @iv_table.
CHECK sy-subrc = 0.
APPEND VALUE gty_component(
component_type = 'TABLE'
description = ls_description
component_name = |{ iv_table }| ) TO gt_components ASSIGNING FIELD-SYMBOL().
SELECT SINGLE as4user, as4date, mainflag FROM dd02l INTO @DATA(ls_dd02l)
WHERE tabname = @iv_table AND
as4local = 'A' AND
as4vers = 0000.
IF sy-subrc = 0.
-table-changed_on = ls_dd02l-as4date.
-table-changed_by = ls_dd02l-as4user.
-table-maintenance = ls_dd02l-mainflag.
ENDIF.
SELECT SINGLE devclass FROM tadir INTO @-devclass
WHERE pgmid = 'R3TR' AND object = 'TABL' AND obj_name = @-component_name.
IF sy-subrc = 0.
SELECT SINGLE ctext FROM tdevct INTO @-devclass_text
WHERE devclass = @-devclass AND spras = @sy-langu.
IF sy-subrc <> 0.
SELECT SINGLE ctext FROM tdevct INTO @-devclass_text
WHERE devclass = @-devclass AND spras <> @sy-langu.
ENDIF.
SELECT e070~as4user, e070~as4date FROM e071
INNER JOIN e070 ON e070~trkorr = e071~trkorr
WHERE e071~pgmid = 'R3TR' AND
e071~object = 'TABL' AND
e071~obj_name = @-component_name
ORDER BY e071~trkorr
INTO @DATA(ls_e070) .
"Fetch the creation date from transports
-table-created_on = ls_e070-as4date.
-table-created_by = ls_e070-as4user.
EXIT.
ENDSELECT.
ENDIF.
SELECT * FROM dd03l INTO TABLE @-table-dd03l
WHERE tabname = @iv_table AND as4local = 'A' AND as4vers = 0000.
-abapdoc = lt_abapdoc.
ENDMETHOD.
METHOD read_function.
DATA lt_abapdoc TYPE gty_doclines.
DATA lt_abap TYPE STANDARD TABLE OF string.
DATA lv_include TYPE char40.
IF NOT iv_abapdoc IS INITIAL.
APPEND LINES OF string_to_abapdoc( iv_abapdoc ) TO lt_abapdoc.
ENDIF.
SELECT SINGLE enlfdir~area, tadir~author, tadir~devclass, tadir~created_on, tfdir~pname, tfdir~include FROM enlfdir
INNER JOIN tadir ON tadir~obj_name = enlfdir~area AND tadir~pgmid = 'R3TR' AND tadir~object = 'FUGR'
INNER JOIN tfdir ON tfdir~funcname = enlfdir~funcname
INTO @DATA(ls_function_data)
WHERE enlfdir~funcname = @iv_function.
*
APPEND VALUE gty_component(
component_type = 'FUNCTION'
component_name = |{ iv_function }|
devclass = ls_function_data-devclass
function-author = ls_function_data-author
function-created_on = ls_function_data-created_on
function-area = ls_function_data-area
) TO gt_components ASSIGNING FIELD-SYMBOL().
SELECT stext FROM tftit INTO @-description
WHERE funcname = @iv_function.
EXIT.
ENDSELECT.
"Hitcounter
SELECT COUNT(*) INTO @-function-hitcount
FROM cross WHERE type = 'F' AND name = @iv_function.
SELECT SINGLE ctext FROM tdevct INTO @-devclass_text
WHERE devclass = @-devclass AND spras = @sy-langu.
IF sy-subrc <> 0.
SELECT SINGLE ctext FROM tdevct INTO @-devclass_text
WHERE devclass = @-devclass AND spras <> @sy-langu.
ENDIF.
lv_include = |{ ls_function_data-pname+3 }U{ ls_function_data-include }|.
READ REPORT lv_include INTO lt_abap.
-function-linecount = lines( lt_abap ).
-abapdoc = lt_abapdoc.
SELECT parameter, paramtype FROM fupararef INTO TABLE @DATA(lt_FUPARAREF)
WHERE funcname = @iv_function AND r3state = 'A'.
"Importing
LOOP AT lt_FUPARAREF INTO DATA(ls_FUPARAREF) WHERE paramtype = 'I'.
INSERT VALUE gty_parameter(
linenr = lines( -parameters ) pardecltyp = '0'
parameter = ls_FUPARAREF-parameter ) INTO TABLE -parameters.
ENDLOOP.
"Changing
LOOP AT lt_FUPARAREF INTO ls_FUPARAREF WHERE paramtype = 'C'.
INSERT VALUE gty_parameter(
linenr = lines( -parameters ) pardecltyp = '2'
parameter = ls_FUPARAREF-parameter ) INTO TABLE -parameters.
ENDLOOP.
"Exporting
LOOP AT lt_FUPARAREF INTO ls_FUPARAREF WHERE paramtype = 'E'.
INSERT VALUE gty_parameter(
linenr = lines( -parameters ) pardecltyp = '1'
parameter = ls_FUPARAREF-parameter ) INTO TABLE -parameters.
ENDLOOP.
"Tables
LOOP AT lt_FUPARAREF INTO ls_FUPARAREF WHERE paramtype = 'T'.
INSERT VALUE gty_parameter(
linenr = lines( -parameters ) pardecltyp = '2'
parameter = ls_FUPARAREF-parameter ) INTO TABLE -parameters.
ENDLOOP.
"Exceptions
LOOP AT lt_FUPARAREF INTO ls_FUPARAREF WHERE paramtype = 'X'.
INSERT VALUE gty_parameter(
linenr = lines( -parameters ) pardecltyp = '9'
parameter = ls_FUPARAREF-parameter ) INTO TABLE -parameters.
ENDLOOP.
ENDMETHOD.
METHOD read_developmentclasses.
DATA lr_devclass TYPE RANGE OF tdevc-devclass.
DATA lr_objectnames type range of tadir-obj_name.
lr_devclass = VALUE #( ( sign = 'I' option = 'CP' low = '$*' ) ( sign = 'I' option = 'CP' low = 'Z*' ) ( sign = 'I' option = 'CP' low = 'Y*' ) ).
SELECT tdevc~devclass, tdevc~parentcl, tdevct_E~ctext, tdevct_N~ctext
FROM tdevc
LEFT OUTER JOIN tdevct AS tdevct_E
ON tdevc~devclass = tdevct_E~devclass AND tdevct_E~spras = 'E'
LEFT OUTER JOIN tdevct AS tdevct_N
ON tdevc~devclass = tdevct_N~devclass AND tdevct_N~spras = 'N'
INTO TABLE @gt_devclass
WHERE tdevc~devclass IN @lr_devclass.
lr_objectnames = VALUE #( ( sign = 'I' option = 'CP' low = 'Y*' ) ( sign = 'I' option = 'CP' low = 'Z*' ) ).
select distinct devclass, count( * ) as counter from tadir
into table @data(lt_tadircounts)
WHERE obj_name in @lr_objectnames and
devclass IN @lr_devclass
group by devclass.
loop at gt_devclass assigning field-symbol().
read table lt_tadircounts with key devclass = -devclass into data(ls_tadircount).
if sy-subrc = 0.
-tadircounter = ls_tadircount-counter.
endif.
endloop.
ENDMETHOD.
ENDCLASS.
CLASS lcl_document_groups IMPLEMENTATION.
METHOD set_group.
DATA lv_space_counter TYPE n LENGTH 3.
FIELD-SYMBOLS TYPE gty_group.
FIELD-SYMBOLS TYPE gty_group_object.
INSERT VALUE gty_group( ) INTO TABLE gt_groups ASSIGNING .
-description = iv_description.
-summary = iv_summary.
LOOP AT it_playlist INTO DATA(ls_playlist).
IF ls_playlist-object_type = 'SPACE'.
lv_space_counter = lv_space_counter + 1.
ls_playlist-object_name = lv_space_counter.
ENDIF.
READ TABLE -objects WITH KEY
object_type = ls_playlist-object_type
object_name = ls_playlist-object_name ASSIGNING .
IF sy-subrc <> 0.
INSERT VALUE gty_group_object(
id = lines( -objects )
object_type = ls_playlist-object_type
object_name = ls_playlist-object_name
links = ls_playlist-links
tagwords = ls_playlist-tagwords
reviews = ls_playlist-reviews )
INTO TABLE -objects ASSIGNING .
ENDIF.
-components = NEW lcl_component_documentor(
iv_only_methods = ls_playlist-only_methods
iv_abapdoc = ls_playlist-abapdoc
iv_name = ls_playlist-object_name
iv_type = ls_playlist-object_type ).
ENDLOOP.
ENDMETHOD.
METHOD string_to_html.
DATA lt_string_components TYPE STANDARD TABLE OF swastrtab.
CHECK strlen( iv_string ) > 0.
CALL FUNCTION 'SWA_STRING_SPLIT'
EXPORTING
input_string = iv_string
max_component_length = 70
TABLES
string_components = lt_string_components.
LOOP AT lt_string_components INTO DATA(ls_string_component).
APPEND ls_string_component-str TO gt_html.
ENDLOOP.
ENDMETHOD.
METHOD set_html_style.
gt_html = VALUE #(
( 'The Zone - inspiration for developers')
( '')
( '' ) ).
ENDMETHOD.
METHOD set_svg_images.
gt_svg_class = VALUE #(
( ' ' ) ).
gt_svg_report = VALUE #(
( ' ' ) ).
gt_svg_function = VALUE #(
( ' ' ) ).
gt_svg_table = VALUE #(
( ' ' ) ).
gv_svg_mini_icon =
' '.
gv_svg_mini_icon2 =
' '.
* https://www.svgrepo.com/collection/solar-line-duotone-icons/19
gt_svg_exporting = VALUE #(
( '' ) ).
gt_svg_importing = VALUE #(
( '' ) ).
gt_svg_changing = VALUE #(
( '' ) ).
gt_svg_returning = VALUE #(
( '' ) ).
gt_svg_parameter = VALUE #(
( '' ) ).
gt_svg_selectoption = VALUE #(
( '' ) ).
gt_svg_exception = VALUE #(
( '' ) ).
gt_svg_screw = VALUE #(
( '' ) ).
gt_svg_star = VALUE #(
( ' ' ) ).
gt_svg_star_empty = VALUE #(
( ' ' ) ).
gt_svg_lapse = VALUE #(
( ' ' ) ).
ENDMETHOD.
METHOD set_age_color.
"The age-color grading is derived from the age in days against fibonacci numbers
TYPES: BEGIN OF lty_colors,
days TYPE int2,
color TYPE c LENGTH 8,
END OF lty_colors.
rv_color = '#000000'.
CHECK NOT iv_date IS INITIAL.
DATA lt_colorcodes TYPE SORTED TABLE OF lty_colors WITH UNIQUE KEY days.
lt_colorcodes = VALUE #( ( days = 0 color = '#00ff00' ) ( days = 2 color = '#e6e6ff' ) ( days = 3 color = '#ccccff' )
( days = 5 color = '#b3b3ff' ) ( days = 8 color = '#9999ff' ) ( days = 13 color = '#8080ff' ) ( days = 21 color = '#6666ff' )
( days = 34 color = '#4d4dff' ) ( days = 55 color = '#3333ff' ) ( days = 89 color = '#1a1aff' ) ( days = 144 color = '#1a1aff' )
( days = 233 color = '#0000ff' ) ( days = 377 color = '#0000e6' ) ( days = 610 color = '#0000cc' ) ( days = 987 color = '#0000b3' )
( days = 1697 color = '#000099' ) ( days = 2584 color = '#000080' ) ( days = 32000 color = '#000000' ) ).
DATA(lv_age_in_days) = sy-datum - iv_date.
LOOP AT lt_colorcodes INTO DATA(ls_colorcode) WHERE days <= lv_age_in_days.
rv_color = ls_colorcode-color.
ENDLOOP.
ENDMETHOD.
METHOD harvest_counters.
CLEAR gs_counters.
LOOP AT gt_groups INTO DATA(ls_group).
gs_counters-groups = gs_counters-groups + 1.
LOOP AT ls_group-objects INTO DATA(ls_object) WHERE object_type <> 'SPACE'.
gs_counters-objects = gs_counters-objects + 1.
LOOP AT ls_object-components->gt_components INTO DATA(ls_component).
CASE ls_component-component_type.
WHEN 'CLASS'.
gs_counters-classes = gs_counters-classes + 1.
WHEN 'METHODS'.
gs_counters-methods = gs_counters-methods + 1.
WHEN 'CLASS-METHODS'.
gs_counters-classmethods = gs_counters-classmethods + 1.
WHEN 'TABLE'.
gs_counters-tables = gs_counters-tables + 1.
WHEN 'REPORT'.
gs_counters-reports = gs_counters-reports + 1.
WHEN 'FUNCTION'.
gs_counters-functions = gs_counters-functions + 1.
ENDCASE.
ENDLOOP.
ENDLOOP.
ENDLOOP.
ENDMETHOD.
METHOD harvest_developmentclasses.
DATA lv_focus_devclass TYPE devclass.
LOOP AT gt_groups INTO DATA(ls_group).
gs_counters-groups = gs_counters-groups + 1.
LOOP AT ls_group-objects INTO DATA(ls_object).
gs_counters-objects = gs_counters-objects + 1.
LOOP AT ls_object-components->gt_components INTO DATA(ls_component).
READ TABLE lcl_component_documentor=>gt_devclass ASSIGNING FIELD-SYMBOL()
WITH KEY devclass = ls_component-devclass.
IF sy-subrc = 0.
-objectcounter = -objectcounter + 1.
ENDIF.
ENDLOOP.
ENDLOOP.
ENDLOOP.
"Determine relevance: everything with a counter and their parents
LOOP AT lcl_component_documentor=>gt_devclass ASSIGNING
WHERE objectcounter > 0.
-relevant = abap_true.
"Find all parents
lv_focus_devclass = -parentcl.
DO 20 TIMES.
IF lv_focus_devclass IS INITIAL.
EXIT.
ENDIF.
READ TABLE lcl_component_documentor=>gt_devclass
ASSIGNING FIELD-SYMBOL()
WITH KEY devclass = lv_focus_devclass.
IF sy-subrc = 0.
-relevant = abap_true.
lv_focus_devclass = -parentcl.
ELSE.
CLEAR lv_focus_devclass.
ENDIF.
ENDDO.
ENDLOOP.
DELETE lcl_component_documentor=>gt_devclass WHERE relevant = abap_false.
ENDMETHOD.
METHOD print_developmentclass.
"Recursive calls
DATA lv_description TYPE string.
IF iv_devclass-objectcounter = 0.
APPEND |
| TO gt_html. "No click-link functionality
ELSE.
APPEND |
| TO gt_html.
ENDIF.
APPEND |
{ iv_devclass-devclass }| TO gt_html.
lv_description = COND #( WHEN iv_devclass-ctext_N <> '' THEN iv_devclass-ctext_N ELSE iv_devclass-ctext_E ).
APPEND |
{ lv_description }
| TO gt_html.
if iv_devclass-objectcounter = 0.
APPEND |
| TO gt_html.
ELSE.
APPEND |
{ iv_devclass-objectcounter } objects
| TO gt_html.
APPEND |
.. of { iv_devclass-tadircounter } objects
| TO gt_html.
endif.
APPEND |
| TO gt_html.
LOOP AT lcl_component_documentor=>gt_devclass INTO DATA(ls_devclass) USING KEY via_parents
WHERE parentcl = iv_devclass-devclass.
print_developmentclass( EXPORTING iv_level = ( iv_level + 1 ) iv_devclass = ls_devclass ).
ENDLOOP.
ENDMETHOD.
METHOD harvest_dates.
"The components on the group have a CREATED and CHANGED date, which needs to be set with information derived from the components.
LOOP AT gt_groups ASSIGNING FIELD-SYMBOL().
-created = sy-datum.
* -changed = '19690308'.
LOOP AT -objects ASSIGNING FIELD-SYMBOL().
-created = sy-datum.
* -changed = '19690308'.
LOOP AT -components->gt_components INTO DATA(ls_component).
CASE ls_component-component_type.
WHEN 'CLASS'.
-created = COND #( WHEN ls_component-class-createdon < -created THEN ls_component-class-createdon ELSE -created ).
-changed = COND #( WHEN ls_component-class-changedon > -changed THEN ls_component-class-changedon ELSE -changed ).
WHEN 'REPORT'.
-created = COND #( WHEN ls_component-report-cdat < -created THEN ls_component-report-cdat ELSE -created ).
-changed = COND #( WHEN ls_component-report-udat > -changed THEN ls_component-report-udat ELSE -changed ).
WHEN 'FUNCTION'.
-created = COND #( WHEN ls_component-function-created_on < -created THEN ls_component-function-created_on ELSE -created ).
-changed = COND #( WHEN ls_component-function-created_on > -changed THEN ls_component-function-created_on ELSE -changed ).
WHEN 'TABLE'.
-created = COND #( WHEN ls_component-table-created_on < -created THEN ls_component-table-created_on ELSE -created ).
-changed = COND #( WHEN ls_component-table-changed_on > -changed THEN ls_component-table-changed_on ELSE -changed ).
ENDCASE.
ENDLOOP.
IF NOT -created IS INITIAL.
-created = COND #( WHEN -created < -created THEN -created ELSE -created ).
ENDIF.
IF NOT -changed IS INITIAL.
-changed = COND #( WHEN -changed > -changed THEN -changed ELSE -changed ).
ENDIF.
ENDLOOP.
ENDLOOP.
ENDMETHOD.
METHOD set_abapdoc.
CHECK lines( it_abapdoc ) > 0.
APPEND '
' TO gt_html.
LOOP AT it_abapdoc INTO DATA(ls_abapdocline).
"@parameter and @exception are ABAPdoc elements that require a bit of special attention
REPLACE '@parameter' IN ls_abapdocline-content WITH '
Parameter'.
REPLACE '@exception' IN ls_abapdocline-content WITH '
Exception'.
REPLACE '|' IN ls_abapdocline-content WITH ''.
APPEND |{ ls_abapdocline-content }| TO gt_html.
ENDLOOP.
APPEND '
' TO gt_html.
ENDMETHOD.
METHOD mini_dot_as_svg.
DATA lv_color TYPE c LENGTH 20.
DATA lv_text TYPE c LENGTH 3.
IF iv_medium = abap_false.
rv_colored_dot = gv_svg_mini_icon.
ELSE.
rv_colored_dot = gv_svg_mini_icon2. "Just a little bigger
ENDIF.
CASE iv_object_type.
WHEN 'CLASS'.
lv_color = 'blue'.
lv_text = 'Cla'.
WHEN 'TABLE'.
lv_color = 'orange'.
lv_text = 'Tab'.
WHEN 'REPORT'.
lv_color = 'purple'.
lv_text = 'Rep'.
WHEN 'FUNCTION'.
lv_color = 'red'.
lv_text = 'Fun'.
WHEN OTHERS.
lv_color = 'black'.
lv_text = '?'.
ENDCASE.
REPLACE 'BLACK' IN rv_colored_dot WITH lv_color.
REPLACE 'TEXT' IN rv_colored_dot WITH lv_text.
ENDMETHOD.
METHOD set_group_header.
DATA lv_colored_dot TYPE char255.
DATA lt_svg_lapse TYPE STANDARD TABLE OF char255.
APPEND |
| TO gt_html.
APPEND |
{ iv_groupnr }.
| TO gt_html.
APPEND |
| TO gt_html.
LOOP AT is_group-objects INTO DATA(ls_object) WHERE object_type <> 'SPACE'.
APPEND mini_dot_as_svg( ls_object-object_type ) TO gt_html.
ENDLOOP.
APPEND |
| TO gt_html.
"Compose an SVG image with a bit of data on it - the create/last change icons
lt_svg_lapse[] = gt_svg_lapse[].
LOOP AT lt_svg_lapse ASSIGNING FIELD-SYMBOL().
REPLACE 'm1' IN WITH get_date_summary( is_group-created ).
REPLACE 'col1' IN WITH set_age_color( is_group-created ).
IF is_group-changed = sy-datum.
REPLACE 'm2' IN WITH 'Today'.
ELSE.
REPLACE 'm2' IN WITH get_date_summary( is_group-changed ).
ENDIF.
REPLACE 'col2' IN WITH set_age_color( is_group-changed ).
APPEND TO gt_html.
ENDLOOP.
APPEND |
| TO gt_html.
APPEND |
| TO gt_html.
APPEND |
{ is_group-description }
| TO gt_html.
APPEND |
| TO gt_html.
IF NOT is_group-summary IS INITIAL.
APPEND |
| TO gt_html.
ENDMETHOD.
METHOD get_date_summary.
DATA lv_components TYPE n VALUE 0.
IF iv_date IS INITIAL.
rv_result = '.'.
EXIT.
ENDIF.
"Number of days into year, week and day
DATA(lv_days_total) = sy-datum - iv_date.
CLEAR rv_result.
DATA(lv_div) = lv_days_total DIV 365.
IF ( lv_div > 0 ).
rv_result = |{ lv_div }j|.
lv_days_total = lv_days_total - ( lv_div * 365 ).
lv_components = lv_components + 1.
ENDIF.
lv_div = lv_days_total DIV 7.
IF ( lv_div > 0 ).
rv_result = |{ rv_result }{ lv_div }w|.
lv_days_total = lv_days_total - ( lv_div * 7 ).
lv_components = lv_components + 1.
ELSEIF lv_components > 0.
RETURN.
ENDIF.
CHECK lv_components < 2.
IF ( lv_days_total > 0 ).
rv_result = |{ rv_result }{ lv_days_total }d|.
lv_components = lv_components + 1.
ELSEIF lv_components > 0.
RETURN.
ENDIF.
ENDMETHOD.
METHOD set_all_tagwords.
DATA lv_all_tagwords TYPE string.
DATA lt_all_tagwords TYPE STANDARD TABLE OF string.
CLEAR lv_all_tagwords.
CLEAR lt_all_tagwords.
LOOP AT is_group-objects INTO DATA(ls_object) WHERE tagwords <> ''.
lv_all_tagwords = |{ lv_all_tagwords } { ls_object-tagwords }|.
ENDLOOP.
CONDENSE lv_all_tagwords.
APPEND |
| TO gt_html.
IF NOT lv_all_tagwords IS INITIAL.
SPLIT lv_all_tagwords AT space INTO TABLE lt_all_tagwords.
SORT lt_all_tagwords.
DELETE ADJACENT DUPLICATES FROM lt_all_tagwords.
lv_all_tagwords = 'Tagwords '.
LOOP AT lt_all_tagwords INTO DATA(lv_tagword).
lv_all_tagwords = |{ lv_all_tagwords } \| { lv_tagword }|.
IF strlen( lv_all_tagwords ) > 150.
APPEND lv_all_tagwords TO gt_html.
CLEAR lv_all_tagwords.
ENDIF.
ENDLOOP.
APPEND |{ lv_all_tagwords }| TO gt_html.
ENDIF.
APPEND '' TO gt_html.
ENDMETHOD.
METHOD set_tagwords.
IF iv_tagwords IS INITIAL.
APPEND |
| TO gt_html.
ELSE.
APPEND |
TAGWORDS
| TO gt_html.
SPLIT iv_tagwords AT space INTO TABLE DATA(lt_tokens).
SORT lt_tokens.
LOOP AT lt_tokens INTO DATA(lv_token).
APPEND |{ lv_token } | TO gt_html.
ENDLOOP.
APPEND |
| TO gt_html.
ENDIF.
ENDMETHOD.
METHOD set_parameter_svg.
CASE iv_parameter_type.
WHEN 0.
APPEND LINES OF gt_svg_exporting TO gt_html.
WHEN 1.
APPEND LINES OF gt_svg_importing TO gt_html.
WHEN 2.
APPEND LINES OF gt_svg_changing TO gt_html.
WHEN 3.
APPEND LINES OF gt_svg_returning TO gt_html.
WHEN 6.
APPEND LINES OF gt_svg_parameter TO gt_html.
WHEN 7.
APPEND LINES OF gt_svg_selectoption TO gt_html.
WHEN 9.
APPEND LINES OF gt_svg_exception TO gt_html.
ENDCASE.
ENDMETHOD.
METHOD set_links.
CHECK lines( is_object-links ) > 0.
APPEND '
External links
' TO gt_html.
LOOP AT is_object-links INTO DATA(ls_link).
APPEND |
' TO gt_html.
LOOP AT is_object-reviews INTO DATA(ls_review).
APPEND || TO gt_html.
APPEND |
| TO gt_html. " style="margin-left:90px;"
DO 5 TIMES.
IF sy-index <= ls_review-rating.
APPEND LINES OF gt_svg_star TO gt_html.
ELSE.
APPEND LINES OF gt_svg_star_empty TO gt_html.
ENDIF.
ENDDO.
APPEND |{ ls_review-summary } | TO gt_html.
string_to_html( ls_review-remarks ).
APPEND | { ls_review-date DATE = USER } \| { ls_review-uname }| TO gt_html.
APPEND | { lcl_component_documentor=>get_username( ls_review-uname ) } { ls_review-username } | TO gt_html.
APPEND '
' TO gt_html.
ENDLOOP.
ENDMETHOD.
METHOD set_object_header.
DATA lt_svg_lapse TYPE STANDARD TABLE OF char255.
DATA lv_review_date TYPE d.
DATA lv_review_text TYPE string.
gv_id = gv_id + 1.
APPEND |
| TO gt_html.
APPEND |
| TO gt_html.
CASE is_object-object_type.
WHEN 'CLASS'.
APPEND LINES OF gt_svg_class TO gt_html.
WHEN 'REPORT'.
APPEND LINES OF gt_svg_report TO gt_html.
WHEN 'TABLE'.
APPEND LINES OF gt_svg_table TO gt_html.
WHEN 'FUNCTION'.
APPEND LINES OF gt_svg_function TO gt_html.
ENDCASE.
APPEND |
{ is_object-object_name }
| TO gt_html.
CLEAR: lv_review_text, lv_review_date.
IF lines( is_object-reviews ) > 0.
LOOP AT is_object-reviews INTO DATA(ls_review).
IF ls_review-date > lv_review_date.
lv_review_date = ls_review-date.
ENDIF.
ENDLOOP.
lv_review_text = |{ lines( is_object-reviews ) } reviews - { get_date_summary( ls_review-date ) }|.
ENDIF.
APPEND |
| TO gt_html.
IF NOT lv_review_text IS INITIAL.
APPEND LINES OF gt_svg_star TO gt_html.
ENDIF.
APPEND |
| TO gt_html.
READ TABLE is_object-components->gt_components INTO DATA(ls_main_component)
WITH KEY component_type = is_object-object_type component_name = is_object-object_name.
IF sy-subrc = 0.
APPEND |{ ls_main_component-description }| TO gt_html.
set_abapdoc( ls_main_component-abapdoc ).
APPEND |
| TO gt_html.
"Compose an SVG image with a bit of data on it - the create/last change icons
lt_svg_lapse[] = gt_svg_lapse[].
LOOP AT lt_svg_lapse ASSIGNING FIELD-SYMBOL().
REPLACE 'm1' IN WITH get_date_summary( is_object-created ).
REPLACE 'col1' IN WITH set_age_color( is_object-created ).
IF is_object-changed = sy-datum.
REPLACE 'm2' IN WITH 'Today'.
ELSE.
REPLACE 'm2' IN WITH get_date_summary( is_object-changed ).
ENDIF.
REPLACE 'col2' IN WITH set_age_color( is_object-changed ).
APPEND TO gt_html.
ENDLOOP.
set_tagwords( is_object-tagwords ).
ELSE.
APPEND |
Sorry ! { is_object-object_type CASE = LOWER } not found
| TO gt_html.
ENDIF.
APPEND |
| TO gt_html.
APPEND |
| TO gt_html.
ENDMETHOD.
METHOD set_group_detail.
DATA lv_value TYPE char120.
APPEND |
| TO gt_html.
APPEND LINES OF gt_svg_screw TO gt_html.
APPEND |
{ iv_created_on DATE = USER } { get_date_summary( iv_created_on ) }
| TO gt_html.
APPEND |
| TO gt_html.
APPEND LINES OF gt_svg_screw TO gt_html.
APPEND |
| TO gt_html.
LOOP AT it_content INTO DATA(ls_content).
lv_value = ls_content-value. "Solution to the problem: how to check whether a string is empty
IF NOT ( ls_content-username IS INITIAL AND ls_content-datevalue IS INITIAL ).
APPEND |
{ ls_content-datevalue DATE = USER } { get_date_summary( ls_content-datevalue ) }
| TO gt_html.
ELSEIF NOT lv_value IS INITIAL.
APPEND |
{ ls_content-label }
{ ls_content-value }
| TO gt_html.
ENDIF.
ENDLOOP.
APPEND '
' TO gt_html.
ENDMETHOD.
METHOD filter_focus.
DATA lr_main_object_types TYPE RANGE OF char10.
DATA lv_inherited_devclass TYPE devclass.
CHECK NOT iv_devclass IS INITIAL.
lr_main_object_types = VALUE #( ( sign = 'I' option = 'EQ' low = 'CLASS' ) ( sign = 'I' option = 'EQ' low = 'REPORT' )
( sign = 'I' option = 'EQ' low = 'TABLE' ) ( sign = 'I' option = 'EQ' low = 'FUNCTION' ) ).
LOOP AT gt_groups ASSIGNING FIELD-SYMBOL().
LOOP AT -objects ASSIGNING FIELD-SYMBOL()
WHERE object_type IN lr_main_object_types.
CLEAR lv_inherited_devclass.
LOOP AT -components->gt_components INTO DATA(ls_component).
lv_inherited_devclass = COND #(
WHEN ls_component-devclass = '' THEN lv_inherited_devclass ELSE ls_component-devclass ).
IF lv_inherited_devclass <> iv_devclass.
DELETE -components->gt_components.
ENDIF.
ENDLOOP.
IF lines( -components->gt_components ) = 0.
DELETE -objects.
ENDIF.
ENDLOOP.
"Are the objects that are still listed all SPACE ?
LOOP AT -objects TRANSPORTING NO FIELDS WHERE object_type <> 'SPACE'.
ENDLOOP.
IF sy-subrc <> 0.
DELETE gt_groups.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD zone_reporter.
DATA lv_component_name TYPE char255.
DATA lv_tab TYPE char20.
set_html_style( ).
set_svg_images( ).
gv_ID = 1000.
APPEND || TO gt_html.
APPEND |
| TO gt_html.
APPEND |
| TO gt_html.
APPEND |
| TO gt_html.
APPEND LINES OF gt_documentheader TO gt_html.
APPEND |
| TO gt_html.
harvest_counters( ).
APPEND |{ lcl_component_documentor=>get_zone_version( ) }| TO gt_html.
APPEND |
{ gs_counters-groups } topics \|
| TO gt_html.
APPEND mini_dot_as_svg( iv_object_type = 'CLASS' iv_medium = abap_true ) TO gt_html.
APPEND |
{ gs_counters-classes } classes \|
| TO gt_html.
IF gs_counters-classmethods > 0.
APPEND |{ gs_counters-classmethods } class-methods \| | TO gt_html.
ENDIF.
IF gs_counters-methods > 0.
APPEND |{ gs_counters-methods } methods \| | TO gt_html.
ENDIF.
APPEND '
' TO gt_html.
IF gs_counters-reports > 0.
APPEND mini_dot_as_svg( iv_object_type = 'REPORT' iv_medium = abap_true ) TO gt_html.
APPEND |
{ gs_counters-reports } reports \|
| TO gt_html.
ENDIF.
IF gs_counters-tables > 0.
APPEND mini_dot_as_svg( iv_object_type = 'TABLE' iv_medium = abap_true ) TO gt_html.
APPEND |
{ gs_counters-tables } tables \|
| TO gt_html.
ENDIF.
IF gs_counters-functions > 0.
APPEND mini_dot_as_svg( iv_object_type = 'FUNCTION' iv_medium = abap_true ) TO gt_html.
APPEND |
{ gs_counters-functions } functions \|
| TO gt_html.
ENDIF.
APPEND |{ gs_counters-objects } total
| TO gt_html.
harvest_developmentclasses( ).
APPEND |
Overview development classes
| TO gt_html.
LOOP AT lcl_component_documentor=>gt_devclass INTO DATA(ls_devclass)
USING KEY via_parents WHERE parentcl = ''.
print_developmentclass( iv_level = 1 iv_devclass = ls_devclass ).
ENDLOOP.
APPEND |
| TO gt_html.
APPEND |
Overview chapters
| TO gt_html.
harvest_dates( ).
LOOP AT gt_groups INTO DATA(ls_group).
DATA(lv_groupnr) = sy-tabix.
gv_ID = gv_ID + 1.
set_group_header( iv_groupnr = lv_groupnr is_group = ls_group ).
APPEND |
| TO gt_html.
LOOP AT ls_group-objects INTO DATA(ls_object).
IF 'CLASS:REPORT:TABLE:FUNCTION' CS ls_object-object_type.
set_object_header( ls_object ).
ENDIF.
CASE ls_object-object_type.
* ====================================================================================================
WHEN 'CLASS'.
* ====================================================================================================
READ TABLE ls_object-components->gt_components INTO DATA(ls_component)
WITH KEY component_type = ls_object-object_type component_name = ls_object-object_name.
set_group_detail( iv_created_by = ls_component-class-author iv_created_on = ls_component-class-createdon
it_content = VALUE #(
( label = 'Last changed by' username = ls_component-class-changedby datevalue = ls_component-class-changedon )
( label = 'Abap coding' value = |{ ls_component-class-linecount } lines in { ls_component-class-methods } methods | &&
|{ COND string( WHEN ls_component-class-redefinitions = 0 THEN '' ELSE |{ ls_component-class-redefinitions } redefinitions| ) } | )
( label = 'Message' value = |{ ls_component-class-message } | )
( label = 'Superclass' value = |{ ls_component-class-superclass }| )
( label = 'Interfaces' value = |{ ls_component-class-interfaces }| )
( label = 'Development class' value = |{ ls_component-devclass } { ls_component-devclass_text }| ) ) ).
set_reviews( ls_object ).
set_links( ls_object ).
IF lines( ls_object-components->gt_components ) > 1.
APPEND '
Components
' TO gt_html.
ENDIF.
DATA(lv_filter_on_methods) = ls_component-class-filter_on_methods.
"Constants
READ TABLE ls_object-components->gt_components WITH KEY component_type = 'CONSTANTS' TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
DATA lv_constants_value TYPE string.
APPEND |
CONSTANTS
| TO gt_html.
LOOP AT ls_object-components->gt_components INTO ls_component
WHERE component_type = 'CONSTANTS'.
lv_constants_value = COND #( WHEN ls_component-attvalue = '' THEN '...' ELSE |= { ls_component-attvalue }| ).
lv_tab = COND #( WHEN ls_component-attvalue = '' THEN '' ELSE ' ' ).
lv_component_name = ||.
IF lines( ls_component-abapdoc ) > 0.
APPEND |
| TO gt_html.
set_abapdoc( ls_component-abapdoc ).
APPEND |{ lv_tab }| TO gt_html.
ELSE.
APPEND |
{ lv_tab }| TO gt_html.
ENDIF.
APPEND lv_component_name TO gt_html.
APPEND |{ ls_component-component_name }
{ lv_constants_value }| TO gt_html.
ENDLOOP.
APPEND |
| TO gt_html.
ENDIF.
"Class-data
READ TABLE ls_object-components->gt_components WITH KEY component_type = 'CLASS-DATA' TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
APPEND |
CLASS-DATA
| TO gt_html.
LOOP AT ls_object-components->gt_components INTO ls_component
WHERE component_type = 'CLASS-DATA'.
DATA(lv_readonly) = COND string( WHEN ls_component-read_only = abap_true THEN '(read only)' ELSE '' ).
lv_component_name = |onclick=navigator.clipboard.writeText("{ ls_component-component_name }");| &&
|window.prompt(decodeURI("Copied%20to%20Clipboard%20..."),"{ ls_component-component_name }");>|.
IF lines( ls_component-abapdoc ) > 0.
APPEND |
| TO gt_html.
set_abapdoc( ls_component-abapdoc ).
APPEND |{ lv_readonly }
| TO gt_html.
ENDLOOP.
APPEND |
| TO gt_html.
ENDIF.
"Instance data
READ TABLE ls_object-components->gt_components WITH KEY component_type = 'DATA' TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
APPEND |
DATA
| TO gt_html.
LOOP AT ls_object-components->gt_components INTO ls_component
WHERE component_type = 'DATA'.
lv_readonly = COND string( WHEN ls_component-read_only = abap_true THEN '(read only)' ELSE '' ).
lv_component_name = |onclick=navigator.clipboard.writeText("{ ls_component-component_name }");| &&
|window.prompt(decodeURI("Copied%20to%20Clipboard%20..."),"{ ls_component-component_name }");>|.
IF lines( ls_component-abapdoc ) > 0.
APPEND |
| TO gt_html.
set_abapdoc( ls_component-abapdoc ).
APPEND |{ lv_readonly }
| TO gt_html.
ENDLOOP.
APPEND |
| TO gt_html.
ENDIF.
"Class-Methodes
LOOP AT ls_object-components->gt_components INTO ls_component
WHERE component_type = 'CLASS-METHODS'.
APPEND |
CLASS-METHOD
| TO gt_html.
APPEND || TO gt_html.
APPEND |{ ls_component-component_name }| TO gt_html.
IF ls_component-redefinition = abap_true.
APPEND |Redefinition| TO gt_html.
ENDIF.
IF ls_component-method_hitcount = 1.
APPEND |(used from 1 location)| TO gt_html.
ELSEIF ls_component-method_hitcount > 1.
APPEND |(used from { ls_component-method_hitcount } locations)| TO gt_html.
ENDIF.
APPEND |
| TO gt_html.
APPEND |
PARAMETERS
| TO gt_html.
LOOP AT ls_component-parameters INTO DATA(ls_parameter).
APPEND '
' TO gt_html.
set_parameter_svg( ls_parameter-pardecltyp ).
APPEND |
{ ls_parameter-parameter }
| TO gt_html.
ENDLOOP.
IF sy-subrc <> 0.
APPEND '
' TO gt_html.
ENDIF.
APPEND '
' TO gt_html.
APPEND |
| TO gt_html.
set_abapdoc( ls_component-abapdoc ).
APPEND '
' TO gt_html.
ENDLOOP.
"Instance methods
LOOP AT ls_object-components->gt_components INTO ls_component
WHERE component_type = 'METHODS'.
APPEND |
METHOD
| TO gt_html.
APPEND || TO gt_html.
APPEND |{ ls_component-component_name }| TO gt_html.
IF ls_component-redefinition = abap_true.
APPEND |Redefinition| TO gt_html.
ENDIF.
IF ls_component-method_hitcount = 1.
APPEND |(used from 1 location)| TO gt_html.
ELSEIF ls_component-method_hitcount > 1.
APPEND |(used from { ls_component-method_hitcount } locations)| TO gt_html.
ENDIF.
APPEND |
PARAMETERS
| TO gt_html.
LOOP AT ls_component-parameters INTO ls_parameter.
APPEND '
' TO gt_html.
set_parameter_svg( ls_parameter-pardecltyp ).
APPEND |
{ ls_parameter-parameter }
| TO gt_html.
ENDLOOP.
IF sy-subrc <> 0.
APPEND '
' TO gt_html.
ENDIF.
APPEND '
' TO gt_html.
APPEND |
| TO gt_html.
set_abapdoc( ls_component-abapdoc ).
APPEND '
' TO gt_html.
ENDLOOP.
"A warning on method-filtering.
IF lv_FILTER_ON_METHODS = abap_true.
APPEND '
Note: not all available PUBLIC methods are displayed (filtering)' TO gt_html.
ENDIF.
APPEND '
' TO gt_html.
* ====================================================================================================
WHEN 'REPORT'.
* ====================================================================================================
READ TABLE ls_object-components->gt_components INTO ls_component
WITH KEY component_type = ls_object-object_type component_name = ls_object-object_name.
DATA lt_group_detail_content TYPE gty_content_tt.
DATA lv_count_text TYPE string.
lv_count_text = COND #( WHEN lines( ls_component-report-includes ) = 0 THEN '' ELSE ' (with includes)' ).
lt_group_detail_content = VALUE #(
( label = 'Last changed by' username = ls_component-report-unam datevalue = ls_component-report-udat )
( label = 'Lines of Abap coding' value = |{ ls_component-report-linecount } { lv_count_text }| )
( label = 'Development class' value = |{ ls_component-devclass } { ls_component-devclass_text }| ) ).
LOOP AT ls_component-report-includes INTO DATA(lv_include).
APPEND VALUE #( label = 'Include' value = lv_include ) TO lt_group_detail_content.
ENDLOOP.
SELECT SINGLE tstct~tcode, tstct~ttext FROM tstc
INNER JOIN tstct ON tstct~tcode = tstc~tcode
INTO (@DATA(lv_tcode), @DATA(lv_ttext))
WHERE pgmna = @ls_object-object_name AND tstct~sprsl = @sy-langu.
IF sy-subrc <> 0.
SELECT SINGLE tstct~tcode, tstct~ttext FROM tstc
INNER JOIN tstct ON tstct~tcode = tstc~tcode
INTO (@lv_tcode, @lv_ttext)
WHERE pgmna = @ls_object-object_name AND tstct~sprsl = 'E'.
ENDIF.
IF sy-subrc = 0.
APPEND VALUE #( label = 'Transaction' value = |{ lv_tcode } { lv_ttext }| ) TO lt_group_detail_content.
ENDIF.
set_group_detail(
iv_created_by = ls_component-report-cnam
iv_created_on = ls_component-report-cdat
it_content = lt_group_detail_content ).
set_reviews( ls_object ).
set_links( ls_object ).
APPEND |
PARAMETERS
| TO gt_html.
READ TABLE ls_object-components->gt_components INTO ls_component INDEX 1.
LOOP AT ls_component-parameters INTO ls_parameter.
IF sy-tabix > 8.
APPEND |
{ lines( ls_component-parameters ) - 8 } more ...
| TO gt_html.
EXIT.
ENDIF.
APPEND |
| TO gt_html.
set_parameter_svg( ls_parameter-pardecltyp ).
APPEND |
{ ls_parameter-parameter }
| TO gt_html.
ENDLOOP.
IF sy-subrc <> 0.
APPEND '
' TO gt_html.
ENDIF.
APPEND '
' TO gt_html.
APPEND '' TO gt_html.
* ====================================================================================================
WHEN 'TABLE'.
* ====================================================================================================
READ TABLE ls_object-components->gt_components INTO ls_component
WITH KEY component_type = ls_object-object_type component_name = ls_object-object_name.
set_group_detail( iv_created_by = ls_component-table-created_by iv_created_on = ls_component-table-created_on
it_content = VALUE #(
( label = 'Last changed by' username = ls_component-table-changed_by datevalue = ls_component-table-changed_on )
( label = 'Has table maintenance' value = |{ COND #( WHEN ls_component-table-maintenance = abap_true THEN 'Yes' ELSE 'No' ) }| )
( label = 'Development class' value = |{ ls_component-devclass } { ls_component-devclass_text }| ) ) ).
set_reviews( ls_object ).
set_links( ls_object ).
APPEND '
Definition
' TO gt_html.
APPEND '
Fieldname
Type
Description
' TO gt_html.
DATA lv_fields TYPE string.
DATA lv_fieldname TYPE string.
DATA lv_html_line TYPE string.
DATA lv_description TYPE string.
DATA lv_type TYPE char40.
CLEAR lv_fields.
LOOP AT ls_component-table-dd03l INTO DATA(ls_dd03l) WHERE fieldname(5) <> '.INCL'.
* Field description and type definition:
lv_fieldname = |{ ls_object-object_name }-{ ls_dd03l-fieldname }|.
lv_description = lcl_component_documentor=>get_sap_description( fieldreference = lv_fieldname ).
WRITE: ls_dd03l-leng TO lv_type NO-ZERO LEFT-JUSTIFIED.
SHIFT lv_type RIGHT BY 1 PLACES.
lv_type(1) = ls_dd03l-inttype.
lv_type = |{ lv_type }|.
CONDENSE lv_type NO-GAPS.
* Field (or key field)
lv_html_line = COND #( WHEN ls_dd03l-keyflag = abap_true THEN |{ ls_dd03l-fieldname }| ELSE |{ ls_dd03l-fieldname }| ).
APPEND |
{ lv_html_line }
{ lv_type }
{ lv_description }
| TO gt_html.
lv_fields = lv_fields + 1.
IF lv_fields > 50.
APPEND |
Only 50 fields listed
| TO gt_html.
EXIT.
ENDIF.
ENDLOOP.
APPEND '
' TO gt_html.
* ====================================================================================================
WHEN 'FUNCTION'.
* ====================================================================================================
READ TABLE ls_object-components->gt_components INTO ls_component
WITH KEY component_type = ls_object-object_type component_name = ls_object-object_name.
set_group_detail( iv_created_by = ls_component-function-author iv_created_on = ls_component-function-created_on
it_content = VALUE #(
( label = 'Area' value = ls_component-function-area )
( label = 'Where-used: used from' value = |{ ls_component-function-hitcount } locations| )
( label = 'Lines of Abap coding' value = ls_component-function-linecount )
( label = 'Development class' value = |{ ls_component-devclass } { ls_component-devclass_text }| ) ) ).
set_reviews( ls_object ).
set_links( ls_object ).
APPEND |
PARAMETERS
| TO gt_html.
LOOP AT ls_component-parameters INTO ls_parameter.
APPEND '
' TO gt_html.
set_parameter_svg( ls_parameter-pardecltyp ).
APPEND |
{ ls_parameter-parameter }
| TO gt_html.
ENDLOOP.
IF sy-subrc <> 0.
APPEND '
' TO gt_html.
ENDIF.
APPEND '
' TO gt_html.
APPEND '' TO gt_html.
* ====================================================================================================
WHEN 'SPACE'.
* ====================================================================================================
"A bit of space on the overview
APPEND '
' TO gt_html.
ENDCASE.
ENDLOOP.
APPEND '
' TO gt_html.
ENDLOOP.
APPEND |
{ sy-datum DATE = USER } on SAP { sy-sysid } report/transaction { sy-repid }
| TO gt_html.
APPEND '' TO gt_html.
ENDMETHOD.
ENDCLASS.
PARAMETERS pa_devcl TYPE devclass NO-DISPLAY.
START-OF-SELECTION.
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
percentage = 0
text = 'Starting up and gathering information...'.
DATA(go_documentation) = NEW lcl_document_groups( ).
* ====================================================================================================
INCLUDE zone_script.
* ====================================================================================================
"Apply development class filter - when applicable
go_documentation->filter_focus( pa_devcl ).
"Fetch the development class hierarchy - custom classes only
lcl_component_documentor=>read_developmentclasses( ).
go_documentation->zone_reporter( ).
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
percentage = 0
text = 'Enjoy...'.
CALL SCREEN 900.
MODULE status_0900 OUTPUT.
SET PF-STATUS 'MAIN'.
SET TITLEBAR '001'.
IF go_documentation->go_container IS INITIAL.
CREATE OBJECT go_documentation->go_container
EXPORTING
container_name = 'CUSTOM_CONTROL'
EXCEPTIONS
OTHERS = 4.
CREATE OBJECT go_documentation->go_html_control
EXPORTING
parent = go_documentation->go_container.
"To enable response from the HTML document
go_documentation->gt_myevents = VALUE #(
( eventid = go_documentation->go_html_control->m_id_sapevent
appl_event = 'x' ) ).
CALL METHOD go_documentation->go_html_control->set_registered_events
EXPORTING
events = go_documentation->gt_myevents.
CREATE OBJECT go_documentation->go_event_receiver.
SET HANDLER go_documentation->go_event_receiver->handle_sapevent
FOR go_documentation->go_html_control.
"Load the html control with the (already prepared) html/javascript content
go_documentation->go_html_control->load_data(
IMPORTING assigned_url = go_documentation->gv_url
CHANGING data_table = go_documentation->gt_html ).
ENDIF.
go_documentation->go_html_control->show_url(
EXPORTING url = go_documentation->gv_url ).
ENDMODULE.
MODULE user_command_0900 INPUT.
CASE gv_okcode.
WHEN 'BACK' OR 'LEAVE'.
LEAVE PROGRAM.
WHEN 'DOWNLOAD'.
DATA lv_returncode TYPE sy-subrc.
cl_gui_frontend_services=>clipboard_export(
IMPORTING data = go_documentation->gt_html
CHANGING rc = lv_returncode
EXCEPTIONS OTHERS = 4 ).
IF sy-subrc = 0 AND lv_returncode = 0.
MESSAGE 'Full HTML content placed on clipboard' TYPE 'S'.
ENDIF.
ENDCASE.
ENDMODULE.
Parameter'. REPLACE '@exception' IN ls_abapdocline-content WITH '
Exception'. REPLACE '|' IN ls_abapdocline-content WITH ''. APPEND |{ ls_abapdocline-content }| TO gt_html. ENDLOOP. APPEND '