SAP R/3 форум ABAP консультантов
Russian ABAP Developer's Club

Home - FAQ - Search - Memberlist - Usergroups - Profile - Log in to check your private messages - Register - Log in - English
Blogs - Weblogs News

ZICDOC - HTML documentation generator for ABAP programs



 
Post new topic   Reply to topic    Russian ABAP Developer's Club Forum Index -> Project Management | Управление проектами, документация и стандарты
View previous topic :: View next topic  
Author Message
admin
Администратор
Администратор



Joined: 01 Sep 2007
Posts: 1639

PostPosted: Fri Nov 28, 2008 2:07 am    Post subject: ZICDOC - HTML documentation generator for ABAP programs Reply with quote

Author: Cwir Ireneusz
Source: https: //www.sdn.sap.com/irj/sdn/weblogs?blog=/pub/wlg/8528

1 ZICDOC introduction
1.1 What is ZICDOC generator

ZICDOC is an ABAP program, which ties to analyze source code of other ABAP program and create then HTML documentation. It is based mainly on comments extracted from source code, but it also recognize a few simple objects like database tables, forms, classes and similar code blocks and tries to assign comments to these objects. As a result, you can receive HTML file describing analyzed program. The level of details depend on what programmer "left" in source code.

1.2 Short story

Documenting source code of any program is crucial for it's later maintenance and extending. There are many tools for storing documentation (from word processors and file systems to advanced and sophisticated databases with version management, workflows and other wonderful functionalities). But programmers don't like to use them. After several program's modification, such a documentation is typically outdated and sooner or later - useless. I see, that the only place where programmers eventually leave additional information is source code (comments).

Suppose, that you have wonderful, detailed and up-to-date information inside source code of your program. That's great, but it isn't the end of you problems. You probably write a program not for yourself. Very soon your manager, quality controller or customer will ask you for any kind of documentation of your work...

It would be nice to have any tool which will automatically create such a documentation based on information in source code. There are several such a tools on the market - JAVADOC is good example, which solves problem of Java programmers. Unfortunately, I have not found such a generator for ABAP (I mean freeware, I heard some time ago about similar tool for ABAP, but it was very expensive).

I have been thinking about automatic documentation generator for several months, but I have had no motivation do it. I have started programming it, but never finished. About one year ago, I have decided finally to go into object-oriented ABAP (learn it) and it was turning point. I was looking for any real task for implementing (not just simple report displaying data from several tables) and I reminded about the generator.

After a few weeks, I had a class analyzing source code and storing results in internal tables. The next step was preparing any solution for displaying these results. At the beginning, I considered creation of XML files and then preparing XML transformations for converting XML data into more readable HTML, PDF or any other format. But, when I looked into details of XMLT - I gave up. It is so complex like new programming language. Finally, I did not decide to learn XML, XMLT and HTML, but just only HTML (it was also new for me). I only introduced CSS (cascade style sheets) to be more flexible with formatting output information.

Now, if you know that the ZICDOC project was for me the first contact with object-oriented ABAP, HTML and CSS, I hope that you will be more patient reading source code of the generator. It still needs some improvements or corrections, but at he moment I have no time to do it.
1.4 SAP R/3 versions

Program was tested mainly on WAS 6.40 and WAS 7.0, but it should work on all versions of WAS. It was also tested a little on 4.6C (I started on this version), but It offers oldest version of statement SCAN ABAP-SOURCE. It has different syntax and results. Source code of the generator contains part described with word COMPATYBILITY (for 4.6C), so it is probably possible to adjust program to that version.

2 Using ZICDOC
2.1 Installation

ATTENTION!
Due to size limit of single Weblog, I had to put source code of programs in part II, III and IV of the blog.

I tried not to use any nonstandard dictionary objects. You can even find, that I haven't used program text for HTML tags, but created them as constants. So, it should be enough just to create all ABAP programs and then activate them. If you want to understand what fields are on selection screen of the main program, copy texts from source code (they are at the beginning ) to selection texts.

Additionally, you have to create file ZIcDocStyle.css.

You should create the following programs:
ZICDOC - the main program (type ‘1') of the generator. It is ready-to-use program or just example how to call generator from other programs.
ZICDOC_CL_HTML - include (type ‘I') with class supporting creation of HTML file
ZICDOC_CL_CODE_ANALYSIS - include containing class for source code analysis
ZICDOC_CL_CODE_ANALYSIS_HTML - include with class analyzing code and creating HTML documentation
1.1 Starting generator

The main program of generator is ZICDOC. Selection screen is below:


It allows entering the path to generated output HTML file.

As a input you have two options:
Enter a name of the program in the system (it is suggested). You can try with ZICDOC itself, so you will have documentation of the generator.
Enter a name and path of file on local disk with source code to be analyzed. This option limits analysis to this single file - any INCLUDES are not taken into account.

Additionally, you can influence the content of generated file (see also section 4). The meaning of options is the following:
INCLUDES - hierarchy - generates section with a list of includes of the main analyzed program. See: 4.1.
INCLUDES - details - generates section with information about each include (name, comments, list of code units). See: 4.3.
Database tables - generates section with a list of database tables accessed from the analyzed program. See: 4.2.
Class components - generates section with details and components of classes and interfaces. See: 4.4.
Non-class code units - generates section with list of list events, form, function modules and other code units. See: 4.5.
Code units hierarchy - generates section with hierarchy of class (for instance one for from another). See: 4.6.
Protected class components - if protected components have to be placed in output file (in addition do public).
Private class components - if private components have to be placed in output file (in addition do public).
Comments include HTML tags - if selected, comments are written to HTML file without any conversion. It allows using formatting tags inside comments (like <br>), but characters like &, <, > can disappear in output file. If you not select this check box, comments are converted to HTML text. Characters like &, <, > are outputted correctly (converted to special strings), but you cannot use HTML tags in your comments.



After starting program, and waiting several seconds, you will (hopefully) see message, that NNNN bytes transferred. It means that your program has been analyzed and you can see results.

Attention!
To see correctly HTML file, you must place in the same folder file with styles: ZIcDocStyle.css. You can find additional information in section 2.6).
1.2 Prerequisites

Before you can create with ZICDOC documentation for any program, the analyzed source code:
Should be activated (at least syntax check performed). Behavior of the generator during analyzing of code with syntax errors is undefined.
It is suggested to verify comments in the analyzed code and, if possible, adjust it to standards described in this documents.
1.3 Basic functionality

The generator tries to find comments I source code and assign them to code units (like programs, forms, classes, etc). This information is later used to create documentation for these units. Program recognizes the following types of statements:
Comments - specials rules apply (see section 3)
List events - like: START-OF-SELECTION, END-OF-SELECTION, INITIALIZATION, GET, AT.
Database operation statements - like: TABLES, SELECT, UPDATE, INSERT, MODIFY, DELETE. Based on them, list of tables used in the program can be built. It doses not cover operation performed in function modules called from the program (they are not analyzed).
Class and interface definition. List of components are built.
Form definition and call - like FORM, PERFORM
Report calls - like SUBMIT
Function module definition - like FUNCTION. The program has not been test for function groups, so it can require improvements.
Method definition - like METHOD
Function and methods calls - like CALL xxx (FUNCTION, CUSTOMER-FUNCTION, BADI, METHOD, TRANSACTION).
1.4 Technical description of ZICDOC

I tried to write documentation of the ZICDOC in the source code. Try to generate HTML file for the program (it can be the first exercise). Additional information you will find directly in source code.

In general, the generator is based on built-in keyword SCAN ABAP-CODE (see online help for ABAP). It performs decomposition of source code into single statements and tokens. They can be later analyzed by your own program.
1.5 Cascade Style Sheets

Generation of output HTML file is based on CSS. It allows using simple HTML tags in generated document and storing formatting information in separate file. You can, for instance, have several CSS files with different formatting, and depending on which one is used, different result will be displayed. You can experiment with CSS file and change different options. You can receive quite interesting results.

The name of CSS file is inside HTML file (in the header). The name of file is ZIcDocStyle.css and it must be located in the same directory as the main HTML file. Of course, you can edit HTML file and easy change the name of used CSS file.
1.5.1 CSS for beginners

CSS files can be edit with dedicated editors (which show you formatting options in dialog windows) or just any plain text editor (like Notepad). In the file, you can assign formatting options (like font name and size, color, table cell width) to specific HTML tags. For instance, headers are displayed with style H1 (in HTML document: <h1>Header text</h1>). In CSS file we define, that this style uses sans-serif font, size of 160% of default, bold and wit additional space before and after. Important thing - if you don't define a specific parameter - it is derived from parent node. It is a little complicated to explain here, but there are many free HTML and CSS courses on WEB.

I have used three basic forms of defining styles (it was an exercise for me):
Define style for single tags - like for <h1> to <h6>, <body>, <dfn> and others
Define style for nested tags - used for pair <td><samp>. If tag <samp> is nested inside <td> (inside tables cell) then width of a cell must be equal 25ex. By nesting, I understand: <td><samp>Any text in cell</samp></td>
Define class for tag - used for TD.dbname. This style is used when in HTML document you use <td class="dbname">Text</td>.
2 Comments

Generated documentation is based mainly on comments entered by programmer. This section describes rules, which should be considered.
2.1.1 General rules

Source code comments are very important for understanding usage of functions, forms, objects and individual lines of code. Therefore, program reads comments and places them in output file as description of specific objects.

Depending on a context, comments can describe code before or after it. To assign comments to right objects, strict rules must be applied by a programmer. The most important are described below.
All following lines of comments are treated as continuous string and are concatenated into one paragraph (section, segment). New paragraph starts when:
- Blank line is between lines of comment (without even *)
- After any code statement
Program assigns single paragraph to specific objects. It means, that if we have several paragraphs (separated by blank lines), only the first or the last will be used. If you want to use blank lines as visual separators inside comments, enter single * at the beginning of the blank line.
All comments beginning with " (quotation marks) not in the first column are ignored.
All comments, which has 3 the same character starting on 4-th column are ignored (all comments separating parts of code are ignored). Example: *& ---------
Program recognizes special comments types. They are cognized by beginning characters of the first line of comment paragraph (details below):
*& - comment on program level
*" - comment inside function or other type of coding block (form, method, class)
* or " - other comment
Comments describing programs and includes should start with characters: *& (asterix + ampersand). They are treated in special way - the first appearance of such a comment is assigned to program (include). All others (following) are treated in normal way (like comment before the next statement). As a result, program's description can be placed at the end of the program (if there is no other above, like generated by Pretty Printer for forms.) See additional description below.
All comments inside implementation of forms, methods and similar coding blocks are ignored, except starting with two characters: *". They can be placed inside block, but refer not to the following statement, but block as general (see point 3.1.4).
There should be at least one blank line after program comments and the following comments (for instance assigned to form or program event).
It is possible to place special predefined tags (variables) at the beginning of comment. They start with @ (at). The list of predefined tags is below. Tags starts different parts of comment and can be used to generate a special output format (for instance use different colors or font for each comment's part).
Comments can include HTML formatting tags. The typical is <br> for line break. If you need then to write characters: <, >, &, | or ~, you need to enter:
< &lt;
> &gt;
& &amp;
| &brvbar;
~ &tilde;
It is controlled by parameter on selection screen of the ZICDOC program.
2.1.2 Special tags in comments

Comments can contain variables (tags) starting with character @. They can be any single word. There are several predefined (assumed to be used) but other are treated in the same way - a special formatting cab be applied in output file.

List of examples:
@Info - description of the object. It is default tag for comment, so it is assigned also if no tag has been written at the beginning of the comment. The word Info is not outputted to HTML file.
@Author - author of the code
@Date - date of creation
@Change - change details

The following tags are treated in different way. The generator use the word following the tag as its special parameter (like in: * @Param I_MATNR Material number). Parameters can be issued with different formatting options (font). Only the following predefined variables can have parametrs (it is hard-coded):
@Param - parameter of form, method
@Using - parameter of form
@Change, @Changing - parameter of form
@Import, @Importing - import parameter
@Export, @Exporting - export parameter
@Return, @Returning - return parameter
@Receiving - parameter of method
@Tables - table parameter
@Throws, @Exception, @Raising - exception generated by code
2.1.3 Program comments

At the beginning of each main program or include it is possible to write comment describing this unit. This comment is recognized by beginning characters: *&. It is not required, that all lines of this part begins with these 2 characters. It is enough, that the first line begins with them. All following lines can begin with single character *.

Program comment can start in any line of code, even at the end of program. I suggest to enter it at the beginning, because Pretty Printer generates form's header comments beginning wit *&, so it can lead to unexpected results. Program comment ends with the firs blank line or statement (just no-comment). Example:

Code:
*&---------------------------------------------------------------------*
*& Report  ZICDOC_TEST1
*&
*&---------------------------------------------------------------------*
*& @Author Ireneusz Cwir
*& @Date 18.01.2008
*& @Info Program for testing documentation generation by ZICDOC
*&---------------------------------------------------------------------*
* This comment, although doesn't begin with '*&' belong to program's
* description part. It is because there is no empty line between
* above section and this section.<br> It will start in new line -
* thanks to HTML tag: &lt;br&gt;
* Line with horizontal separator is ignored.
*
* This comment also belongs to above section, because line above
* starts with '*', so it is no really blank line.

* This doesn't belong to previous section, because there is really
* empty line above.



2.1.4 Code units comments

Comments for forms, list events and other similar code units are placed before the unit. The last continuous section of comment (without blank line) before unit is assigned to that unit.

Comments can contain special tags using for marking special sections of comments (like author, date, parameters - see point 3.1.2).

If you want to output comment from inside form or method, you must use comment starting with*".
3 Output file sections

Output HTML file can contain different sections. Selection screen parameters control this. Sections are describe below.
3.1 Hierarchy of programs and includes

Section lists all includes used in the program. They are printed as subnodes of the analyzed program. This section contains also macros called from the program. If source code of include has been available for analysis and detailed section should be generated, nodes are created as links to detailed descriptions of each include.
3.2 Database tables

Section lists database tables used in the program (covers includes). The following information is displayed for each table:
Table name
Access mode:
T - declaration with TABLES statement
S - select
U - update
I - insert
M - modify (update or insert)
D - delete
Table title - from dictionary
3.3 Programs and includes summary

This section contains the following information for each program (include):
Program name
Program title - from attributes screen of a program
Program description - from program comments (see point 3.1.3)
List of events, forms and other code units defined in the program (include)
3.4 Class components

Section contains more detailed information about classes defined and implemented in analyzed program:
Class name and its declaration
Base class
Attributes and methods with comments - based on class definition. Comments are displayed also from method implementation.
3.5 Non-class code units

Section contains more detailed information about code units in each program (include):
Type of code unit (list event, form, function)
Name of the unit
Parameters of the unit
Database tables affected by the unit (with access mode: reads, updates - see point 4.2)
Unit description - comments before unit code

3.6 Code units calls hierarchy

The section contains hierarchy of calls of forms, function modules and other code units. It is intended for documenting reports. Then, list events are roots of calls. Other program types have not been tested. For instance, it does not list calls made from class methods.

ZICDOC does not recognize methods calls if short version are used.

Cwir Ireneusz is internal R/3 support team member in Cadbury Wedel.


Last edited by admin on Fri Nov 28, 2008 2:15 am; edited 2 times in total
Back to top
View user's profile Send private message
admin
Администратор
Администратор



Joined: 01 Sep 2007
Posts: 1639

PostPosted: Fri Nov 28, 2008 2:08 am    Post subject: Reply with quote

This post is the second part of WeBlog describing ZICDOC - generator of HTML description of ABAP program.

I tried not to use any nonstandard dictionary objects. You can even find, that I haven't used program text for HTML tags, but created them as constants. So, it should be enough just to create all ABAP programs and then activate them. If you want to understand what fields are on selection screen of the main program, copy texts from source code (they are at the beginning ) to selection texts.

Additionally, you have to create local file ZIcDocStyle.css and paste into it content from the field below:


Code:
   <!-- Default font for the document -->
   BODY {
          font-family: "Verdana", "Arial", "Helvetica", "sans-serif";
          font-size: x-small;
        }

   <!-- Document title -->
   H1 {
          font-family: "Verdana", "Arial", "Helvetica", "sans-serif";
          font-size: 160%;
          font-weight: bold;
          padding-top: 10pt;
          padding-bottom: 10pt;
      }

   <!-- Titles of main sections - frames with blue background -->
   H2 {
          font-family: "Verdana", "Arial", "Helvetica", "sans-serif";
          font-size: 160%;
          font-weight: bold;
          padding-top: 8pt;
          padding-bottom: 8pt;
          border-top: medium double;
          border-bottom: medium double;
          border-left: medium double;
          border-right: medium double;
          background-color: lightsteelblue;
      }

   <!-- Titles of subsection - frames with light gray background -->
   H3 {
          font-family: "Verdana", "Arial", "Helvetica", "sans-serif";
          font-size: 140%;
          font-weight: bold;
          padding-top: 5pt;
          padding-bottom: 5pt;
          border-top: medium double;
          border-bottom: medium double;
          border-left: medium double;
          border-right: medium double;
          background-color: whitesmoke;
      }

   <!-- Titles of lists like: database tables, components, forms -->
   H4 {
          font-family: "Verdana", "Arial", "Helvetica", "sans-serif";
          font-size: 120%;
          font-weight: bold;
          font-style: italic;
          padding-top: 4pt;
          padding-bottom: 4pt;
      }

   <!-- Names of code units (class components, forms, events) -->
   H5 {
          font-family: "Verdana", "Arial", "Helvetica", "sans-serif";
          font-size: 110%;
          font-weight: bold;
          padding-top: 4pt;
          padding-bottom: 4pt;
      }

   <1-- Not used -->
   H6 {
          font-family: "Verdana", "Arial", "Helvetica", "sans-serif";
          font-size: 10pt;
          font-weight: bold;
          font-style: italic;
          padding-top: 4pt;
          padding-bottom: 4pt;
      }

   <!-- In lists: names of objects  (includes, components, ...) -->
   DFN {
          font-family: "Courier New", "Courier", "monospace";
          font-weight: bold;
          font-style: normal;
       }

   <!-- In lists: types of objects (like: Title, Method, Form) -->
   SAMP {
          font-family: "Verdana", "Arial", "Helvetica", "sans-serif";
          font-size: 90%;
          font-style: italic;
        }


   CODE {
          font-family: "Courier New", "Courier", "monospace";
          font-size: 100%;
        }

   VAR {
          font-family: "Courier New", "Courier", "monospace";
          font-size: 100%;
          font-style: italic;
       }

   DT {
          font-family: "Verdana", "Arial", "Helvetica", "sans-serif";
          font-weight: bold;
      }

   DD {
          font-family: "Verdana", "Arial", "Helvetica", "sans-serif";
          font-size: 110%;
      }

   TD SAMP {
          width: 25ex;
           }

   TD.dbname {
          width: 20ex;
             }

   TD.dbaccess {
          width: 15ex;
               }
Back to top
View user's profile Send private message
admin
Администратор
Администратор



Joined: 01 Sep 2007
Posts: 1639

PostPosted: Fri Nov 28, 2008 2:09 am    Post subject: Reply with quote

You should create the following programs:
ZICDOC - the main program (type ‘1') of the generator. It is ready-to-use program or just example how to call generator from other programs.
ZICDOC_CL_HTML - include (type ‘I') with class supporting creation of HTML file
ZICDOC_CL_CODE_ANALYSIS - include containing class for source code analysis
ZICDOC_CL_CODE_ANALYSIS_HTML - include with class analyzing code and creating HTML documentation

Code:
*&---------------------------------------------------------------------*
*& Report  ZICDOC
*&
*&---------------------------------------------------------------------*
* @Author Ireneusz Cwir
* The main program of ZICDOC generator. It shows also how to call
* program analysis and HTML file generation from other code.

REPORT  zicdoc LINE-SIZE 256.

* These texts are defined in properties of the program.
* You can uncomment them (optionally) and copy to right fields.
*
* Title (Goto -> Attributes)
* ZICDOC - ABAP documentation generator
*
* Selection parametrs (Goto -> Text elements -> Selection texts):
*P_CCPRIV   Private class components
*P_CCPROT   Protected class components
*P_CLSCMP   Class components
*P_FHTML  Output file name (html)
*P_FSRC   Cource code file name
*P_HTMLCM   Comments include HTML tags
*P_INCDET   INCLUDES - details
*P_INCHIE   INCLUDES - hierarchy
*P_PROG   Analysed program name
*P_TABLES   Database tables
*P_UNTDET   Code units - details
*P_UNTHIE   Code units - hierarchy


PARAMETERS: p_prog  LIKE trdir-name DEFAULT 'ZICDOC_TEST1',
            p_fsrc  LIKE rlgrap-filename DEFAULT 'd:\Z22IC002.txt'.
SELECTION-SCREEN SKIP 1.
PARAMETERS: p_fhtml LIKE rlgrap-filename DEFAULT 'D:\ZICDOC_TEST1.html'.

SELECTION-SCREEN SKIP 1.
PARAMETERS: p_inchie AS CHECKBOX DEFAULT 'X',
            p_incdet AS CHECKBOX DEFAULT 'X',
            p_clscmp AS CHECKBOX DEFAULT 'X',
            p_unthie AS CHECKBOX DEFAULT 'X',
            p_untdet AS CHECKBOX DEFAULT 'X',
            p_tables AS CHECKBOX DEFAULT 'X'.

SELECTION-SCREEN SKIP 1.
PARAMETERS: p_ccprot AS CHECKBOX DEFAULT 'X',
            p_ccpriv AS CHECKBOX DEFAULT 'X'.

SELECTION-SCREEN SKIP 1.
PARAMETERS: p_htmlcm AS CHECKBOX DEFAULT 'X'.

*----------------------------------------------------------------------

* Include classe for code analysis and HTML file generation
INCLUDE zicdoc_cl_code_analysis_html.

*----------------------------------------------------------------------
* Reference to the main objectof analysis.
DATA: ref_html TYPE REF TO zcl_ic_code_analysis_html.

* Additional data
DATA: gv_str TYPE string.
DATA: gv_retcode TYPE i.

*----------------------------------------------------------------------
START-OF-SELECTION.

* Create object for code analysis
  CREATE OBJECT ref_html.

* Depending on parameters entered on selection screen, call method for
* anlysing code of program in the system or code uploaded
* from local file (from presentation server or PC).
  IF p_prog IS NOT INITIAL.

    gv_retcode = ref_html->analyse_program( p_prog ).

  ELSEIF p_fsrc IS NOT INITIAL.

    gv_str = p_fsrc.
    gv_retcode = ref_html->analyse_file( gv_str ).

  ELSE.

    WRITE:/ 'No program specified for analysis!'.
    EXIT.

  ENDIF.

  IF gv_retcode <> 0.
    WRITE:/ 'Scan ERROR:', gv_retcode.
  ENDIF.
  CHECK gv_retcode = 0.

* Type conversion (output file name)
  gv_str = p_fhtml.

* Create HTML file with documentation.
  CALL METHOD ref_html->write_html_file
    EXPORTING
      i_filename                    = gv_str
      i_write_includes_hier         = p_inchie
      i_write_includes_details      = p_incdet
      i_write_class_components      = p_clscmp
      i_write_class_components_prot = p_ccprot
      i_write_class_components_priv = p_ccpriv
      i_write_code_units_hier       = p_unthie
      i_write_code_units_details    = p_untdet
      i_write_tables                = p_tables
      i_html_comments               = p_htmlcm
    RECEIVING
      ret_code                      = gv_retcode.


* Helper function for displaying tables with results of code scanning.
* Uncomment them if you are interested in further development of ZICDOC
* and you want to understand details of the code analysis.
*  CALL METHOD ref_html->dump_statements.
*  CALL METHOD ref_html->dump_statements_detailed.
*  CALL METHOD ref_html->dump_tables_scan.
Back to top
View user's profile Send private message
admin
Администратор
Администратор



Joined: 01 Sep 2007
Posts: 1639

PostPosted: Fri Nov 28, 2008 2:09 am    Post subject: Reply with quote

Code:
   
*&---------------------------------------------------------------------*
*&  Include           ZICDOC_CL_HTML
*&---------------------------------------------------------------------*
* Contains helper methods for creating HTML file.

CLASS zcl_ic_html DEFINITION.
  PUBLIC SECTION.

*   Table with content of HTML document (source text of document).
    DATA: gt_content TYPE STANDARD TABLE OF string.

    METHODS: constructor.
    METHODS: reset.

*   Returns string afetr conversion to HTML internal format
*   (e.c. '<' is replaced by '<'
    METHODS: str2html IMPORTING i_str TYPE string
                      RETURNING value(e_str) TYPE string.
*   Add string with or  without conversion to internal format
    METHODS: add_string IMPORTING str TYPE string,
             add_string_raw IMPORTING str TYPE string.

*   Moves content of internal line buffer to document (like new line).
    METHODS: flush_buffer.

    METHODS: add_tag_start IMPORTING tag TYPE string,
             add_tag_end IMPORTING tag TYPE string,
             add_tag IMPORTING tag TYPE string str TYPE string.
    METHODS: add_header1 IMPORTING str TYPE string,
             add_header2 IMPORTING str TYPE string,
             add_header3 IMPORTING str TYPE string,
             add_header4 IMPORTING str TYPE string,
             add_header5 IMPORTING str TYPE string,
             add_header6 IMPORTING str TYPE string,
             add_paragraph IMPORTING str TYPE string,
             add_line_break,
             add_blank_line.

*   Returns string (str...) or appends (add...) tag elements
*   for links inside document. a_name is an anchor on a page,
*   a_href is a refernce to an anchor. i_label must be unique
*   identifier of an anchor. i_text is a text displayed as a reference.
    METHODS: str_a_href IMPORTING i_label TYPE string
                                  i_text TYPE string
                        RETURNING value(e_str) TYPE string,
             str_a_name IMPORTING i_label TYPE string
                                  i_text TYPE string
                        RETURNING value(e_str) TYPE string,
             add_a_href IMPORTING i_label TYPE string
                                  i_text TYPE string,
             add_a_name IMPORTING i_label TYPE string
                                  i_text TYPE string.
*   Starts new document - place several tags
    METHODS: start_document IMPORTING i_title TYPE string
                                      i_code_page TYPE string
                                      i_css_file_name TYPE string
                                      i_comment TYPE string,
             end_document.

*   Writes HTML document to disk
    METHODS: write_file IMPORTING file_name TYPE string
                        RETURNING value(ret_code) TYPE i.

  PRIVATE SECTION.

    DATA: lv_buffer TYPE string.

ENDCLASS.                    "zcl_ic_html DEFINITION


*----------------------------------------------------------------------*
*       CLASS zcl_ic_html IMPLEMENTATION
*----------------------------------------------------------------------*

CLASS zcl_ic_html IMPLEMENTATION.

  METHOD constructor.
    CALL METHOD reset.
  ENDMETHOD.                    "constructor

  METHOD reset.
    REFRESH: gt_content.
    CLEAR: lv_buffer.
  ENDMETHOD.                    "reset

  METHOD add_tag_start.
    CONCATENATE lv_buffer '<' tag '>' INTO lv_buffer.
  ENDMETHOD.                    "add_tag_start

  METHOD add_tag_end.
    CONCATENATE lv_buffer '</' tag '>' INTO lv_buffer.
  ENDMETHOD.                    "add_tag_end

  METHOD add_tag.
    CALL METHOD flush_buffer.
    CALL METHOD add_tag_start( tag ).
    CALL METHOD add_string( str ).
    CALL METHOD add_tag_end( tag ).
    CALL METHOD flush_buffer.
  ENDMETHOD.                    "add_tag

  METHOD str2html.
    DATA: str TYPE string,
          len TYPE i, cur TYPE i, cnt TYPE i,
          off1 TYPE i,
          lv_char TYPE c, lv_spec(20) TYPE c.

    off1 = 0.
    len = STRLEN( i_str ).
    DO len TIMES.
      cur = sy-index - 1.
      lv_char = i_str+cur(1).
      CASE lv_char.
        WHEN '<'.
          lv_spec = '<'.
        WHEN '>'.
          lv_spec = '>'.
        WHEN '&'.
          lv_spec = '&'.
        WHEN '|'.
          lv_spec = '¦'.
        WHEN '~'.
          lv_spec = '˜'.
        WHEN OTHERS.
          IF sy-index = len.   " last char
            lv_spec = lv_char.
          ELSE.
            lv_spec = space.
          ENDIF.
      ENDCASE.
      IF lv_spec <> space.
        cnt = cur - off1.
        CONCATENATE str i_str+off1(cnt) lv_spec INTO str.
        off1 = sy-index.
      ENDIF.
    ENDDO.
    e_str = str.
  ENDMETHOD.                                                "str2html


  METHOD add_string.
    DATA: txt TYPE string.
    txt = str2html( str ).
    CONCATENATE lv_buffer txt INTO lv_buffer.
  ENDMETHOD.                    "add_string


  METHOD add_string_raw.
    CONCATENATE lv_buffer str INTO lv_buffer.
  ENDMETHOD.                    "add_string_raw


  METHOD flush_buffer.
    IF NOT lv_buffer IS INITIAL.
      APPEND lv_buffer TO gt_content.
      CLEAR: lv_buffer.
    ENDIF.
  ENDMETHOD.                    "flush_buffer


  METHOD add_header1.
    CALL METHOD add_tag
      EXPORTING
        tag = 'h1'
        str = str.
  ENDMETHOD.                    "append_header1


  METHOD add_header2.
    CALL METHOD add_tag
      EXPORTING
        tag = 'h2'
        str = str.
  ENDMETHOD.                    "append_header2


  METHOD add_header3.
    CALL METHOD add_tag
      EXPORTING
        tag = 'h3'
        str = str.
  ENDMETHOD.                    "append_header3


  METHOD add_header4.
    CALL METHOD add_tag
      EXPORTING
        tag = 'h4'
        str = str.
  ENDMETHOD.                    "add_header4


  METHOD add_header5.
    CALL METHOD add_tag
      EXPORTING
        tag = 'h5'
        str = str.
  ENDMETHOD.                    "add_header5


  METHOD add_header6.
    CALL METHOD add_tag
      EXPORTING
        tag = 'h6'
        str = str.
  ENDMETHOD.                    "add_header6


  METHOD add_paragraph.
    CALL METHOD add_tag
      EXPORTING
        tag = 'p'
        str = str.
  ENDMETHOD.                    "append_paragraph


  METHOD add_line_break.
    CALL METHOD add_string_raw( '<br>' ).
  ENDMETHOD.                    "append_line_break


  METHOD add_blank_line.
    CALL METHOD add_string_raw( '<p><br></p>' ).
  ENDMETHOD.


  METHOD str_a_href.
    e_str = str2html( i_text ).
    CONCATENATE '<a href="#' i_label '">' e_str '</a>' INTO e_str.
  ENDMETHOD.                    "str_a_href


  METHOD str_a_name.
    e_str = str2html( i_text ).
    CONCATENATE '<a name="' i_label '">' e_str '</a>' INTO e_str.
  ENDMETHOD.                    "str_a_name


  METHOD add_a_href.
    DATA: str TYPE string.
    str = str2html( i_text ).
    CONCATENATE '<a href="#' i_label '">' str '</a>' INTO str.
    CALL METHOD add_string_raw( str ).
  ENDMETHOD.                    "add_a_href


  METHOD add_a_name.
    DATA: str TYPE string.
    str = str2html( i_text ).
    CONCATENATE '<a name="' i_label '">' str '</a>' INTO str.
    CALL METHOD add_string_raw( str ).
  ENDMETHOD.                    "add_a_name


  METHOD start_document.

    DATA: l_str TYPE string.

    CALL METHOD add_string_raw( '<html>' ).
    CALL METHOD flush_buffer.
    CALL METHOD add_string_raw( '<head>' ).
    CALL METHOD flush_buffer.

    CONCATENATE '<META CONTENT="text/html; charset=' i_code_page '">'
                INTO l_str.
    CALL METHOD add_string_raw( l_str ).
    CALL METHOD flush_buffer.

    IF i_css_file_name IS NOT INITIAL.
      CONCATENATE '<link rel="Stylesheet" type="text/css" href="'
                  i_css_file_name '"></link>'  INTO l_str.
      CALL METHOD add_string_raw( l_str ).
      CALL METHOD flush_buffer.
    ENDIF.

    IF i_comment IS NOT INITIAL.
      CALL METHOD add_string_raw( i_comment ).
      CALL METHOD flush_buffer.
    ENDIF.

    CALL METHOD add_tag
      EXPORTING
        tag = 'title'
        str = i_title.
    CALL METHOD add_string_raw( '</head>' ).
    CALL METHOD flush_buffer.
    CALL METHOD add_string_raw( '<body>' ).
    CALL METHOD flush_buffer.

  ENDMETHOD.                    "start_document


  METHOD end_document.
    CALL METHOD add_string_raw( '</body>' ).
    CALL METHOD flush_buffer.
    CALL METHOD add_string_raw( '</html>' ).
    CALL METHOD flush_buffer.
  ENDMETHOD.                    "end_document


  METHOD write_file.

    CALL METHOD flush_buffer.

    CALL FUNCTION 'GUI_DOWNLOAD'
      EXPORTING
        filename                = file_name
      TABLES
        data_tab                = gt_content
      EXCEPTIONS
        file_write_error        = 1
        no_batch                = 2
        gui_refuse_filetransfer = 3
        invalid_type            = 4
        no_authority            = 5
        unknown_error           = 6
        header_not_allowed      = 7
        separator_not_allowed   = 8
        filesize_not_allowed    = 9
        header_too_long         = 10
        dp_error_create         = 11
        dp_error_send           = 12
        dp_error_write          = 13
        unknown_dp_error        = 14
        access_denied           = 15
        dp_out_of_memory        = 16
        disk_full               = 17
        dp_timeout              = 18
        file_not_found          = 19
        dataprovider_exception  = 20
        control_flush_error     = 21
        OTHERS                  = 22.

    ret_code = sy-subrc.

  ENDMETHOD.                    "write_file

ENDCLASS.                    "zcl_ic_html IMPLEMENTATION
Back to top
View user's profile Send private message
admin
Администратор
Администратор



Joined: 01 Sep 2007
Posts: 1639

PostPosted: Fri Nov 28, 2008 2:13 am    Post subject: Reply with quote

Code:
   
*&---------------------------------------------------------------------*
*&  Include      ZICDOC_CL_CODE_ANALYSIS
*&---------------------------------------------------------------------*
* @Author Ireneusz Cwir
* @Date   June 2006
* @Info
* Definiotion and implementation of class CL_IC_CODE_ANALYSIS handling
* ABAP sorce code scan and analysis. Results of analysis are placed in
* several public tables. Class does not writes results of analysis
* to any devices - it must be done bu user of the class.


* Types defined to be used in the class and other programs.
* They are used to declare tables with results of analysis.

* Comment tag. Represents segment or section of code comments.
* Each segment starts with tag name: @NAME.
* If no tag is placed in the beginning of comment, INFO is used
* by default.
* All following lines of comment are concatenated into one string.
* Blank line can be used to finish comment (or any ABAP statemnt).
* To place line break, you can use HTML commands (like <br>).
* Comments:
* - Program level comment - starts with: *&. They are added in the
*   beginning of include and by pretty-printer for forms.<br>
* - Function parameters - starts with: *" <br>
* - Other comments - start with *. <br>
* - Comments starting with " are ignored <br>
* - Obligatory to put SPACE after above chars <br>
* - Between program comment and following form comment there should be
*   one blank line placed
* - Predefined comment variables (tags) start with: @ <br>
* - Comments can contain HTML formating commands <br>

* Comment section - starting with special tag (like @Author or @Info).
TYPES: BEGIN OF ts_commtag,
         tag(30) TYPE c,    " tag name (e.c. INFO, AUTHOR)
         param(50) TYPE c,       " optional parameter
         text TYPE string,       " text of comment
       END OF ts_commtag.
TYPES: tt_commtag TYPE STANDARD TABLE OF ts_commtag
             WITH DEFAULT KEY.

* Comment. Represents continuous part of code comments. It can consist
* of several tags (segments, sections).
TYPES: BEGIN OF ts_comment,
     tags TYPE tt_commtag,
   END OF ts_comment.


* Structure describing individual parameter of method, form, class
* declaration, etc. In the current version it is not implemented yet,
* so it contains just one dummy field. In the future, it can contain
* field for parameter name, type, import/export, etc.
TYPES: BEGIN OF ts_param_detail,
     dummy TYPE c,
   END OF ts_param_detail.
TYPES: tt_param_details TYPE STANDARD TABLE OF ts_param_detail
              WITH DEFAULT KEY.

* Structure describing all parameters of single method, form, etc.
* At the moment, TEXT field containing the whole declaration. In the
* future, declaration cab further analyzed and split into individual
* parameters (name, type, etc.).
TYPES: BEGIN OF ts_parameters,
     text    TYPE string,
     params  TYPE tt_param_details,
   END OF ts_parameters.


* Hierarchy of programs and includes (based on LEVELS returned by SCAN).
* For macros (DEFINE...) a special prog type is used ('9')
TYPES: BEGIN OF ts_program,
     program TYPE programm,    " Prog (include) name
     subc    TYPE subc,   " Prog types (1=executable, ...)
     title   TYPE repti,       " Report title
     depth   TYPE level_dpth,  " Nesting depth of code unit
     level   TYPE level_levl,  " Index of superior code unit
     comment TYPE ts_comment,  " Comment for program
   END OF ts_program.


* Class/Interface parameters
* This structure is filled-up from class/interface definition.
TYPES: BEGIN OF ts_class,
     clsname TYPE seoclsname,    " Class/intf name
     clstype TYPE seoclstype,    " 0-class, 1-interface
     program TYPE programm,      " Program, Include name
     super   TYPE seoclsname,    " Class/intf name of superclass
     param   TYPE ts_parameters, " Parameters
     comment TYPE ts_comment,    " Comment for class
   END OF ts_class.

* Components of class/interface
* Components types:
*       I  - interface
*       T  - type
*       C  - constant
*       A  - aliases
*       D  - data
*       CD - class-data
*       M  - method
*       CM - class-method
*       E  - event
*       CE - class-event
TYPES: t_clscmptype(2) TYPE c.

* This structure is filled-up from class/interface definition. For
* methods, additional comments are also placed in code units (from
* method implementation).

TYPES: BEGIN OF ts_classcmp,
     clsname  TYPE seoclsname,   " Class/intf name
     clstype  TYPE seoclstype,   " 0-class, 1-interface
     exposure TYPE seoexpose,    " 0-private, 1-protected, 2-public
     cmpname  TYPE seocmpname,   " Component name
     cmptype  TYPE t_clscmptype, " Component type (see above)
     param    TYPE ts_parameters," Parameters
     comment  TYPE ts_comment,   " Comment for component
   END OF ts_classcmp.
TYPES: tt_classcmps TYPE STANDARD TABLE OF ts_classcmp.


* Type for code unit name. It must be long enough to store
* interface + ~ + method name
TYPES: t_unitname(70) TYPE c.

*   Types of code modularization units and calls
*   Types: F  - form
*     FM - function module
*     CF - customer function
*     B  - BADI
*     T  - transaction
*     E  - main event (GET, INITIALIZATION, START-OF-SELECTION...
*     CD - class definition
*     CI - class implementation
*     I  - interface definition
*     M  - method
*     S  - submit program
TYPES: t_unittype(2) TYPE c.

* Source code modularization units details. It contains information
* from implementation.

TYPES: BEGIN OF ts_modunit,
     name    TYPE t_unitname,   " Name of form, function, event,
     type    TYPE t_unittype,   " Type of unit - see above
     program TYPE programm,     " Program, Include name
     clsname TYPE seoclsname,   " class name (required for methods)
     param   TYPE ts_parameters," Parameters (as string)
     comment TYPE ts_comment,   " Comment for unit
       END OF ts_modunit.


* Hierarchy of code units calls
TYPES: BEGIN OF ts_unitshier,
     name1   TYPE t_unitname,  " Caller name (main)
     type1   TYPE t_unittype,  " Caller type (main)
     prog1   TYPE programm,    " Caller program (main)
     clsname1 TYPE seoclsname, " Caller class name
     name2   TYPE t_unitname,  " Callee name (sub)
     type2   TYPE t_unittype,  " Callee type (sub)
     depth   TYPE level_dpth,  " Nesting depth of call
       END OF ts_unitshier.


*   Database tables usage
*   Access modes: T - Tables statement
*       S - select (read)
*       U - Update
*       I - Insert
*       M - Modify (U lub I)
*       D - Delete
TYPES: t_dbaccmode TYPE c.

TYPES: BEGIN OF ts_dbtable,
     table   TYPE tabname,    " Table name
     mode    TYPE t_dbaccmode," Access mode - see above
     ddtext  TYPE as4text,    " Table description
     program TYPE programm,   " Program, Include
     clsname TYPE seoclsname, " class name (required for methods)
     name    TYPE t_unitname, " Function or form name (access)
     type    TYPE t_unittype, " Module type
       END OF ts_dbtable.
TYPES: tt_dbtables TYPE STANDARD TABLE OF ts_dbtable.


*----------------------------------------------------------------------*
*       CLASS zcl_ic_code_analysis DEFINITION
*----------------------------------------------------------------------*
* Class contains methods used for source code analysis. Results are
* stored in atributes (tables) and they are not output. It must be
* done by another program (for instance subclas).
*----------------------------------------------------------------------*


CLASS zcl_ic_code_analysis DEFINITION.

  PUBLIC SECTION.

*   Main (root) program name - program, from which analysis starts
    DATA: gv_main_program_name TYPE progname.

*   Results of detailed analysis. They can be read by user of class
*   and then displayed.
*   Table contains hierarchy of includes (starting from main program).
    DATA: gt_programs  TYPE STANDARD TABLE OF ts_program,
*   Table contains general information about classes and interfaces.
     gt_classes   TYPE STANDARD TABLE OF ts_class,
*   Table contains components (attributes, methods) of classes and
*   interfaces.
     gt_classcmps TYPE STANDARD TABLE OF ts_classcmp,
*   Table contains non-class code units (like forms, functions). As an
*   exception, it contains comments for method implementation.
     gt_modunits  TYPE STANDARD TABLE OF ts_modunit,
*   Table contains hierarchy of calls of code subunits (like calling
*   form from anther one).
     gt_unitshier TYPE STANDARD TABLE OF ts_unitshier,
*   Table contans information about database tables affected by
*   code units.
     gt_dbtables  TYPE STANDARD TABLE OF ts_dbtable.

    METHODS: constructor.
*   Resets (clears) all atributes of the object.
    METHODS: reset.

*   The main method which performs analysis of a program.
*   Program must be available in the system.
*   Results are stored in atribute tables (GT_XXX).
*   @IMPORTING I_PROGRAM - The name of program in the system to be
*         analyzed.
*   @RETURNING RET_CODE - Returns result of analysis: 0-OK, <>0-error
    METHODS: analyse_program IMPORTING i_program TYPE any
              RETURNING value(ret_code) TYPE i,
*   This method loads source code from the file and then performs
*   analysis. With this method it is not possible to analyse
*   nested includes.
*   @IMPORTING I_FILENAME - The name with a path of program on local
*         disk to loaded and analyzed.
*   @RETURNING RET_CODE - Returns result of analysis: 0-OK, <>0-error
        analyse_file    IMPORTING i_filename TYPE string
              RETURNING value(ret_code) TYPE i.

*   Returns description of code unit type ('Form' for 'F'...).
    METHODS: get_code_unit_type_desc IMPORTING i_type TYPE t_unittype
               RETURNING value(e_desc) TYPE string,
*   Returns desription of class component type ('Method' for 'M'...).
        get_class_cmp_type_desc IMPORTING i_type TYPE t_clscmptype
               RETURNING value(e_desc) TYPE string,
*   Returns description of class exposure type ('Public' for '2')
        get_class_cmp_exposure_desc IMPORTING i_exp TYPE seoexpose
               RETURNING value(e_desc) TYPE string,
*   Return description of database access mode ('Select' for 'S'...)
        get_db_access_mode_desc IMPORTING i_mode TYPE t_dbaccmode
               RETURNING value(e_desc) TYPE string.

    "   Helper funtions for testing
*   Displays results of SCAN ABAP-CODE (dumps contents of returned
*   tables). It helps understand results of built-in keyword.
*   You will find very useful information in online help for
*   keyword <code>SCAN ABAP-SOURCE<code>.
    METHODS: dump_tables_scan,
*   Displays individual statements and tokens with additional details.
*   It also help understand results of SCAN keyword.
        dump_statements_detailed,
*   Displays statements (and tokens building statements) as source code
*   lines. This is how ZICDOC sees source code after replacing
*   INCLUDE with content of that program, unpacking statemts with ':'
*   and other conversions.
        dump_statements.

  PROTECTED SECTION.

*   COMPATYBILITY!!!!!
*   For compatibility (SCAN keyword parameters changed in WAS)
    TYPES: ts_token TYPE stokesx.           " in >= WAS 6.10
*    TYPES: begin of ts_token,         " in R/3 4.6C
*         str type string,
*         row type TOKEN_ROW,
*         OFF2 type TOKEN_OFF2,
*         OFF3 type TOKEN_OFF3,
*         COL type TOKEN_COL,
*         LEN1 type TOKEN_LEN1,
*         LEN2 type TOKEN_LEN2,
*         LEN3 type TOKEN_LEN3,
*         TYPE type TOKEN_TYPE,
*       end of ts_token.


*   Source code of a program
    TYPES: BEGIN OF ts_srccode,
         line(200) TYPE c,
       END OF ts_srccode.
    DATA: lt_srccode TYPE STANDARD TABLE OF ts_srccode.

*   Direct results of SCAN ABAP-SOURCE
    DATA: lt_tokens TYPE STANDARD TABLE OF ts_token,
*   Direct results of SCAN ABAP-SOURCE
     lt_statements TYPE STANDARD TABLE OF sstmnt ,
*   Direct results of SCAN ABAP-SOURCE
     lt_levels TYPE STANDARD TABLE OF slevel .

  PRIVATE SECTION.

*   Hierarchy of calls before further reworking.
    DATA: lt_uhier TYPE STANDARD TABLE OF ts_unitshier.

*   Current program, class and module unit during analysis
    DATA: ls_cur_prog     TYPE slevel,
     ls_cur_class    TYPE ts_class,
     ls_cur_unit     TYPE ts_modunit.
*   The last read comment. It can be assigne to the next ABAP statement.
    DATA: ls_last_comment TYPE ts_comment.

*   Current statement and token during analysis
    DATA: lv_cur_token_idx TYPE i,
     lv_cur_stmnt_idx TYPE i.
    DATA: ls_cur_stmnt TYPE sstmnt,
     ls_cur_token TYPE ts_token.

*   Performs analysis of source code loaded into private table. It is
*   used by the main function of the class.
    METHODS: do_analysis RETURNING value(ret_code) TYPE i.

    "   Analysis of specific statements groups
    METHODS: do_events,
        do_databases,
        do_code_units,
        do_classes,
        do_class_components,
        do_comments,
        do_others.

*   Reads the following tokens (starting from the next) and places
*   them into parametr structure.
    METHODS: do_parameters EXPORTING es_param TYPE ts_parameters.

*   Fills-up current program nad module unit during analysis
    METHODS: set_cur_prog,
        set_cur_class IMPORTING i_clsname TYPE seoclsname
                 i_clstype TYPE seoclstype
                 i_super   TYPE seoclsname
                 is_param  TYPE ts_parameters,
        set_cur_unit IMPORTING i_name    TYPE t_unitname
                i_type    TYPE t_unittype
                is_param  TYPE ts_parameters.
*   Appends current module unit to attribute table.
    METHODS: append_cur_unit,
        append_cur_class,
        append_class_cmp IMPORTING is_clscmp TYPE ts_classcmp,
        append_sub_unit IMPORTING i_name TYPE t_unitname
                   i_type TYPE t_unittype,
        append_dbtable IMPORTING i_table TYPE tabname
                  i_mode TYPE c,
        append_cur_prog_comment,
        append_cur_class_comment,
        append_cur_unit_comment,
        append_comment.

    METHODS: levels_to_programms,
        rework_units_hier,
        do_hier_path IMPORTING is_start TYPE ts_unitshier.

    METHODS: get_first_statement EXPORTING  es_stmnt TYPE sstmnt,
        get_next_statement EXPORTING es_stmnt TYPE sstmnt,
        get_cur_statement EXPORTING es_stmnt TYPE sstmnt,
        get_first_token EXPORTING es_token TYPE ts_token,
        get_next_token EXPORTING es_token TYPE ts_token,
        get_cur_token EXPORTING es_token TYPE ts_token.

*   Compatybility!!!!
    METHODS: do_scan_code_46c RETURNING value(ret_code) TYPE i,
        do_scan_code_610 RETURNING value(ret_code) TYPE i.

ENDCLASS.          "zcl_ic_code_analysis DEFINITION


*----------------------------------------------------------------------*
*       CLASS zcl_ic_code_analysis IMPLEMENTATION
*----------------------------------------------------------------------*

CLASS zcl_ic_code_analysis IMPLEMENTATION.

* Clears all atributes. It is not necessary, but just to do anything.
  METHOD constructor.
    CALL METHOD reset.
  ENDMETHOD.          "constructor


* Resets (clears) all atributes of the object.
  METHOD reset.
    CLEAR: gv_main_program_name.
    CLEAR: lv_cur_stmnt_idx, lv_cur_token_idx.
    CLEAR: ls_cur_stmnt, ls_cur_token.
    CLEAR: ls_cur_prog, ls_cur_class, ls_cur_unit, ls_last_comment.
    FREE: lt_srccode, lt_tokens, lt_statements, lt_levels, lt_uhier.
    FREE: gt_programs, gt_modunits, gt_unitshier, gt_dbtables,
     gt_classes, gt_classcmps.
  ENDMETHOD.          "reset

*======================================================================

* Returns description of code unit type.

  METHOD get_code_unit_type_desc.

    CASE i_type.
      WHEN 'F'.
   e_desc = 'Form'.
      WHEN 'FM'.
   e_desc = 'Function module'.
      WHEN 'CF'.
   e_desc = 'Customer function'.
      WHEN 'B'.
   e_desc = 'BADi'.
      WHEN 'T'.
   e_desc = 'Transaction'.
      WHEN 'E'.
   e_desc = 'List event'.
      WHEN 'S'.
   e_desc = 'Submit program'.
      WHEN 'CD'.
   e_desc = 'Class definition'.
      WHEN 'CI'.
   e_desc = 'Class implementation'.
      WHEN 'I'.
   e_desc = 'Interface'.
      WHEN 'M'.
   e_desc = 'Method'.    " Must be the same as in the next method
    ENDCASE.

  ENDMETHOD.          "get_code_unit_type_desc


* Returns description of class component type.

  METHOD get_class_cmp_type_desc.

    CASE i_type.
      WHEN 'T'.
   e_desc = 'Type'.
      WHEN 'C'.
   e_desc = 'Constant'.
      WHEN 'I'.
   e_desc = 'Interface'.
      WHEN 'A'.
   e_desc = 'Alias'.
      WHEN 'D'.
   e_desc = 'Data'.
      WHEN 'CD'.
   e_desc = 'Class-data'.
      WHEN 'M'.
   e_desc = 'Method'.    " Must be the same as in the prev method
      WHEN 'CM'.
   e_desc = 'Class-method'.
      WHEN 'E'.
   e_desc = 'Event'.
      WHEN 'CE'.
   e_desc = 'Class-event'.
    ENDCASE.

  ENDMETHOD.          "get_class_cmp_type_desc


* Returns description of class component exposure.

  METHOD  get_class_cmp_exposure_desc.

    CASE i_exp.
      WHEN '0'.
   e_desc = 'Private'.
      WHEN '1'.
   e_desc = 'Protected'.
      WHEN '2'.
   e_desc = 'Public'.
    ENDCASE.

  ENDMETHOD.          "get_class_cmp_exposure_desc


* Returns description of database access mode.

  METHOD get_db_access_mode_desc.

    CASE i_mode.
      WHEN 'T'.
   e_desc = 'Table'.
      WHEN 'S'.
   e_desc = 'Select'.
      WHEN 'U'.
   e_desc = 'Update'.
      WHEN 'I'.
   e_desc = 'Insert'.
      WHEN 'M'.
   e_desc = 'Modify (U,I)'.
      WHEN 'D'.
   e_desc = 'Delete'.
    ENDCASE.

  ENDMETHOD.          "get_db_access_mode_desc


*======================================================================

* The main method used to analyse code of program stored in the system.

  METHOD analyse_program.

    CALL METHOD reset.

*   Read source code of the program into local table
    READ REPORT i_program INTO lt_srccode.
    ret_code = sy-subrc.
    CHECK ret_code = 0.

*   Store the main (starting) program name and analyse code.
    gv_main_program_name = i_program.
    CALL METHOD do_analysis
      RECEIVING
   ret_code = ret_code.

  ENDMETHOD.          "analyse_program


* The main method used to analyse code loaded from file on presentation
* server.

  METHOD analyse_file.

    CALL METHOD reset.

*   Load code from local file
    CALL FUNCTION 'GUI_UPLOAD'
      EXPORTING
   filename      = i_filename
   filetype      = 'ASC'
      TABLES
   data_tab      = lt_srccode
      EXCEPTIONS
   file_open_error    = 1
   file_read_error    = 2
   no_batch      = 3
   gui_refuse_filetransfer = 4
   invalid_type       = 5
   no_authority       = 6
   unknown_error      = 7
   bad_data_format    = 8
   header_not_allowed      = 9
   separator_not_allowed   = 10
   header_too_long    = 11
   unknown_dp_error   = 12
   access_denied      = 13
   dp_out_of_memory   = 14
   disk_full          = 15
   dp_timeout         = 16
   OTHERS        = 17.
    ret_code = sy-subrc.
    CHECK ret_code = 0.

*   Store the main (starting) program name and analyze code.
    gv_main_program_name = i_filename.
    TRANSLATE gv_main_program_name TO UPPER CASE.
    CALL METHOD do_analysis
      RECEIVING
   ret_code = ret_code.

  ENDMETHOD.          "analyse_file

*======================================================================

* Scans source code - to be used in version 4.6.
* Statement SCAN ABAP_SOURCE behaves in different way in system
* 4.6 and >= WAS 6.1. It uses other types of parameters.

  METHOD do_scan_code_46c.

    DATA: lt_tok TYPE STANDARD TABLE OF stokex,
     ls_tok TYPE stokex,
     ls_token TYPE ts_token,
     lv_over(65535) TYPE c.

*    COMPATYBILITY!!!!!
*    SCAN ABAP-SOURCE lt_srccode TOKENS INTO lt_tok
*            OVERFLOW INTO lv_over
*            STATEMENTS INTO lt_statements
*            WITH ANALYSIS
*            WITH INCLUDES LEVELS INTO lt_levels
*            WITH COMMENTS.
*    ret_code = sy-subrc.
**   Konwersja do formatu z 6.10 (STOKESX)
*    LOOP AT lt_tok INTO ls_tok.
*      MOVE-CORRESPONDING ls_tok TO ls_token.
*      IF ls_tok-ovfl <> space.
*   ls_token-str = lv_over+ls_tok-off1(ls_tok-len).
*      ENDIF.
*      APPEND ls_token TO lt_tokens.
*    ENDLOOP.

  ENDMETHOD.          "do_analyse_46C


* Scans source code - to be used in version WAS 6.1 and newer.

  METHOD do_scan_code_610.

*    COMPATYBILITY!!!!!
    SCAN ABAP-SOURCE lt_srccode TOKENS INTO lt_tokens
            STATEMENTS INTO lt_statements
            WITH ANALYSIS
            WITH INCLUDES LEVELS INTO lt_levels
            WITH COMMENTS.
    ret_code = sy-subrc.

  ENDMETHOD.          "do_analyse_610

*======================================================================

* The main method performing analysis of loaded source code.
* It scans source code and then converts returned tables into tables
* used later for documentation generation (global attributes).

  METHOD do_analysis.

    DATA: ls_stmnt TYPE sstmnt,
     ls_token TYPE ts_token.

*   Scan source code and fill tables of statements and tokens
    IF sy-saprl >= '610'.
      CALL METHOD do_scan_code_610
   RECEIVING
     ret_code = ret_code.
    ELSE.
      CALL METHOD do_scan_code_46c
   RECEIVING
     ret_code = ret_code.
    ENDIF.
    CHECK ret_code < 4.
    ret_code = 0.

*   Convert levels into GT_PROGRAMS
    CALL METHOD levels_to_programms.

*   Analyse statements of code one-by-one
    CALL METHOD get_first_statement
      IMPORTING
   es_stmnt = ls_stmnt.
    WHILE ls_stmnt-type <> space.

*     For comments - they recognized by statemnt type.
      IF ls_stmnt-type = 'P'.
   CALL METHOD do_comments.

*     For other keywords
      ELSE.

*       The first token of the current statement
   CALL METHOD get_first_token
     IMPORTING
       es_token = ls_token.

   CASE ls_token-str.
     WHEN 'START-OF-SELECTION' OR
          'END-OF-SELECTION'   OR
          'INITIALIZATION'     OR
          'GET'      OR
          'AT'.
       CALL METHOD do_events.

     WHEN 'TABLES' OR
          'SELECT' OR
          'UPDATE' OR
          'INSERT' OR
          'MODIFY' OR
          'DELETE'.
       CALL METHOD do_databases.

     WHEN 'FORM'    OR
          'ENDFORM'      OR
          'FUNCTION'     OR
          'ENDFUNCTION'  OR
          'METHOD'       OR
          'ENDMETHOD'    OR
          'PERFORM'      OR
          'CALL'    OR
          'SUBMIT'.
       CALL METHOD do_code_units.

     WHEN 'CLASS'      OR
          'ENDCLASS'   OR
          'INTERFACE'  OR
          'ENDINTERFACE'.
       CALL METHOD do_classes.

     WHEN OTHERS.
       CALL METHOD do_others.
   ENDCASE.
   CLEAR: ls_last_comment.
      ENDIF.

      CALL METHOD get_next_statement
   IMPORTING
     es_stmnt = ls_stmnt.
    ENDWHILE.

*   Convert code units calls hierarchy to more suitable for further
*   processing
    CALL METHOD rework_units_hier.

  ENDMETHOD.          "do_analysis


* Performs analysis of statements representing list events

  METHOD do_events.

    DATA: ls_token  TYPE ts_token,
     ls_param  TYPE ts_parameters.
    DATA: l_name    TYPE t_unitname.

    CALL METHOD get_cur_token
      IMPORTING
   es_token = ls_token.
    l_name = ls_token-str.

*   For AT, we use two tokens to build name
    IF ls_token-str = 'AT'.
      CALL METHOD get_next_token
   IMPORTING
     es_token = ls_token.
      CONCATENATE l_name ls_token-str INTO l_name SEPARATED BY space.
    ENDIF.

*   The rest of tokens builds parameter
    CALL METHOD do_parameters
      IMPORTING
   es_param = ls_param.

    CALL METHOD set_cur_unit
      EXPORTING
   i_name   = l_name
   i_type   = 'E'
   is_param = ls_param.
    CALL METHOD append_cur_unit.

  ENDMETHOD.          "do_events


* Performs analysis of statement representing definition and
* implementation of several types of code units and calls.

  METHOD do_code_units.

    DATA: ls_cmp  TYPE ts_classcmp.
    DATA: ls_token TYPE ts_token,
     ls_param TYPE ts_parameters.
    DATA: l_name  TYPE t_unitname,
     l_type  TYPE t_unittype.

    CALL METHOD get_cur_token
      IMPORTING
   es_token = ls_token.

    CASE ls_token-str.

      WHEN 'FORM'.
*       Form name
   CALL METHOD get_next_token
     IMPORTING
       es_token = ls_token.
   l_name = ls_token-str.
*       Form parameters
   CALL METHOD do_parameters
     IMPORTING
       es_param = ls_param.
   CALL METHOD set_cur_unit
     EXPORTING
       i_name   = l_name
       i_type   = 'F'
       is_param = ls_param.
   CALL METHOD append_cur_unit.

      WHEN 'FUNCTION' OR
      'METHOD'.
   l_type = 'FM'.
   IF ls_token-str = 'METHOD'.
     l_type = 'M'.
   ENDIF.
*       Name
   CALL METHOD get_next_token
     IMPORTING
       es_token = ls_token.
   l_name = ls_token-str.
   CALL METHOD set_cur_unit
     EXPORTING
       i_name   = l_name
       i_type   = l_type
       is_param = ls_param.
   CALL METHOD append_cur_unit.
*       In case of interface method implementation, it is not added to
*       class components from class definition. We must do there.
*       We can call function for all methods (not only interfaces).
   IF l_type = 'M'.
     ls_cmp-cmpname  = l_name.
     ls_cmp-cmptype  = l_type.
     ls_cmp-clsname  = ls_cur_class-clsname..
     ls_cmp-clstype  = '0'.
     ls_cmp-exposure = '2'.
     CALL METHOD append_class_cmp
       EXPORTING
         is_clscmp = ls_cmp.
   ENDIF.

      WHEN 'ENDFORM'      OR
      'ENDMETHOD'    OR
      'ENDFUNCTION'.
   CLEAR: ls_cur_unit.

      WHEN 'PERFORM'  OR
      'SUBMIT'.
   l_type = 'F'.
   IF ls_token-str = 'SUBMIT'.
     l_type = 'S'.
   ENDIF.
*       Name
   CALL METHOD get_next_token
     IMPORTING
       es_token = ls_token.
   l_name = ls_token-str.
   CALL METHOD append_sub_unit
     EXPORTING
       i_name = l_name
       i_type = l_type.

      WHEN 'CALL'.
   CALL METHOD get_next_token
     IMPORTING
       es_token = ls_token.
*       Check the secont part of call
   CASE ls_token-str.
     WHEN 'FUNCTION'.
       l_type = 'FM'.
     WHEN 'CUSTOMER-FUNCTION'.
       l_type = 'CF'.
     WHEN 'BADI'.
       l_type = 'B'.
     WHEN 'METHOD'.
       l_type = 'M'.
     WHEN 'TRANSATION'.
       l_type = 'T'.
   ENDCASE.
   IF l_type <> space.
     CALL METHOD get_next_token
       IMPORTING
         es_token = ls_token.
     l_name = ls_token-str.
     CALL METHOD append_sub_unit
       EXPORTING
         i_name = l_name
         i_type = l_type.
   ENDIF.
    ENDCASE.

  ENDMETHOD.          "do_calls


* Performs analysis of statement representing definition and
* implementation of classes.

  METHOD do_classes.

    DATA: ls_token  TYPE ts_token,
     ls_param  TYPE ts_parameters.
    DATA: l_name    TYPE t_unitname,
     l_clsname TYPE seoclsname,
     l_super   TYPE seoclsname,
     l_type    TYPE t_unittype,
     l_clstype TYPE seoclstype.

    CALL METHOD get_cur_token
      IMPORTING
   es_token = ls_token.

    CASE ls_token-str.

      WHEN 'CLASS'  OR
      'INTERFACE'.
   l_clstype = '0'.      " class
   IF ls_token-str = 'INTERFACE'.
     l_clstype = '1'.         " interface
     l_type = 'I'.
   ENDIF.

*       Get class name
   CALL METHOD get_next_token
     IMPORTING
       es_token = ls_token.
   l_clsname = ls_token-str.

*       Get parameters for analysing special parameters of class.
*       They are not stored in dedicated components - it will be done
*       in the second run.
   WHILE ls_token-str <> space.
     CALL METHOD get_next_token
       IMPORTING
         es_token = ls_token.
     CASE ls_token-str.
*      Skip these types of declartions
       WHEN 'DEFERRED'  OR
       'LOAD'.
         RETURN.
       WHEN 'DEFINITION'.
         l_type = 'CD'.
       WHEN 'IMPLEMENTATION'.
         l_type = 'CI'.
       WHEN 'FROM'.
         CALL METHOD get_next_token
      IMPORTING
        es_token = ls_token.
         l_super = ls_token-str.
     ENDCASE.
   ENDWHILE.

*       The second run for filling standard component
*       First, we must skip starting keywords
   CALL METHOD get_first_token
     IMPORTING
       es_token = ls_token.
   DO 2 TIMES.
     CALL METHOD get_next_token
       IMPORTING
         es_token = ls_token.
   ENDDO.

   CALL METHOD do_parameters
     IMPORTING
       es_param = ls_param.

*       set_cur_class must be called before set_cur_unit
   CALL METHOD set_cur_class
     EXPORTING
       i_clsname = l_clsname
       i_clstype = l_clstype
       i_super   = l_super
       is_param  = ls_param.
   l_name = l_clsname.
   CALL METHOD set_cur_unit
     EXPORTING
       i_name   = l_name
       i_type   = l_type
       is_param = ls_param.

   CALL METHOD append_cur_unit.

*       For interface and class definition
   IF l_type = 'I'  OR  l_type = 'CD'.
     CALL METHOD append_cur_class.
*    Analyse components of class/interface
     CALL METHOD do_class_components.
     CLEAR: ls_cur_unit,
       ls_cur_class.
   ENDIF.

      WHEN 'ENDCLASS'  OR
      'ENDINTERFACE'.
   CLEAR: ls_cur_unit,
          ls_cur_class.

    ENDCASE.

  ENDMETHOD.          "do_classes


* Performs analysis of class definition - stores components.

  METHOD do_class_components.

    DATA: ls_stmnt TYPE sstmnt,
     ls_token TYPE ts_token.
    DATA: ls_cmp   TYPE ts_classcmp.

*   Set default values
    ls_cmp-exposure = 2.        " Public

*   Method is called from CLASS / INTERFACE statement, so need the next
    CALL METHOD get_next_statement
      IMPORTING
   es_stmnt = ls_stmnt.
    WHILE ls_stmnt-type <> space.

*     Clear selected fields
      CLEAR: ls_cmp-cmpname, ls_cmp-cmptype, ls_cmp-param.

*     We must handle comments
      IF ls_stmnt-type = 'P'.
   CALL METHOD do_comments.

      ELSE.

*       The first token of the current statement
   CALL METHOD get_first_token
     IMPORTING
       es_token = ls_token.

   CASE ls_token-str.

     WHEN 'ENDCLASS'  OR
          'ENDINTERFACE'.
       EXIT.

     WHEN 'PUBLIC'.
       ls_cmp-exposure = '2'.
     WHEN 'PROTECTED'.
       ls_cmp-exposure = '1'.
     WHEN 'PRIVATE'.
       ls_cmp-exposure = '0'.

     WHEN 'TYPES'.
       ls_cmp-cmptype = 'T'.
     WHEN 'CONSTANTS'.
       ls_cmp-cmptype = 'C'.
     WHEN 'INTERFACES'.
       ls_cmp-cmptype = 'I'.
     WHEN 'ALIASES'.
       ls_cmp-cmptype = 'A'.
     WHEN 'DATA'.
       ls_cmp-cmptype = 'D'.
     WHEN 'CLASS-DATA'.
       ls_cmp-cmptype = 'CD'.
     WHEN 'METHODS'.
       ls_cmp-cmptype = 'M'.
     WHEN 'CLASS-METHODS'.
       ls_cmp-cmptype = 'CM'.
     WHEN 'EVENTS'.
       ls_cmp-cmptype = 'E'.
     WHEN 'CLASS-EVENTS'.
       ls_cmp-cmptype = 'CE'.

   ENDCASE.

*       If CLSTYPE set, then we have component
   IF ls_cmp-cmptype IS NOT INITIAL.

*    The next token contains name
     CALL METHOD get_next_token
       IMPORTING
         es_token = ls_token.
     ls_cmp-cmpname = ls_token-str.

*    The rest contains parameters
     CALL METHOD do_parameters
       IMPORTING
         es_param = ls_cmp-param.

*    Add component to the table
     CALL METHOD append_class_cmp
       EXPORTING
         is_clscmp = ls_cmp.

   ENDIF.
      ENDIF.

*   Get the next statement
      CALL METHOD get_next_statement
   IMPORTING
     es_stmnt = ls_stmnt.

    ENDWHILE.

  ENDMETHOD.          "do_class_components


* Performs analysis of statement representing access to database table.

  METHOD do_databases.

    DATA: ls_token TYPE ts_token.
    DATA: l_table TYPE tabname,
     l_mode  TYPE c.

    CALL METHOD get_cur_token
      IMPORTING
   es_token = ls_token.

    CASE ls_token-str.

      WHEN 'TABLES' OR 'UPDATE' OR 'MODIFY'.
   l_mode = ls_token-str(1).
   CALL METHOD get_next_token
     IMPORTING
       es_token = ls_token.
   l_table = ls_token-str.
   CALL METHOD append_dbtable
     EXPORTING
       i_table = l_table
       i_mode  = l_mode.

      WHEN 'SELECT'.
   WHILE ls_token-str <> 'FROM'  AND  ls_token-str <> space.
     CALL METHOD get_next_token
       IMPORTING
         es_token = ls_token.
   ENDWHILE.
   IF ls_token-str = 'FROM'.
     CALL METHOD get_next_token
       IMPORTING
         es_token = ls_token.
     l_table = ls_token-str.
     CALL METHOD append_dbtable
       EXPORTING
         i_table = l_table
         i_mode  = 'S'.
   ENDIF.
   DO 1000 TIMES.
     WHILE ls_token-str <> 'JOIN'  AND  ls_token-str <> space.
       CALL METHOD get_next_token
         IMPORTING
      es_token = ls_token.
     ENDWHILE.
     IF ls_token-str = 'JOIN'.
       CALL METHOD get_next_token
         IMPORTING
      es_token = ls_token.
       l_table = ls_token-str.
       CALL METHOD append_dbtable
         EXPORTING
      i_table = l_table
      i_mode  = 'S'.
     ELSE.
       EXIT.
     ENDIF.
   ENDDO.

      WHEN 'INSERT'.
   CALL METHOD get_next_token
     IMPORTING
       es_token = ls_token.
   IF ls_token-str = 'INTO'.
     CALL METHOD get_next_token
       IMPORTING
         es_token = ls_token.
   ENDIF.
   l_table = ls_token-str.
   CALL METHOD append_dbtable
     EXPORTING
       i_table = l_table
       i_mode  = 'I'.

      WHEN 'DELETE'.
   CALL METHOD get_next_token
     IMPORTING
       es_token = ls_token.
   IF ls_token-str = 'FROM'.
     CALL METHOD get_next_token
       IMPORTING
         es_token = ls_token.
   ENDIF.
   l_table = ls_token-str.
   CALL METHOD append_dbtable
     EXPORTING
       i_table = l_table
       i_mode  = 'D'.
    ENDCASE.

  ENDMETHOD.          "do_databases


* Performs analysis of continuous code section of comments. If we
* enter several lines of comments, even with balnk lines inside,
* SCAN returns them as one statemnt (each line will be separate token).
* Results are placed in structure and can be used by by other methods.
* Typically, coments are placed BEFORE code we are interested in.
* Comment is stored in LS_LAST_COMMENT atribute.

  METHOD do_comments.

    DATA: ls_token  TYPE ts_token,
     ls_tag    TYPE ts_commtag.
    DATA: l_str     TYPE string,
     l_buf     TYPE string.
    DATA: l_comm_type TYPE c,
     l_char      TYPE c.
    DATA: l_last_row  TYPE i,
     l_len       TYPE i,
     l_offs      TYPE i.

    CLEAR: ls_last_comment.
    CALL METHOD get_first_token
      IMPORTING
   es_token = ls_token.
    l_last_row = ls_token-row.

*   Analyse all lines of comment
    WHILE ls_token-str <> space.

      l_len = STRLEN( ls_token-str ).

*     Process only comments starting with '*' or " in the first column
      IF l_len >= 1  AND  ls_token-str(1) = '"'  AND  ls_token-col > 0.
   CALL METHOD get_next_token
     IMPORTING
       es_token = ls_token.
   CONTINUE.
      ENDIF.

*     Set comment type (program, function or other). It is called for
*     the first line of the comment (also after blank line).
      IF l_comm_type = space.
   IF l_len >= 2  AND  ls_token-str(2) = '*&'.
     l_comm_type = 'P'.      " like program beginning
   ELSEIF l_len >= 2  AND  ls_token-str(2) = '*"'.
     l_comm_type = 'F'.      " like function parameters
   ELSE.
     l_comm_type = 'O'.      " other comments
   ENDIF.
      ENDIF.

*     Check if blank lines appeares between lines of comment. Blank line
*     ends the current part of comment.
      l_offs = ls_token-row - l_last_row.
      l_last_row = ls_token-row.
      IF l_offs > 1.
   IF l_comm_type = 'P'  OR  l_comm_type = 'F'.
     IF ls_tag-text <> space.
       APPEND ls_tag TO ls_last_comment-tags.
     ENDIF.
     CALL METHOD append_comment.
   ENDIF.
*       Starting next paragraph
   CLEAR: ls_tag.
   CLEAR: l_comm_type.
   CONTINUE.
      ENDIF.

*     Ommit semi-lines (strings of the same characters)
      l_len = STRLEN( ls_token-str ).
      IF l_len >= 6  AND  ls_token-str+3(1) = ls_token-str+4(1)  AND
           ls_token-str+3(1) = ls_token-str+5(1).
   l_char = ls_token-str+3(1).
   IF l_char  <> space.
     IF ls_tag-text <> space.
       APPEND ls_tag TO ls_last_comment-tags.
     ENDIF.
     CLEAR: ls_tag.
     CALL METHOD get_next_token
       IMPORTING
         es_token = ls_token.
     CONTINUE.
   ENDIF.
      ENDIF.

*     Remove beginning markers
      l_len = STRLEN( ls_token-str ).
      l_offs = 0.
      WHILE l_offs < l_len  AND  ls_token-str+l_offs(1) CA '*"& '.
   l_offs = l_offs + 1.
      ENDWHILE.
      l_str = ls_token-str+l_offs.

*     Special tags in comments (starting with '@')
      l_len = STRLEN( l_str ).
      IF l_len > 0.
   IF l_str(1) = '@'.
     IF ls_tag-text <> space.
       APPEND ls_tag TO ls_last_comment-tags.
     ENDIF.
     CLEAR: ls_tag.
     SPLIT l_str+1 AT space INTO ls_tag-tag l_buf.
     TRANSLATE ls_tag-tag TO UPPER CASE.
*    Tags with parameters
     IF ls_tag-tag = 'PARAM'  OR ls_tag-tag = 'TABLES'    OR
        ls_tag-tag = 'USING'  OR
        ls_tag-tag = 'IMPORT' OR ls_tag-tag = 'IMPORTING' OR
        ls_tag-tag = 'EXPORT' OR ls_tag-tag = 'EXPORTING' OR
        ls_tag-tag = 'CHANGE' OR ls_tag-tag = 'CHANGING'  OR
        ls_tag-tag = 'RETURN' OR ls_tag-tag = 'RETURNING' OR
        ls_tag-tag = 'RECEIVING'  OR
        ls_tag-tag = 'EXCEPTION'  OR ls_tag-tag = 'THROWS' OR
        ls_tag-tag = 'RAISING'.
       CLEAR: l_buf.
       SPLIT l_str+1 AT space INTO ls_tag-tag ls_tag-param l_buf.
       TRANSLATE ls_tag-tag TO UPPER CASE.
     ENDIF.
     ls_tag-text = l_buf.
   ELSE.
     CONCATENATE ls_tag-text l_str INTO ls_tag-text
               SEPARATED BY space.
     SHIFT ls_tag-text LEFT DELETING LEADING space.
     IF ls_tag-tag = space.
       ls_tag-tag = 'INFO'.
     ENDIF.
   ENDIF.
      ENDIF.

      CALL METHOD get_next_token
   IMPORTING
     es_token = ls_token.

    ENDWHILE.

    IF ls_tag-text <> space.
      APPEND ls_tag TO ls_last_comment-tags.
    ENDIF.
    IF l_comm_type = 'P'  OR  l_comm_type = 'F'.
      CALL METHOD append_comment.
    ENDIF.

  ENDMETHOD.          "do_comments


* Performs analysis of other statements.

  METHOD do_others.
  ENDMETHOD.          "do_others


* Reads token from current statemnt (starting from the next)
* and creates parameter structure.

  METHOD do_parameters.

    DATA: ls_token  TYPE ts_token.
    DATA: ls_detail TYPE ts_param_detail.

    CALL METHOD get_next_token
      IMPORTING
   es_token = ls_token.

    WHILE ls_token-str <> space.

      CONCATENATE es_param-text ls_token-str INTO es_param-text
                     SEPARATED BY space.

      CALL METHOD get_next_token
   IMPORTING
     es_token = ls_token.

    ENDWHILE.

    SHIFT es_param-text LEFT DELETING LEADING space.

*    SHIFT ls_detail-text LEFT DELETING LEADING space.
*    IF ls_detail IS NOT INITIAL.
*      APPEND ls_detail TO es_param-params.
*    ENDIF.

  ENDMETHOD.          "do_parameters


* Sets the program name of current statement. Called when
* the following statementr is taken for analysis.

  METHOD set_cur_prog.

    DATA: ls_level TYPE slevel.
    DATA: l_name TYPE programm.

    l_name = ls_cur_prog-name.
    CLEAR: ls_cur_prog.
    LOOP AT lt_levels INTO ls_level.
      IF lv_cur_stmnt_idx >= ls_level-from  AND
    lv_cur_stmnt_idx <= ls_level-to.
   ls_cur_prog = ls_level.
   IF ls_level-level = 0.
     ls_cur_prog-name = gv_main_program_name.
   ENDIF.
      ENDIF.
    ENDLOOP.
    IF ls_cur_prog-name <> l_name.
      CLEAR: ls_last_comment.
    ENDIF.

  ENDMETHOD.          "set_cur_prog_name


* Sets the name and parameters of class/interf definition/implement.
* Called in the beginning of class definiotion/implement (CLASS, ITER..)

  METHOD set_cur_class.

    CLEAR: ls_cur_class.
    ls_cur_class-clsname = i_clsname.
    ls_cur_class-clstype = i_clstype.
    ls_cur_class-super   = i_super.
    ls_cur_class-param   = is_param.
    ls_cur_class-program = ls_cur_prog-name.
    ls_cur_class-comment = ls_last_comment.
    CLEAR: ls_last_comment.

  ENDMETHOD.          "set_cur_class


* Sets the name and parameters of code unit of current statement.
* Called in the beginning of unit code definiotion (FORM, CLASS, ..., ).

  METHOD set_cur_unit.

    CLEAR: ls_cur_unit.
    ls_cur_unit-name = i_name.
    ls_cur_unit-type = i_type.
    ls_cur_unit-param = is_param.
    ls_cur_unit-program = ls_cur_prog-name.
    ls_cur_unit-clsname = ls_cur_class-clsname.
    ls_cur_unit-comment = ls_last_comment.
    CLEAR: ls_last_comment.

  ENDMETHOD.          "set_cur_unit


* Appends parameters (declaration) of current class to results table

  METHOD append_cur_class.

    CHECK ls_cur_class-clsname IS NOT INITIAL.
    APPEND ls_cur_class TO gt_classes.

  ENDMETHOD.          "append_cur_func


* Append class component to result table.

  METHOD append_class_cmp.

    DATA: ls_cmp TYPE ts_classcmp.
    DATA: l_tabix TYPE syst-tabix.

    CHECK is_clscmp-cmpname IS NOT INITIAL.

*   Check if table already contains component. It can be called twice:
*   for definition and implementation. For the first time we populate
*   more fields than for the second.
    READ TABLE gt_classcmps INTO ls_cmp
         WITH KEY clsname = ls_cur_class-clsname
             clstype = ls_cur_class-clstype
             cmpname = is_clscmp-cmpname.
*   If already exists - update comment only
    IF sy-subrc = 0.
      l_tabix = sy-tabix.
      APPEND  LINES OF ls_last_comment-tags TO ls_cmp-comment-tags.
      MODIFY gt_classcmps INDEX l_tabix FROM ls_cmp
       TRANSPORTING comment.
*   Append new component
    ELSE.
      ls_cmp = is_clscmp.
      ls_cmp-clsname = ls_cur_class-clsname.
      ls_cmp-clstype = ls_cur_class-clstype.
      ls_cmp-comment = ls_last_comment.
      APPEND ls_cmp TO gt_classcmps.
    ENDIF.
    CLEAR: ls_last_comment.

  ENDMETHOD.          "append_class_cmp


* Appends parameters of current code unit to results table.

  METHOD append_cur_unit.

    CHECK ls_cur_unit-name IS NOT INITIAL.
    APPEND ls_cur_unit TO gt_modunits.

  ENDMETHOD.          "append_cur_unit

* Appends information about sub code unit called from current unit
* Called from PERFORM..., CALL... etc.

  METHOD append_sub_unit.

    DATA: ls_unitshier TYPE ts_unitshier.
    ls_unitshier-name1    = ls_cur_unit-name.
    ls_unitshier-type1    = ls_cur_unit-type.
    ls_unitshier-prog1    = ls_cur_unit-program.
    ls_unitshier-clsname1 = ls_cur_class-clsname.
    ls_unitshier-name2    = i_name.
    ls_unitshier-type2    = i_type.
    CHECK ls_unitshier-name1 <> space  AND  ls_unitshier-name2 <> space.
    APPEND ls_unitshier TO lt_uhier.

  ENDMETHOD.          "append_sub_func


* Appends information about access to database table.

  METHOD append_dbtable.

    DATA: ls_dbtable TYPE ts_dbtable.
    DATA: lv_tabclass TYPE tabclass.

*   If table name is provided dynamically - just store information.
*   If statically - check and get table parameters in DDIC.
    IF i_table(1) <> '('.
*     Check if table exists and get description.
      SELECT SINGLE tabclass INTO (lv_tabclass) FROM dd02l
   WHERE tabname = i_table.
      IF sy-subrc <> 0.
   EXIT.
      ENDIF.
      SELECT SINGLE ddtext INTO (ls_dbtable-ddtext) FROM dd02t
   WHERE tabname = i_table
     AND ddlanguage = sy-langu
     AND as4local = 'A'.
    ENDIF.
    ls_dbtable-table = i_table.
    ls_dbtable-mode = i_mode.
    ls_dbtable-program = ls_cur_prog-name.
    ls_dbtable-clsname = ls_cur_class-clsname.
    ls_dbtable-name = ls_cur_unit-name.
    ls_dbtable-type = ls_cur_unit-type.
    COLLECT ls_dbtable INTO gt_dbtables.

  ENDMETHOD.          "append_dbtable


* Appends last comment to the current program (include). Appends only
* if is not entered yet. It is because comments beginning with *&
* are added by pretty-printer for forms.


  METHOD append_cur_prog_comment.

    DATA: ls_prog TYPE ts_program.
    DATA: l_tabix TYPE sy-tabix.

*   This comment must be outside code unit
    IF ls_cur_unit-name IS INITIAL.
*     Store program comment only if it is empty yet.
      READ TABLE gt_programs INTO ls_prog
       WITH KEY program = ls_cur_prog-name.
      IF sy-subrc = 0  AND  ls_prog-comment IS INITIAL.
   l_tabix = sy-tabix.
   ls_prog-comment = ls_last_comment.
   MODIFY gt_programs FROM ls_prog INDEX l_tabix.
   CLEAR: ls_last_comment.       " only if appended
      ENDIF.
    ENDIF.

  ENDMETHOD.          "append_prog_comment


* Appends last comment to the current class (general level).

  METHOD append_cur_class_comment.

    DATA: ls_class TYPE ts_class.
    DATA: l_tabix TYPE sy-tabix.

    READ TABLE gt_classes INTO ls_class
          WITH KEY clsname = ls_cur_class-clsname
         clstype = ls_cur_class-clstype.
    IF sy-subrc = 0.
      l_tabix = sy-tabix.
      IF ls_class-comment IS INITIAL.
   ls_class-comment = ls_last_comment.
      ELSE.
   APPEND LINES OF ls_last_comment-tags TO ls_class-comment-tags.
      ENDIF.
      MODIFY gt_classes FROM ls_class INDEX l_tabix.
    ENDIF.
    CLEAR: ls_last_comment.

  ENDMETHOD.          "append_prog_comment


* Appends last comment to the current code unit.

  METHOD append_cur_unit_comment.

    DATA: ls_unit TYPE ts_modunit.
    DATA: l_tabix TYPE sy-tabix.

    READ TABLE gt_modunits INTO ls_unit
          WITH KEY name = ls_cur_unit-name
         type = ls_cur_unit-type.
    IF sy-subrc = 0.
      l_tabix = sy-tabix.
      IF ls_unit-comment IS INITIAL.
   ls_unit-comment = ls_last_comment.
      ELSE.
   APPEND LINES OF ls_last_comment-tags TO ls_unit-comment-tags.
      ENDIF.
      MODIFY gt_modunits FROM ls_unit INDEX l_tabix.
    ENDIF.
    CLEAR: ls_last_comment.

  ENDMETHOD.          "append_cur_unit_comment


* Appends comment to right object - depends, if it is inside form or
* class or outside them

  METHOD append_comment.

*   If inside code unit, comment is added to this unit
    IF ls_cur_unit-name IS NOT INITIAL.
      CALL METHOD append_cur_unit_comment.
*   If inside class definition/implementation (but outside method)
    ELSEIF ls_cur_class-clsname IS NOT INITIAL.
      CALL METHOD append_cur_class_comment.
*   In other cases add to program's comment
    ELSEIF ls_cur_prog-name IS NOT INITIAL.
      CALL METHOD append_cur_prog_comment.
    ENDIF.

  ENDMETHOD.          "append_comment


* Converts program levels (raw results of SCAN ABAP-CODE) into more
* suitable format of global table GT_PROGRAMS

  METHOD levels_to_programms.

    DATA: ls_level TYPE slevel,
     ls_prog TYPE ts_program.

*   Convert levels into GT_PROGRAMS
    LOOP AT lt_levels INTO ls_level.

      CLEAR: ls_prog.
      ls_prog-depth   = ls_level-depth.
      ls_prog-program = ls_level-name.
      IF ls_level-level = 0.
   ls_prog-program = gv_main_program_name.
      ENDIF.

*     For macros
      IF ls_level-type = 'D'.
   ls_prog-subc = '9'.          " non-standard
   ls_prog-title = 'User macro'.
*       Each call of macro is placed in the table, so we maust check
*       if already appended
   READ TABLE gt_programs TRANSPORTING NO FIELDS WITH KEY
            program = ls_prog-program
            depth   = ls_prog-depth.
   CHECK sy-subrc <> 0.

*     Main program, include (type = P)
      ELSE.
*       Get program type (1, ...)
   SELECT SINGLE subc INTO (ls_prog-subc) FROM trdir
     WHERE name = ls_prog-program.
*       Title of the program is determined from program's properties
*       in logon language, or in EN/DE or in any available.
   SELECT SINGLE text INTO (ls_prog-title) FROM trdirt
     WHERE name = ls_prog-program
       AND sprsl = sy-langu.
   IF sy-subrc <> 0.
     SELECT SINGLE text INTO (ls_prog-title) FROM trdirt
       WHERE name = ls_prog-program
         AND sprsl IN ('E', 'D').
     IF sy-subrc <> 0.
       SELECT SINGLE text INTO (ls_prog-title) FROM trdirt
         WHERE name = ls_prog-program.
     ENDIF.
   ENDIF.
      ENDIF.

      APPEND ls_prog TO gt_programs.
    ENDLOOP.

  ENDMETHOD.          "levels_to_programms


* Converts results code analysis (hierarchy of code units calls)
* into format more suitable for further processing.

  METHOD rework_units_hier.

    DATA: ls_hier TYPE ts_unitshier,
     ls_prog TYPE ts_program,
     ls_unit TYPE ts_modunit.

*   If main program is an executable (type 1) program we will start
*   with events in main program
    READ TABLE gt_programs INTO ls_prog INDEX 1.
    IF ls_prog-subc = '1'.
      LOOP AT gt_modunits INTO ls_unit WHERE program = ls_prog-program
                AND type = 'E'.
   CLEAR: ls_hier.
   ls_hier-name2 = ls_unit-name.
   ls_hier-type2 = ls_unit-type.
   ls_hier-prog1 = ls_unit-program.
   ls_hier-clsname1 = ls_unit-clsname.
   ls_hier-depth = '1'.
   CALL METHOD do_hier_path( ls_hier ).
      ENDLOOP.

*   For other program types, we go through all programs and build
*   tree for every unit which has no caller
    ELSE.
      LOOP AT gt_programs INTO ls_prog.
   LOOP AT gt_modunits INTO ls_unit
             WHERE program = ls_prog-program.
*    Check if it has caller
     READ TABLE lt_uhier WITH KEY name2 = ls_unit-name
                   type2 = ls_unit-type
               TRANSPORTING NO FIELDS.
     IF sy-subrc <> 0.
       CLEAR: ls_hier.
       ls_hier-name2 = ls_unit-name.
       ls_hier-type2 = ls_unit-type.
       ls_hier-prog1 = ls_unit-program.
       ls_hier-clsname1 = ls_unit-clsname.
       ls_hier-depth = '1'.
       CALL METHOD do_hier_path( ls_hier ).
     ENDIF.
   ENDLOOP.
      ENDLOOP.
    ENDIF.

  ENDMETHOD.          "rework_units_hier


* This method does not work for calls cycles (a->b and b->a)

  METHOD do_hier_path.  " importing is_start type ts_unitshier

    DATA: ls_hier TYPE ts_unitshier.

    APPEND is_start TO gt_unitshier.
    LOOP AT lt_uhier INTO ls_hier WHERE name1 = is_start-name2
                AND type1 = is_start-type2.
      ls_hier-depth = is_start-depth + 1.
      CALL METHOD do_hier_path( ls_hier ).
    ENDLOOP.

  ENDMETHOD.          "do_hier_path


*======================================================================

* Gets the first statement of code. Statement is a part of code ended
* with dot.

  METHOD get_first_statement.

    CLEAR: lv_cur_stmnt_idx.
    CALL METHOD get_next_statement
      IMPORTING
   es_stmnt = es_stmnt.

  ENDMETHOD.          "get_first_statement


* Gets the next statement of code. In case of error (no more
* statements), returns empty statement (you can check field TYPE).

  METHOD get_next_statement.

    DATA: l_cnt TYPE i.
    CLEAR: ls_cur_stmnt, ls_cur_token,
      lv_cur_token_idx.

    DESCRIBE TABLE lt_statements LINES l_cnt.
    IF lv_cur_stmnt_idx <= l_cnt.        " pozwalamy wyjsc idx
      lv_cur_stmnt_idx = lv_cur_stmnt_idx + 1.
    ENDIF.
    IF lv_cur_stmnt_idx > 0  AND  lv_cur_stmnt_idx <= l_cnt.
      READ TABLE lt_statements INTO ls_cur_stmnt INDEX lv_cur_stmnt_idx.
      CALL METHOD set_cur_prog.
    ENDIF.
    es_stmnt = ls_cur_stmnt.

  ENDMETHOD.          "get_next_statement


* Returns again current statement.

  METHOD get_cur_statement.
    es_stmnt = ls_cur_stmnt.
  ENDMETHOD.          "get_cur_statement


* Gets the first token (keyword, operator) in the current statement.

  METHOD get_first_token.

    CLEAR: lv_cur_token_idx.
    CALL METHOD get_next_token
      IMPORTING
   es_token = es_token.

  ENDMETHOD.          "get_first_token


* Gets the next token of current statemnt. In case of error (no more
* tokens), returns empty token (you can check field STR or TYPE).

  METHOD get_next_token.

    CLEAR: ls_cur_token.
    IF lv_cur_token_idx < ls_cur_stmnt-from.
      lv_cur_token_idx = ls_cur_stmnt-from.
    ELSEIF lv_cur_token_idx <= ls_cur_stmnt-to.
      lv_cur_token_idx = lv_cur_token_idx + 1.
    ENDIF.
    IF lv_cur_token_idx >= ls_cur_stmnt-from  AND
       lv_cur_token_idx <= ls_cur_stmnt-to.
      READ TABLE lt_tokens INTO ls_cur_token INDEX lv_cur_token_idx.
    ENDIF.
    es_token = ls_cur_token.

  ENDMETHOD.          "get_next_token


* Returns again current token of current statemnt.

  METHOD get_cur_token.
    es_token = ls_cur_token.
  ENDMETHOD.          "get_cur_token


*======================================================================
* The followinh methods are used for test purposes - they dump
* to the screen results of SCAN ABAP-CODE.

* Displays all statements and tokens with details (type, level, posit.).

  METHOD dump_statements_detailed.

    DATA: l_stmnt TYPE sstmnt,
     l_token TYPE ts_token.

    WRITE:/ 'Program:', gv_main_program_name.
    WRITE: / '==================================================='.
    WRITE: / 'S T A T E M E N T S   D E T A I L S'.
    WRITE: / '==================================================='.

    CALL METHOD get_first_statement
      IMPORTING
   es_stmnt = l_stmnt.
    WHILE l_stmnt-type <> space.
      WRITE:/ 'Statement idx=', lv_cur_stmnt_idx, 'Type=', l_stmnt-type.
      CALL METHOD get_first_token
   IMPORTING
     es_token = l_token.
      WHILE l_token-type <> space.
   WRITE:/ '       Token idx=', lv_cur_token_idx,
      'Type=', l_token-type, 'Str=', l_token-str.
   CALL METHOD get_next_token
     IMPORTING
       es_token = l_token.
      ENDWHILE.
      CALL METHOD get_next_statement
   IMPORTING
     es_stmnt = l_stmnt.
    ENDWHILE.

  ENDMETHOD.          "dump_statements_detailed


* Displays statements as lines of code (one code = one line).

  METHOD dump_statements.

    DATA: l_stmnt TYPE sstmnt,
     l_token TYPE ts_token.

    WRITE:/ 'Program:', gv_main_program_name.
    WRITE: / '==================================================='.
    WRITE: / 'S T A T E M E N T S'.
    WRITE: / '==================================================='.

    CALL METHOD get_first_statement
      IMPORTING
   es_stmnt = l_stmnt.
    WHILE l_stmnt-type <> space.

      WRITE:/ '===>'.
      CALL METHOD get_first_token
   IMPORTING
     es_token = l_token.
      WHILE l_token-type <> space.
   WRITE: l_token-str.
   CALL METHOD get_next_token
     IMPORTING
       es_token = l_token.
      ENDWHILE.
      CALL METHOD get_next_statement
   IMPORTING
     es_stmnt = l_stmnt.
    ENDWHILE.

  ENDMETHOD.          "dump_statements


* Displays content of tables returned by SCAN ABAP-CODE.

  METHOD dump_tables_scan.

    DATA: ls_srccode TYPE string,
     ls_tokens TYPE ts_token ,
     ls_statements TYPE sstmnt,
     ls_levels TYPE slevel.

    WRITE:/ 'Program:', gv_main_program_name.

    WRITE: / '==================================================='.
    WRITE: / 'T O K E N S'.
    WRITE:/ '       Lp.  TYPE    ROW       OFF2       OFF3',
       '  COL  LEN1  LEN2  LEN3  STR'.
    WRITE: / '==================================================='.

    LOOP AT lt_tokens INTO ls_tokens.
      WRITE:/ sy-tabix,
         ls_tokens-type, ls_tokens-row, ls_tokens-off2,
         ls_tokens-off3, ls_tokens-col,
         ls_tokens-len1, ls_tokens-len2, ls_tokens-len3,
         ls_tokens-str.
    ENDLOOP.

    WRITE: / '==================================================='.
    WRITE: / 'S T A T E M E N T S'.
    WRITE: / '       Lp.      LEVEL      STRUC       FROM    TO',
        '    NUMBER   COLONROW       TROW COCOL  TCOL PRLEN',
        ' TYPE.TERM ENHMT'.
    WRITE: / '==================================================='.
    LOOP AT lt_statements INTO ls_statements.
      WRITE:/ sy-tabix,
         ls_statements-level, ls_statements-struc,
         ls_statements-from,
         ls_statements-to, ls_statements-number,
         ls_statements-colonrow, ls_statements-trow,
         ls_statements-coloncol, ls_statements-tcol,
         ls_statements-prefixlen, ls_statements-type,
         ls_statements-terminator.      ", ls_statements-enhmt.
    ENDLOOP.

    WRITE: / '==================================================='.
    WRITE: / 'L E V E L S'.
    WRITE: / '       Lp.      DEPTH      LEVEL      STMNT',
        '      FROM    TO  TYPE NAME'.
    WRITE: / '==================================================='.
    LOOP AT lt_levels INTO ls_levels.
      WRITE:/ sy-tabix,
         ls_levels-depth, ls_levels-level, ls_levels-stmnt,
         ls_levels-from, ls_levels-to,
         ls_levels-type, ls_levels-name.
    ENDLOOP.

*    WRITE: / '==================================================='.
*    WRITE: / 'S T R U C T U R E S'.
*    WRITE: / '       Lp.  TYPE  STMNT_TYPE   K_START    KEY_END',
*        '   STMNT_FROM   STMNT_TO STRUC_FROM   STRUC_TO',
*        '      BACK'.
*    WRITE: / '==================================================='.
*    LOOP AT gt_structures.
*      WRITE:/ sy-tabix,
*         gt_structures-type, '   ',
*         gt_structures-stmnt_type, '   ',
*         gt_structures-key_start, '   ',
*         gt_structures-key_end, '      ',
*         gt_structures-stmnt_from, gt_structures-stmnt_to,
*         gt_structures-struc_from, gt_structures-struc_to,
*         gt_structures-back.
*    ENDLOOP.

  ENDMETHOD.          "dump_tables_scan

ENDCLASS.          "cl_ic_code_analysis IMPLEMENTATION
Back to top
View user's profile Send private message
admin
Администратор
Администратор



Joined: 01 Sep 2007
Posts: 1639

PostPosted: Fri Nov 28, 2008 2:14 am    Post subject: Reply with quote

Code:
   
*&---------------------------------------------------------------------*
*&  Include      ZICDOC_CL_CODE_ANALYSIS_HTML
*&---------------------------------------------------------------------*
* @Author Ireneusz Cwir
* @Date   June 2006
* @Info   Include contains definition and implementation of class
* ZCL_IC_CODE_ANALYSIS_HTML. This class handles analysis of ABAP
* program and creation of HTML file with analysis results.
* The class uses class ZCL_IC_CODE_ANALYSIS to scan source code and
* store results in public tables. This class reads these tables and
* writes HTML file.
* HTML document creation is handled by class ZCL_IC_HTML.


INCLUDE zicdoc_cl_code_analysis.
INCLUDE zicdoc_cl_html.


* Texts and templates used for creation of HTML file
* They must be in HTML source format (ec. '<' for displaying '<')
* Variables in templates should have format: @n@,
* where n = number of paparmeter
*
* Section 0 - general data (document header)
* Section 1 - programs and includes hierarchy
* Section 2 - database tables used in programs
* Section 3 - programs and includes summary
* Section 4 - class components
* Section 5 - non-class code units
* Section 6 - code units calls hierarchy

* Code page placed in document header
CONSTANTS: c_html_code_page TYPE string VALUE 'windows-1250'.

* Cascade style sheet (CSS) file name (with path)
CONSTANTS: c_css_file_name TYPE string VALUE 'ZIcDocStyle.css'.

* A kind of info about author of the tool
CONSTANTS: c_zicdoc_author TYPE string VALUE
          '<!-- Genereted by ZICDOC, by Ireneusz Cwir -->'.

* HTML title (displayed in explorer window's title)
CONSTANTS: c_html_title TYPE string VALUE
        '@1@ - Source code documentation'.


* Sections' headers
CONSTANTS: c_html_header_0 TYPE string VALUE
        '<h1>@1@ - Source code documentation</h1><br>',
      c_html_header_1 TYPE string VALUE
        '<br><h2>Programs and includes</h2><br>',
      c_html_header_2 TYPE string VALUE
        '<br><h2>Database tables</h2><br>',
      c_html_header_3 TYPE string VALUE
        '<br><h2>Programs and includes summary</h2><br>',
      c_html_header_4 TYPE string VALUE
        '<br><h2>Class components</h2><br>',
      c_html_header_5 TYPE string VALUE
        '<br><h2>Non-class code units</h2><br>',
      c_html_header_6 TYPE string VALUE
        '<br><h2>Code units calls hierarchy</h2><br>'.


* General templates
CONSTANTS:
* Template for writting all elements of comment. variables are for:
* 1. Tag, 2. Parameter, 3. Text of comment
       c_html_comment_complex TYPE string VALUE
        '<dl><dt>@1@</dt><dd><var>@2@ </var>@3@</dd></dl>',
* Code unit details - header. 1. Unit name
       c_html_unit_det_header TYPE string VALUE
        '<hr><h5>@1@</h5>',
* Code unit details - Declaration. 1. Unit name, 2. Type, 3. Params
       c_html_unit_det_declaration TYPE string VALUE
     '<dl><dt><code>@2@ @1@</code></dt><dd><code>@3@</code></dd></dl>'.


* For section 1 - hierarchy of includes
* Prefix representing next level of nesting of include (like . )
CONSTANTS: c_html_s1_nesting_level TYPE string VALUE '. ',

* Style for placing program name
     c_html_s1_program_name TYPE string VALUE
        '<dfn>@1@</dfn><br>'.


* For section 2 - database tables
* Short info
CONSTANTS: c_html_s2_sub_header TYPE string VALUE
         '<h4>Database tables access:</h4>',
* Line of HTML table containing info about database table
* 1. Table name, 2. Access mode, 3. Table description from DDIC
       c_html_s2_db_table_info TYPE string VALUE
       '<tr><td class="dbname"><dfn>@1@</dfn></td>' &
       '<td class="dbaccess">@2@</td>' &
       '<td>@3@</td></tr>'.


* For section 3 - includes summary
CONSTANTS:
* Program name (as a section header)
       c_html_s3_program TYPE string VALUE
      '<h3>@1@</h3>',
* Program title (description from dictionary)
       c_html_s3_title TYPE string VALUE
    '<table><tr><td><samp>Title:</samp></td><td>@1@</td></tr></table>',
* Header for code units list
      c_html_s3_units TYPE string VALUE
      '<h4>Forms, events, functions:</h4>',
* Table line for code unit info: 1. Type, 2. Name
      c_html_s3_unit_info TYPE string VALUE
      '<tr><td><samp>@1@</samp></td><td><dfn>@2@</dfn></td></tr>'.


* For section 4 - class components
CONSTANTS:
* Class name (as subsection header). 1. Clas/interf, 2. Name
      c_html_s4_class_name TYPE string VALUE
      '<h3>@1@ @2@</h3>',
* Header for components list
      c_html_s4_components TYPE string VALUE
      '<h4>Components:</h4>',
* Table line for general class info - program, base class and declar.
      c_html_s4_class_program TYPE string VALUE
 '<tr><td><samp>Program:</samp></td><td><dfn>@1@</dfn></td></tr>',
      c_html_s4_class_base TYPE string VALUE
 '<tr><td><samp>Base class:</samp></td><td><dfn>@1@</dfn></td></tr>',
      c_html_s4_class_declaration TYPE string VALUE
 '<tr><td><samp>Declaration:</samp></td><td><dfn>@1@</dfn></td></tr>',
* Table line for component summary info: 1. Type, 2. Name
      c_html_s4_comp_sum_info TYPE string VALUE
      '<tr><td><samp>@1@</samp></td><td><dfn>@2@</dfn></td></tr>'.


* For section 5 - non-class code units
CONSTANTS:
* Program name (as subsection header). 1. Name
      c_html_s5_program TYPE string VALUE
      '<h3>@1@</h3>'.


* For section 6 - code units calls hierarchy

* Prefix representing next level of nesting of include (like . )
CONSTANTS: c_html_s6_nesting_level TYPE string VALUE '. ',

* Style for placing: 1. Unit name, 2. Unit type
     c_html_s6_unit TYPE string VALUE
        '<dfn>@1@</dfn> <samp>@2@</samp><br>'.


*----------------------------------------------------------------------
* Program uses HTML keywords "A NAME" and "A HREF" (anchors) to build
* links to section describing refrenced objects. Anchors must have
* unique labels (IDs) within document. Program creates them
* in the following way (space is a separator in case of concatenation):
* - Programs (includes) - <program_name> (i.e. 'Z_INC_TEST')
* - Classes - 'Class definition' + <class_name>
*        (i.e. 'Class definition ZCL_TEST')
* - Interfaces - 'Interface' + <interface_name>
* - Class/Interf. component - <comp_type> + <class_name> + <comp_name>
*        (i.e. 'Data ZCL_TEST GV_CNT')
* - Other code units - <unit_type> + <name> (i.e. 'Form DO_TEST')


*----------------------------------------------------------------------*
*       CLASS zcl_ic_code_analysis_html DEFINITION
*----------------------------------------------------------------------*


CLASS zcl_ic_code_analysis_html DEFINITION
            INHERITING FROM zcl_ic_code_analysis.

  PUBLIC SECTION.

*   References to class handling writing HTML file
    DATA: gr_html TYPE REF TO zcl_ic_html.   " Ref to HTML object

    METHODS: constructor.
    METHODS: reset REDEFINITION.

*   Writes results of analysis into HTML file. Must ne called after
*   one of methods ANALYSE_xxx of base class.
*   Parameters decide, which sections of analysis are written
*   to the file.
    METHODS: write_html_file IMPORTING
             i_filename TYPE string
             i_write_includes_hier TYPE c
             i_write_includes_details TYPE c
             i_write_class_components TYPE c
             i_write_class_components_prot TYPE c
             i_write_class_components_priv TYPE c
             i_write_code_units_hier TYPE c
             i_write_code_units_details TYPE c
             i_write_tables TYPE c
             i_html_comments TYPE c
       RETURNING value(ret_code) TYPE i.

  PRIVATE SECTION.

*   Parameters from WRITE_HTML_FILE
    DATA: lv_write_includes_hier TYPE c,
     lv_write_includes_details TYPE c,
     lv_write_code_units_hier TYPE c,
     lv_write_code_units_details TYPE c,
     lv_write_tables TYPE c,
     lv_write_class_components TYPE c,
     lv_write_class_components_prot TYPE c,
     lv_write_class_components_priv TYPE c,
     lv_html_comments TYPE c.

    METHODS: write_general_info,
        write_includes_hier,
        write_database_tables,
        write_includes_details,
        write_class_components,
        write_non_class_code_units,
        write_code_units_hier.

    METHODS: do_write_comments IMPORTING is_comment TYPE ts_comment,
        do_write_db_tables IMPORTING it_tables TYPE tt_dbtables,
        do_write_db_tables_for_unit
               IMPORTING i_clsname TYPE seoclsname
               i_name    TYPE t_unitname
               i_type    TYPE t_unittype,
        do_write_comp_summary_single
              IMPORTING is_cmp   TYPE ts_classcmp,
        do_write_comp_summary IMPORTING i_exp   TYPE seoexpose
                    it_cmps TYPE tt_classcmps,
        do_write_unit_details
               IMPORTING i_name     TYPE string
               i_exp      TYPE string
               i_type     TYPE string
               i_label    TYPE string
               is_param   TYPE ts_parameters
               is_comment TYPE ts_comment,
        do_write_details_class_comp
               IMPORTING is_cmp TYPE ts_classcmp,
        do_write_details_nonclass_unit
               IMPORTING is_unit TYPE ts_modunit.

*   Builds label for anchor for code unit. It can be used in 'a name'
*   and 'a href' HTML tags.
    METHODS: build_a_label_unit IMPORTING is_unit TYPE ts_modunit
            EXPORTING e_label TYPE string,
        build_a_label_class_name
              IMPORTING i_clsname TYPE seoclsname
                   i_clstype TYPE seoclstype
              EXPORTING e_label   TYPE string,
        build_a_label_class_comp IMPORTING is_cmp  TYPE ts_classcmp
                  EXPORTING e_label TYPE string.

*   Adds to HTML document string after replacing varaibles @n@ (n=1..3)
*   with provided value.
    METHODS: add_str_var IMPORTING
             i_str TYPE string
             i_value1 TYPE string OPTIONAL
             i_value2 TYPE string OPTIONAL
             i_value3 TYPE string OPTIONAL.

ENDCLASS.          "zcl_ic_code_analysis_html DEFINITION


*----------------------------------------------------------------------*
*       CLASS zcl_ic_code_analysis_html IMPLEMENTATION
*----------------------------------------------------------------------*

CLASS zcl_ic_code_analysis_html IMPLEMENTATION.

  METHOD constructor.
    CALL METHOD super->constructor.
    CALL METHOD reset.
  ENDMETHOD.          "constructor


* Resets all atributes of the object.
  METHOD reset.
    CALL METHOD super->reset.
    CLEAR: gr_html.
    CLEAR: lv_write_includes_hier, lv_write_includes_details,
      lv_write_class_components, lv_write_class_components_prot,
      lv_write_class_components_priv,
      lv_write_code_units_hier, lv_write_code_units_details,
      lv_write_tables, lv_html_comments.
  ENDMETHOD.          "reset


* Writes results of analysis into HTML file. It must be called after
* one of methods ANALYSE_xxx.

  METHOD write_html_file.

    DATA: l_str TYPE string.

*   Check if analysis has ben already performed
    ret_code = 101.
    CHECK gv_main_program_name IS NOT INITIAL.

*   Store parameters in local atributes - to be used by other methods
    lv_write_includes_hier     = i_write_includes_hier.
    lv_write_includes_details       = i_write_includes_details.
    lv_write_class_components       = i_write_class_components.
    lv_write_class_components_prot  = i_write_class_components_prot.
    lv_write_class_components_priv  = i_write_class_components_priv.
    lv_write_code_units_hier   = i_write_code_units_hier.
    lv_write_code_units_details     = i_write_code_units_details.
    lv_write_tables       = i_write_tables.
    lv_html_comments      = i_html_comments.

*   Start preparing HTML document (prepare heder)
    CREATE OBJECT gr_html.

    l_str = c_html_title.
    REPLACE FIRST OCCURRENCE OF '@1@' IN l_str
       WITH gv_main_program_name.
    CALL METHOD gr_html->start_document
      EXPORTING
   i_title    = l_str
   i_code_page     = c_html_code_page
   i_css_file_name = c_css_file_name
   i_comment       = c_zicdoc_author.

*   Section 0 - document title
    CALL METHOD write_general_info.

*   Section 1 - programs (includes) hierarchy
    IF i_write_includes_hier IS NOT INITIAL.
      CALL METHOD write_includes_hier.
    ENDIF.

*   Section 2 - access to database tables
    IF i_write_tables IS NOT INITIAL.
      CALL METHOD write_database_tables.
    ENDIF.

*   Section 3 - content of programs (includes)
    IF i_write_includes_details IS NOT INITIAL.
      CALL METHOD write_includes_details.
    ENDIF.

*   Section 4 - class components
    IF i_write_class_components IS NOT INITIAL.
      CALL METHOD write_class_components.
    ENDIF.

*   Section 5 - non-class code units
    IF i_write_code_units_details IS NOT INITIAL.
      CALL METHOD write_non_class_code_units.
    ENDIF.

*   Section 6 - hierarchy of code units calls
    IF i_write_code_units_hier IS NOT INITIAL.
      CALL METHOD write_code_units_hier.
    ENDIF.

*   Finish HTML document
    CALL METHOD gr_html->end_document.

*   Write HTML document to disk
    ret_code = gr_html->write_file( i_filename ).

*   Reset all atributes
    CALL METHOD gr_html->reset.
    CLEAR: gr_html.

  ENDMETHOD.          "write_html_file


* Section 0 - general info (document title).

  METHOD write_general_info.

    DATA: l_str TYPE string.

    l_str = gv_main_program_name.
    CALL METHOD add_str_var
      EXPORTING
   i_str    = c_html_header_0
   i_value1 = l_str.

  ENDMETHOD.          "write_general_info


* Section 1 - hierarchy of programs and includes.

  METHOD write_includes_hier.

    DATA: ls_prog TYPE ts_program.
    DATA: l_out TYPE string,
     l_str TYPE string.
    DATA: l_cnt TYPE i.

*   Section title
    CALL METHOD gr_html->add_string_raw( c_html_header_1 ).
    CALL METHOD gr_html->flush_buffer.

*   Write nested includes (hierarchy)
    LOOP AT gt_programs INTO ls_prog.

*     String representin depth of nesting (. . .)
      CLEAR: l_out.
      l_cnt = ls_prog-depth - 1.
      DO l_cnt TIMES.
   CONCATENATE l_out c_html_s1_nesting_level INTO l_out.
      ENDDO.

*     Program name. If details printed - place also HTML link
      l_str = ls_prog-program.
      IF lv_write_includes_details IS NOT INITIAL.
   CALL METHOD gr_html->str_a_href
     EXPORTING
       i_label = l_str
       i_text  = l_str
     RECEIVING
       e_str   = l_str.
      ENDIF.
      CONCATENATE l_out l_str INTO l_out.
      CALL METHOD add_str_var
   EXPORTING
     i_str    = c_html_s1_program_name
     i_value1 = l_out.
    ENDLOOP.

  ENDMETHOD.          "write_includes_hier


* Section 2 - access to database tables.

  METHOD write_database_tables.

    DATA: lt_tables TYPE tt_dbtables,
     ls_table TYPE ts_dbtable,
     ls_last  TYPE ts_dbtable.

*   Table GT_DBTABLES can contains the same table in several records
*   for instance, access from different forms. Therefore, we need
*   to prepare unique record only.
    SORT gt_dbtables BY table mode.
    LOOP AT gt_dbtables INTO ls_table.

      IF ls_table-name <> ls_last-name  AND
    ls_table-mode <> ls_last-mode.
   APPEND ls_table TO lt_tables.
   ls_last = ls_table.
      ENDIF.

    ENDLOOP.

*   At least one record
    CHECK lt_tables IS NOT  INITIAL.

*   Section title
    CALL METHOD gr_html->add_string_raw( c_html_header_2 ).
    CALL METHOD gr_html->flush_buffer.

*   Write list of tables
    CALL METHOD do_write_db_tables( lt_tables ).

  ENDMETHOD.          "write_tables


* Writes list of database tables.

  METHOD do_write_db_tables.

    DATA: ls_table TYPE ts_dbtable.
    DATA: l_str1 TYPE string, l_str2 TYPE string, l_str3 TYPE string.

*   At least one record
    CHECK it_tables IS NOT  INITIAL.

*   Subsection info
    CALL METHOD gr_html->add_string_raw( c_html_s2_sub_header ).
    CALL METHOD gr_html->flush_buffer.

*   Write database tables in HTML table
    gr_html->add_tag_start( 'table' ).
    CALL METHOD gr_html->flush_buffer.

    LOOP AT it_tables INTO ls_table.

      l_str1 = ls_table-table.
      l_str2 = get_db_access_mode_desc( ls_table-mode ).
      l_str3 = ls_table-ddtext.
      l_str3 = gr_html->str2html( l_str3 ).

      CALL METHOD add_str_var
   EXPORTING
     i_str    = c_html_s2_db_table_info
     i_value1 = l_str1
     i_value2 = l_str2
     i_value3 = l_str3.

    ENDLOOP.

    gr_html->add_tag_end( 'table' ).
    CALL METHOD gr_html->flush_buffer.

  ENDMETHOD.          "do_write_db_tables


* Writes tables accessed from code unit.

  METHOD do_write_db_tables_for_unit.

    DATA: lt_tables TYPE tt_dbtables,
     ls_table TYPE ts_dbtable.

*   Prepare list of tables for code unit
    LOOP AT gt_dbtables INTO ls_table WHERE clsname = i_clsname
               AND name = i_name
               AND type = i_type.
      APPEND ls_table TO lt_tables.
    ENDLOOP.

*   At least one record
    CHECK lt_tables IS NOT  INITIAL.

*   Write list of tables
    CALL METHOD do_write_db_tables( lt_tables ).

  ENDMETHOD.          "do_write_db_tables_for_unit


* Section 3 - content of INCLUDEs (summary).

  METHOD write_includes_details.

    DATA: ls_prog TYPE ts_program,
     ls_unit TYPE ts_modunit.
    DATA: l_str   TYPE string,
     l_str2  TYPE string,
     l_str3  TYPE string,
     l_label TYPE string.

*   Section title
    CALL METHOD gr_html->add_string_raw( c_html_header_3 ).
    CALL METHOD gr_html->flush_buffer.

*   For all programs (includes)
    LOOP AT gt_programs INTO ls_prog.

*     Program name (as anchor)
      l_str = ls_prog-program.
      CALL METHOD gr_html->str_a_name
   EXPORTING
     i_label = l_str
     i_text  = l_str
   RECEIVING
     e_str   = l_str.

      CALL METHOD add_str_var
   EXPORTING
     i_str    = c_html_s3_program
     i_value1 = l_str.

*     Program title (in a table)
      IF ls_prog-title IS NOT INITIAL.
   l_str = ls_prog-title.
   CALL METHOD add_str_var
     EXPORTING
       i_str    = c_html_s3_title
       i_value1 = l_str.
      ENDIF.

*     Program comments
      CALL METHOD do_write_comments( ls_prog-comment ).

*     Code units list header
      CALL METHOD gr_html->add_string_raw( c_html_s3_units ).
      CALL METHOD gr_html->flush_buffer.

*     Write code units in HTML table
      gr_html->add_tag_start( 'table' ).
      CALL METHOD gr_html->flush_buffer.

*     All code units for current program
      LOOP AT gt_modunits INTO ls_unit WHERE program = ls_prog-program.

   l_str = get_code_unit_type_desc( ls_unit-type ).
   l_str2 = ls_unit-name.

*       If details for code units or class components are issued
   IF ( ls_unit-type = 'M'  OR ls_unit-type = 'I' OR
        ls_unit-type = 'CD' OR ls_unit-type = 'CI' ) AND
       lv_write_class_components IS NOT INITIAL  OR
       lv_write_code_units_details IS NOT INITIAL.

*    Creates label for anchor
     CALL METHOD build_a_label_unit
       EXPORTING
         is_unit = ls_unit
       IMPORTING
         e_label = l_str3.
     CALL METHOD gr_html->str_a_href
       EXPORTING
         i_label = l_str3
         i_text  = l_str2
       RECEIVING
         e_str   = l_str2.
   ENDIF.
   CALL METHOD add_str_var
     EXPORTING
       i_str    = c_html_s3_unit_info
       i_value1 = l_str
       i_value2 = l_str2.

      ENDLOOP.

      gr_html->add_tag_end( 'table' ).
      CALL METHOD gr_html->flush_buffer.

    ENDLOOP.

  ENDMETHOD.          "write_includes_detail


* Section 4 - class components.

  METHOD write_class_components.

    DATA: lt_cmps   TYPE tt_classcmps,
     ls_cmp    TYPE ts_classcmp.
    DATA: ls_prog   TYPE ts_program,
     ls_class  TYPE ts_class,
*     ls_param  TYPE ts_param_detail,
     l_type    TYPE t_unittype,
     l_str TYPE string, l_str2 TYPE string, l_str3 TYPE string.

*   Section title
    CALL METHOD gr_html->add_string_raw( c_html_header_4 ).
    CALL METHOD gr_html->flush_buffer.

*   Display classes sorted by programs
    LOOP AT gt_programs INTO ls_prog.

*     Classes defined in the program
      LOOP AT gt_classes INTO ls_class
         WHERE program = ls_prog-program.

*       Class name - section header. We also build anchor for reference
   l_type = 'CD'.
   IF ls_class-clstype = '1'.
     l_type = 'I'.
   ENDIF.
   l_str = get_code_unit_type_desc( l_type ).
   l_str2 = ls_class-clsname.
   CALL METHOD build_a_label_class_name
     EXPORTING
       i_clsname = ls_class-clsname
       i_clstype = ls_class-clstype
     IMPORTING
       e_label   = l_str3.
   CALL METHOD gr_html->str_a_name
     EXPORTING
       i_label = l_str3
       i_text  = l_str2
     RECEIVING
       e_str   = l_str2.
   CALL METHOD add_str_var
     EXPORTING
       i_str    = c_html_s4_class_name
       i_value1 = l_str
       i_value2 = l_str2.

*       Write general info in HTML table
   gr_html->add_tag_start( 'table' ).
   CALL METHOD gr_html->flush_buffer.

*       Base class
   IF ls_class-super IS NOT INITIAL.

     l_str2 = ls_class-super.
*    If we have base class in tables components - build reference
     READ TABLE gt_classes TRANSPORTING NO FIELDS
            WITH KEY  clsname = ls_class-super
                 clstype = '0'.
     IF sy-subrc = 0.
       CALL METHOD build_a_label_class_name
         EXPORTING
      i_clsname = ls_class-super
      i_clstype = '0'
         IMPORTING
      e_label   = l_str3.
       CALL METHOD gr_html->str_a_href
         EXPORTING
      i_label = l_str3
      i_text  = l_str2
         RECEIVING
      e_str   = l_str2.
     ENDIF.
     CALL METHOD add_str_var
       EXPORTING
         i_str    = c_html_s4_class_base
         i_value1 = l_str2.

   ENDIF.

*       Class declaration
   IF ls_class-param-text is not INITIAL.
     CALL METHOD add_str_var
       EXPORTING
         i_str    = c_html_s4_class_declaration
         i_value1 = ls_class-param-text.
   ENDIF.
*   READ TABLE ls_class-param-params INTO ls_param INDEX 1.
*   IF sy-subrc = 0.
*
*     l_str = ls_param-text.
*     CALL METHOD add_str_var
*       EXPORTING
*         i_str    = c_html_s4_class_declaration
*         i_value1 = l_str.
*   ENDIF.

*       Program name
   l_str = ls_class-program.
   IF lv_write_includes_details IS NOT INITIAL.
     CALL METHOD gr_html->str_a_href
       EXPORTING
         i_label = l_str
         i_text  = l_str
       RECEIVING
         e_str   = l_str.
   ENDIF.
   CALL METHOD add_str_var
     EXPORTING
       i_str    = c_html_s4_class_program
       i_value1 = l_str.

*       Close general info
   gr_html->add_tag_end( 'table' ).
   CALL METHOD gr_html->flush_buffer.

*       Class comments
   CALL METHOD do_write_comments( ls_class-comment ).

*       Prepare local table with comp. belonging to the current class
   REFRESH: lt_cmps.
   LOOP AT gt_classcmps INTO ls_cmp
             WHERE clsname = ls_class-clsname
               AND clstype = ls_class-clstype.
     APPEND ls_cmp TO lt_cmps.
   ENDLOOP.      " components

*       Components summary list header
   CALL METHOD gr_html->add_string_raw( c_html_s4_components ).
   CALL METHOD gr_html->flush_buffer.
*       Write components summary in HTML table
   gr_html->add_tag_start( 'table' ).
   CALL METHOD gr_html->flush_buffer.

*       Write public components
   CALL METHOD do_write_comp_summary
     EXPORTING
       i_exp   = '2'
       it_cmps = lt_cmps.
*       Write protected components
   IF lv_write_class_components_prot IS NOT INITIAL.
     CALL METHOD do_write_comp_summary
       EXPORTING
         i_exp   = '1'
         it_cmps = lt_cmps.
   ENDIF.
*       Write private components
   IF lv_write_class_components_priv IS NOT INITIAL.
     CALL METHOD do_write_comp_summary
       EXPORTING
         i_exp   = '0'
         it_cmps = lt_cmps.
   ENDIF.

*       Close components summary table
   gr_html->add_tag_end( 'table' ).
   CALL METHOD gr_html->flush_buffer.

*       Components details
   LOOP AT lt_cmps INTO ls_cmp.
     CALL METHOD do_write_details_class_comp( ls_cmp ).
   ENDLOOP.

      ENDLOOP.      " classes
    ENDLOOP.      " programs

  ENDMETHOD.          "write_class_components


* Writes summary (table) with class components for one exposure.

  METHOD do_write_comp_summary.

    DATA: ls_cmp TYPE ts_classcmp.

*   Interfaces
    LOOP AT it_cmps INTO ls_cmp WHERE exposure = i_exp
              AND cmptype  = 'I'.
      CALL METHOD do_write_comp_summary_single( ls_cmp ).
    ENDLOOP.
*   Types
    LOOP AT it_cmps INTO ls_cmp WHERE exposure = i_exp
              AND cmptype  = 'T'.
      CALL METHOD do_write_comp_summary_single( ls_cmp ).
    ENDLOOP.
*   Constants
    LOOP AT it_cmps INTO ls_cmp WHERE exposure = i_exp
              AND cmptype  = 'C'.
      CALL METHOD do_write_comp_summary_single( ls_cmp ).
    ENDLOOP.
*   Aliases
    LOOP AT it_cmps INTO ls_cmp WHERE exposure = i_exp
              AND cmptype  = 'A'.
      CALL METHOD do_write_comp_summary_single( ls_cmp ).
    ENDLOOP.
*   Class-data
    LOOP AT it_cmps INTO ls_cmp WHERE exposure = i_exp
              AND cmptype  = 'CD'.
      CALL METHOD do_write_comp_summary_single( ls_cmp ).
    ENDLOOP.
*   Data
    LOOP AT it_cmps INTO ls_cmp WHERE exposure = i_exp
              AND cmptype  = 'D'.
      CALL METHOD do_write_comp_summary_single( ls_cmp ).
    ENDLOOP.
*   Class-methods
    LOOP AT it_cmps INTO ls_cmp WHERE exposure = i_exp
              AND cmptype  = 'CM'.
      CALL METHOD do_write_comp_summary_single( ls_cmp ).
    ENDLOOP.
*   Methods
    LOOP AT it_cmps INTO ls_cmp WHERE exposure = i_exp
              AND cmptype  = 'M'.
      CALL METHOD do_write_comp_summary_single( ls_cmp ).
    ENDLOOP.
*   Class-events
    LOOP AT it_cmps INTO ls_cmp WHERE exposure = i_exp
              AND cmptype  = 'CE'.
      CALL METHOD do_write_comp_summary_single( ls_cmp ).
    ENDLOOP.
*   Events
    LOOP AT it_cmps INTO ls_cmp WHERE exposure = i_exp
              AND cmptype  = 'E'.
      CALL METHOD do_write_comp_summary_single( ls_cmp ).
    ENDLOOP.


  ENDMETHOD.          "do_write_comp_summary


* Writes single line in table of class components summary.

  METHOD do_write_comp_summary_single.

    DATA: l_str TYPE string, l_str2 TYPE string, l_str3 TYPE string.

*   Build exposure and component type string (i.e. Public Data)
    l_str  = get_class_cmp_exposure_desc( is_cmp-exposure ).
    l_str3 = get_class_cmp_type_desc( is_cmp-cmptype ).
    CONCATENATE l_str l_str3 INTO l_str SEPARATED BY space.

    l_str2 = is_cmp-cmpname.
*   If detailed code info is written - build a reference
    IF lv_write_code_units_details IS NOT INITIAL.

      CALL METHOD build_a_label_class_comp
   EXPORTING
     is_cmp  = is_cmp
   IMPORTING
     e_label = l_str3.
      CALL METHOD gr_html->str_a_href
   EXPORTING
     i_label = l_str3       " ie. Method do_something
     i_text  = l_str2
   RECEIVING
     e_str   = l_str2.
    ENDIF.

    CALL METHOD add_str_var
      EXPORTING
   i_str    = c_html_s4_comp_sum_info
   i_value1 = l_str
   i_value2 = l_str2.

  ENDMETHOD.          "do_write_comp_summary_single


* Writes details of class component.

  METHOD do_write_details_class_comp.

    DATA: ls_unit TYPE ts_modunit.
    DATA: l_name TYPE t_unitname.
    DATA: l_str1 TYPE string,
     l_str2 TYPE string,
     l_str3 TYPE string,
     l_str4 TYPE string.

    l_str1 = get_class_cmp_exposure_desc( is_cmp-exposure ).
    l_str2 = get_class_cmp_type_desc( is_cmp-cmptype ).
    l_str3 = is_cmp-cmpname.

    CALL METHOD build_a_label_class_comp
      EXPORTING
   is_cmp  = is_cmp
      IMPORTING
   e_label = l_str4.

    CALL METHOD do_write_unit_details
      EXPORTING
   i_name     = l_str3
   i_exp      = l_str1
   i_type     = l_str2
   i_label    = l_str4
   is_param   = is_cmp-param
   is_comment = is_cmp-comment.

*   For methods - write additional info
    CHECK is_cmp-cmptype = 'M'  OR  is_cmp-cmptype = 'CM'.

*   Methods can have additional comments in implementation section.
*   These commenta are not in table of class components, but in
*   code units.
    READ TABLE gt_modunits INTO ls_unit
              WITH KEY name = is_cmp-cmpname
                  type = 'M'
                  clsname = is_cmp-clsname.
    IF sy-subrc = 0.
      CALL METHOD do_write_comments( ls_unit-comment ).
    ENDIF.

*   Database tables
    l_name = is_cmp-cmpname.
    CALL METHOD do_write_db_tables_for_unit
      EXPORTING
   i_clsname = is_cmp-clsname
   i_name    = l_name
   i_type    = 'M'.

  ENDMETHOD.          "do_write_details_class_comp


* Section 5 - details of non-class code units (forms, functions, ...)

  METHOD write_non_class_code_units.

    DATA: ls_prog TYPE ts_program,
     ls_unit TYPE ts_modunit.
    DATA: l_str TYPE string, l_str2 TYPE string, l_str3 TYPE string.

*   Section title
    CALL METHOD gr_html->add_string_raw( c_html_header_5 ).
    CALL METHOD gr_html->flush_buffer.

*   Display units sorted by programs
    LOOP AT gt_programs INTO ls_prog.

*     Program name
      l_str = ls_prog-program.
      IF lv_write_includes_details IS NOT INITIAL.

   CALL METHOD gr_html->str_a_href
     EXPORTING
       i_label = l_str
       i_text  = l_str
     RECEIVING
       e_str   = l_str.
      ENDIF.
      CALL METHOD add_str_var
   EXPORTING
     i_str    = c_html_s5_program
     i_value1 = l_str.

*     Units defined in the program
      LOOP AT gt_modunits INTO ls_unit
            WHERE program = ls_prog-program.

*       Skip some unit types (related to classes - they are displayed
*       in dedicated section
   CHECK ls_unit-type <> 'CD'  AND  ls_unit-type <> 'I'  AND
         ls_unit-type <> 'M'.

*       Details of code unit
   CALL METHOD do_write_details_nonclass_unit( ls_unit ).

      ENDLOOP.      " units
    ENDLOOP.   " programs

  ENDMETHOD.          "write_code_units_details


* Writes details of single non-class code unit.

  METHOD do_write_details_nonclass_unit.

    DATA: l_str1 TYPE string,
     l_str2 TYPE string,
     l_str3 TYPE string.

    l_str1 = get_code_unit_type_desc( is_unit-type ).
    l_str2 = is_unit-name.

    CALL METHOD build_a_label_unit
      EXPORTING
   is_unit = is_unit
      IMPORTING
   e_label = l_str3.

    CALL METHOD do_write_unit_details
      EXPORTING
   i_name     = l_str2
   i_type     = l_str1
   i_exp      = ''
   i_label    = l_str3
   is_param   = is_unit-param
   is_comment = is_unit-comment.

    CALL METHOD do_write_db_tables_for_unit
      EXPORTING
   i_clsname = is_unit-clsname
   i_name    = is_unit-name
   i_type    = is_unit-type.

  ENDMETHOD.          "do_write_details_nonclass_unit


* Section 6 - hierarchy of code units calls (functions, forms, ...).

  METHOD write_code_units_hier.

    DATA: ls_hier TYPE ts_unitshier,
     ls_unit TYPE ts_modunit.
    DATA: l_str TYPE string, l_str2 TYPE string, l_str3 TYPE string,
     l_out TYPE string.
    DATA: l_cnt TYPE i.

*   Section title
    CALL METHOD gr_html->add_string_raw( c_html_header_6 ).
    CALL METHOD gr_html->flush_buffer.

*   Process the following calls
    LOOP AT gt_unitshier INTO ls_hier.

*     String representin depth of nesting (. . .)
      CLEAR: l_out.
      l_cnt = ls_hier-depth - 1.
      DO l_cnt TIMES.
   CONCATENATE l_out c_html_s6_nesting_level INTO l_out.
      ENDDO.

      l_str = get_code_unit_type_desc( ls_hier-type2 ).
      l_str2 = ls_hier-name2.
*     At the moment - no reference for methods (we don't know
*     called class name)
      IF lv_write_code_units_details IS NOT INITIAL  AND
    ls_hier-type2 <> 'M'.
*       Check if we have details of called unit
   READ TABLE gt_modunits TRANSPORTING NO FIELDS
        WITH KEY name = ls_hier-name2  type = ls_hier-type2.
   IF sy-subrc = 0.
*    Create label for anchor
     CLEAR: ls_unit.
     ls_unit-name = ls_hier-name2.
     ls_unit-type = ls_hier-type2.
     CALL METHOD build_a_label_unit
       EXPORTING
         is_unit = ls_unit
       IMPORTING
         e_label = l_str3.
     CALL METHOD gr_html->str_a_href
       EXPORTING
         i_label = l_str3
         i_text  = l_str2
       RECEIVING
         e_str   = l_str2.
   ENDIF.
      ENDIF.
      CONCATENATE l_out l_str2 INTO l_out.
      CALL METHOD add_str_var
   EXPORTING
     i_str    = c_html_s6_unit
     i_value1 = l_out
     i_value2 = l_str.

    ENDLOOP.

  ENDMETHOD.          "write_code_units_hier


* Writes details of single code unit. Details should be passed as
* strings (no further processing is performed on them).

  METHOD do_write_unit_details.

    DATA: ls_param  TYPE ts_param_detail.
    DATA: l_str TYPE string, l_str2 TYPE string.

*   Header of code unit - name must be 'a name'
    CALL METHOD gr_html->str_a_name
      EXPORTING
   i_label = i_label
   i_text  = i_name
      RECEIVING
   e_str   = l_str.
    CALL METHOD add_str_var
      EXPORTING
   i_str    = c_html_unit_det_header
   i_value1 = l_str.

*   For class components, concatenate exposure (ie. Public) with
*   component type (ie. Method).
    l_str2 = i_type.
    IF i_exp IS NOT  INITIAL.
      CONCATENATE i_exp i_type INTO l_str2 SEPARATED BY space.
    ENDIF.

*   Prepare string with parameters (declaration)
*    CLEAR: l_str.
*    READ TABLE is_param-params INTO ls_param INDEX 1.
*    IF sy-subrc = 0.
*      l_str = ls_param-text.
*    ENDIF.

*   Unit declaration
    CALL METHOD add_str_var
      EXPORTING
   i_str    = c_html_unit_det_declaration
   i_value1 = i_name
   i_value2 = l_str2
   i_value3 = is_param-text.    " l_str.

*   Unit comments
    CALL METHOD do_write_comments( is_comment ).

  ENDMETHOD.          "do_write_unit_details


* Writes comments formated as a HTML dictionary.

  METHOD do_write_comments.

    DATA: ls_tag TYPE ts_commtag.
    DATA: l_last_param TYPE ts_commtag-param.
    DATA: l_str1 TYPE string,
     l_str2 TYPE string,
     l_str3 TYPE string.

*   Check, if comment is filled
    CHECK is_comment IS NOT INITIAL.

*   Start dictionary
    gr_html->add_tag_start( 'dl' ).
    CALL METHOD gr_html->flush_buffer.

    LOOP AT is_comment-tags INTO ls_tag.

*     If parametr name is repeated - we write it only once
      IF ls_tag-param = l_last_param.
   CLEAR: ls_tag-param.
      ELSE.
   l_last_param = ls_tag-param.
      ENDIF.

*     Text conversions
      l_str1 = ls_tag-tag.
      l_str1 = gr_html->str2html( l_str1 ).
      l_str2 = ls_tag-param.
      l_str2 = gr_html->str2html( l_str2 ).
      l_str3 = ls_tag-text.
      IF lv_html_comments IS INITIAL.
   l_str3 = gr_html->str2html( l_str3 ).
      ENDIF.

*     If tag is INFO, it is printed directly as definition
      IF ls_tag-tag = 'INFO'.
   CALL METHOD gr_html->add_tag
     EXPORTING
       tag = 'dd'
       str = l_str3.
      ELSE.
*       For other tags - write full info
   CALL METHOD add_str_var
     EXPORTING
       i_str    = c_html_comment_complex
       i_value1 = l_str1
       i_value2 = l_str2
       i_value3 = l_str3.
      ENDIF.
    ENDLOOP.

*   Close dictionary
    gr_html->add_tag_end( 'dl' ).
    CALL METHOD gr_html->flush_buffer.

  ENDMETHOD.          "do_write_comments


* Builds label for anchor for code unit. It can be used in 'a name' and
* 'a href' HTML tags.

  METHOD build_a_label_unit.

    DATA: l_type    TYPE t_unittype.
    DATA: l_typestr TYPE string.

    l_type = is_unit-type.
*   Class implementation change to class definition
    IF l_type = 'CI'.
      l_type = 'CD'.
    ENDIF.
    l_typestr = get_code_unit_type_desc( l_type ).

*   For methods we must include class name in an anchor
    IF l_type = 'M'.
      CONCATENATE l_typestr is_unit-clsname is_unit-name INTO e_label
                    SEPARATED BY space.
    ELSE.
      CONCATENATE l_typestr is_unit-name INTO e_label
                    SEPARATED BY space.
    ENDIF.

  ENDMETHOD.          "build_a_label_unit


* Builds label for anchor for class definition or interface.
* It can be used in 'a name' and 'a href' HTML tags.

  METHOD build_a_label_class_name.

    DATA: l_type    TYPE t_unittype.
    DATA: l_typestr TYPE string.

    l_type = 'CD'.
    IF i_clstype = '1'.
      l_type = 'I'.
    ENDIF.
    l_typestr = get_code_unit_type_desc( l_type ).

    CONCATENATE l_typestr i_clsname INTO e_label SEPARATED BY space.

  ENDMETHOD.          "build_a_label_class_name


* Builds label for anchor for class component.
* It can be used in 'a name' and 'a href' HTML tags.

  METHOD build_a_label_class_comp.

    DATA: l_typestr TYPE string.

    l_typestr = get_class_cmp_type_desc( is_cmp-cmptype ).
    CONCATENATE l_typestr is_cmp-clsname is_cmp-cmpname INTO e_label
                    SEPARATED BY space.

  ENDMETHOD.          "build_a_label_class_comp


* Adds to HTML document string after replacing varaibles @n@ (n=1..3)
* with provided value.

  METHOD add_str_var.

    DATA: str TYPE string.

    str = i_str.
    REPLACE ALL OCCURRENCES OF '@1@' IN str WITH i_value1.
    REPLACE ALL OCCURRENCES OF '@2@' IN str WITH i_value2.
    REPLACE ALL OCCURRENCES OF '@3@' IN str WITH i_value3.
    CALL METHOD gr_html->add_string_raw( str ).
    CALL METHOD gr_html->flush_buffer.

  ENDMETHOD.          "add_str_var

ENDCLASS.          "zcl_ic_code_analysis_html IMPLEMENTATION
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Russian ABAP Developer's Club Forum Index -> Project Management | Управление проектами, документация и стандарты All times are GMT + 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


All product names are trademarks of their respective companies. SAPNET.RU websites are in no way affiliated with SAP AG.
SAP, SAP R/3, R/3 software, mySAP, ABAP, BAPI, xApps, SAP NetWeaver and any other are registered trademarks of SAP AG.
Every effort is made to ensure content integrity. Use information on this site at your own risk.