diff --git a/src/zabapgit_css_common.w3mi.data.css b/src/zabapgit_css_common.w3mi.data.css index f81327870..924b1d664 100644 --- a/src/zabapgit_css_common.w3mi.data.css +++ b/src/zabapgit_css_common.w3mi.data.css @@ -503,6 +503,9 @@ table.diff_tab code { table.diff_tab code span.keyword { color: #0a69ce; } table.diff_tab code span.text { color: #48ce4f; } table.diff_tab code span.comment { color: #808080; font-style: italic; } +table.diff_tab code span.xml_tag { color: #3370e0; } +table.diff_tab code span.attr { color: #f20707; } +table.diff_tab code span.attr_val { color: #7a02f9; } table.diff_tab tbody tr:first-child td { padding-top: 0.5em; } table.diff_tab tbody tr:last-child td { padding-bottom: 0.5em; } diff --git a/src/zabapgit_page_diff.prog.abap b/src/zabapgit_page_diff.prog.abap index 0cab80365..79ed392c0 100644 --- a/src/zabapgit_page_diff.prog.abap +++ b/src/zabapgit_page_diff.prog.abap @@ -255,24 +255,21 @@ CLASS lcl_gui_page_diff IMPLEMENTATION. METHOD render_lines. - DATA: lo_highlighter TYPE REF TO lcl_code_highlighter, + DATA: lo_highlighter TYPE REF TO lcl_syntax_highlighter, lt_diffs TYPE lcl_diff=>ty_diffs_tt, lv_local TYPE string, lv_remote TYPE string, lv_lattr TYPE string, lv_rattr TYPE string, - lv_highlight TYPE abap_bool, lv_insert_nav TYPE abap_bool. FIELD-SYMBOLS LIKE LINE OF lt_diffs. - CREATE OBJECT lo_highlighter. + lo_highlighter = lcl_syntax_highlighter=>create( is_diff-filename ). CREATE OBJECT ro_html. lt_diffs = is_diff-o_diff->get( ). - lv_highlight = boolc( is_diff-filename CP '*.abap' ). - LOOP AT lt_diffs ASSIGNING . IF -short = abap_false. lv_insert_nav = abap_true. @@ -292,7 +289,7 @@ CLASS lcl_gui_page_diff IMPLEMENTATION. lv_remote = -old. ENDIF. - IF lv_highlight = abap_true. + IF lo_highlighter IS BOUND. lv_local = lo_highlighter->process_line( lv_local ). lv_remote = lo_highlighter->process_line( lv_remote ). ELSE. diff --git a/src/zabapgit_syntax_highlighter.prog.abap b/src/zabapgit_syntax_highlighter.prog.abap index 8ccef3149..c80816ab0 100644 --- a/src/zabapgit_syntax_highlighter.prog.abap +++ b/src/zabapgit_syntax_highlighter.prog.abap @@ -1,43 +1,30 @@ *&---------------------------------------------------------------------* *& Include ZABAPGIT_SYNTAX_HIGHLIGHTER *&---------------------------------------------------------------------* -*&---------------------------------------------------------------------* -*& Class lcl_code_highligher -*&---------------------------------------------------------------------* -CLASS ltcl_code_highlighter1 DEFINITION DEFERRED. -CLASS ltcl_code_highlighter2 DEFINITION DEFERRED. +CLASS ltcl_syntax_cases DEFINITION DEFERRED. +CLASS ltcl_syntax_basic_logic DEFINITION DEFERRED. + +CLASS lcl_syntax_abap DEFINITION DEFERRED. +CLASS lcl_syntax_xml DEFINITION DEFERRED. *----------------------------------------------------------------------* -* CLASS lcl_code_highlighter DEFINITION +* CLASS lcl_syntax_highlighter DEFINITION *----------------------------------------------------------------------* -CLASS lcl_code_highlighter DEFINITION FRIENDS ltcl_code_highlighter1 ltcl_code_highlighter2. +CLASS lcl_syntax_highlighter DEFINITION ABSTRACT + FRIENDS ltcl_syntax_cases ltcl_syntax_basic_logic. PUBLIC SECTION. - CLASS-METHODS: - class_constructor. - METHODS: - process_line + CLASS-METHODS create + IMPORTING iv_filename TYPE string + RETURNING VALUE(ro_instance) TYPE REF TO lcl_syntax_highlighter. + + METHODS process_line IMPORTING iv_line TYPE string RETURNING VALUE(rv_line) TYPE string. - PRIVATE SECTION. - CONSTANTS: - BEGIN OF c_token, - keyword TYPE c VALUE 'K', - text TYPE c VALUE 'T', - comment TYPE c VALUE 'C', - none TYPE c VALUE 'N', - END OF c_token. - - CONSTANTS: - BEGIN OF c_css, - keyword TYPE string VALUE 'keyword', - text TYPE string VALUE 'text', - comment TYPE string VALUE 'comment', - none TYPE string VALUE 'none', - END OF c_css. + PROTECTED SECTION. TYPES: BEGIN OF ty_match, @@ -51,73 +38,328 @@ CLASS lcl_code_highlighter DEFINITION FRIENDS ltcl_code_highlighter1 ltcl_code_h ty_match_tt TYPE STANDARD TABLE OF ty_match WITH DEFAULT KEY. TYPES: - BEGIN OF ty_regex, - regex TYPE REF TO cl_abap_regex, - token TYPE char1, - END OF ty_regex. + BEGIN OF ty_rule, + regex TYPE REF TO cl_abap_regex, + token TYPE char1, + style TYPE string, + END OF ty_rule. + + CONSTANTS c_token_none TYPE c VALUE '.'. + + DATA mt_rules TYPE STANDARD TABLE OF ty_rule. + + METHODS parse_line + IMPORTING iv_line TYPE string + EXPORTING et_matches TYPE ty_match_tt. + + METHODS order_matches ABSTRACT + IMPORTING iv_line TYPE string + CHANGING ct_matches TYPE ty_match_tt. + + METHODS extend_matches + IMPORTING iv_line TYPE string + CHANGING ct_matches TYPE ty_match_tt. + + METHODS format_line + IMPORTING iv_line TYPE string + it_matches TYPE ty_match_tt + RETURNING VALUE(rv_line) TYPE string. + + METHODS apply_style + IMPORTING iv_line TYPE string + iv_class TYPE string + RETURNING VALUE(rv_line) TYPE string. + +ENDCLASS. " lcl_syntax_highlighter DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_syntax_abap DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_syntax_abap DEFINITION INHERITING FROM lcl_syntax_highlighter FINAL. + + PUBLIC SECTION. + + CLASS-METHODS class_constructor. + METHODS constructor. + + CONSTANTS: + BEGIN OF c_css, + keyword TYPE string VALUE 'keyword', "#EC NOTEXT + text TYPE string VALUE 'text', "#EC NOTEXT + comment TYPE string VALUE 'comment', "#EC NOTEXT + END OF c_css, + + BEGIN OF c_token, + keyword TYPE c VALUE 'K', "#EC NOTEXT + text TYPE c VALUE 'T', "#EC NOTEXT + comment TYPE c VALUE 'C', "#EC NOTEXT + END OF c_token, - CLASS-DATA: BEGIN OF c_regex, - comment TYPE string, - text TYPE string, - keyword TYPE string, + comment TYPE string VALUE '##|"|^\*', + text TYPE string VALUE '`|''|\||\{|\}', + keyword TYPE string VALUE '&&|\b[-_a-z0-9]+\b', END OF c_regex. - CLASS-DATA: mo_regex_table TYPE TABLE OF ty_regex. + PROTECTED SECTION. - METHODS: - parse_line - IMPORTING iv_line TYPE string - RETURNING VALUE(rt_matches) TYPE ty_match_tt. + CLASS-DATA gt_keywords TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line. - METHODS: - order_matches - IMPORTING iv_line TYPE string - CHANGING ct_matches TYPE ty_match_tt. + CLASS-METHODS init_keywords. + CLASS-METHODS is_keyword + IMPORTING iv_chunk TYPE string + RETURNING VALUE(rv_yes) TYPE abap_bool. - METHODS: - format_line - IMPORTING iv_line TYPE string - it_matches TYPE ty_match_tt - RETURNING VALUE(rv_line) TYPE string. + METHODS order_matches REDEFINITION. + METHODS parse_line REDEFINITION. - METHODS: - apply_style - IMPORTING iv_line TYPE string - iv_class TYPE string - RETURNING VALUE(rv_line) TYPE string. - -ENDCLASS. "lcl_code_highlighter DEFINITION +ENDCLASS. " lcl_syntax_abap DEFINITION *----------------------------------------------------------------------* -* Macros +* CLASS lcl_syntax_xml DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_syntax_xml DEFINITION INHERITING FROM lcl_syntax_highlighter FINAL. + + PUBLIC SECTION. + + METHODS constructor. + + CONSTANTS: + BEGIN OF c_css, + xml_tag TYPE string VALUE 'xml_tag', "#EC NOTEXT + attr TYPE string VALUE 'attr', "#EC NOTEXT + attr_val TYPE string VALUE 'attr_val', "#EC NOTEXT + END OF c_css, + + BEGIN OF c_token, + xml_tag TYPE c VALUE 'X', "#EC NOTEXT + attr TYPE c VALUE 'A', "#EC NOTEXT + attr_val TYPE c VALUE 'V', "#EC NOTEXT + END OF c_token, + + BEGIN OF c_regex, + xml_tag TYPE string VALUE '[<>]', "#EC NOTEXT + attr TYPE string VALUE '\s[-a-z:_0-9]+\s*(?==)', "#EC NOTEXT + attr_val TYPE string VALUE '["''][^''"]+[''"]', "#EC NOTEXT + END OF c_regex. + + PROTECTED SECTION. + + METHODS order_matches REDEFINITION. + +ENDCLASS. " lcl_syntax_xml DEFINITION + +*----------------------------------------------------------------------* +* Macros to fill table with a regular expressions to be parsed *----------------------------------------------------------------------* -DEFINE _add_regex. +DEFINE _add_rule. - CREATE OBJECT ls_regex_table-regex + CREATE OBJECT ls_rule-regex EXPORTING pattern = c_regex-&1 ignore_case = abap_true. - ls_regex_table-token = c_token-&1. - APPEND ls_regex_table TO mo_regex_table. + ls_rule-token = c_token-&1. + ls_rule-style = c_css-&1. + APPEND ls_rule TO mt_rules. -END-OF-DEFINITION. +END-OF-DEFINITION. " _add_rule *----------------------------------------------------------------------* -* CLASS lcl_code_highlighter IMPLEMENTATION +* CLASS lcl_syntax_highlighter IMPLEMENTATION *----------------------------------------------------------------------* -CLASS lcl_code_highlighter IMPLEMENTATION. +* Implementation of syntax highligther for ABAP source code +*----------------------------------------------------------------------* + +CLASS lcl_syntax_highlighter IMPLEMENTATION. + + METHOD create. + + " Create instance of highighter dynamically dependent on syntax type + IF iv_filename CP '*.abap'. + CREATE OBJECT ro_instance TYPE lcl_syntax_abap. + ELSEIF iv_filename CP '*.xml'. + CREATE OBJECT ro_instance TYPE lcl_syntax_xml. + ELSE. + CLEAR ro_instance. + ENDIF. + + ENDMETHOD. " create. + + METHOD parse_line. + + DATA: + lo_regex TYPE REF TO cl_abap_regex, + lo_matcher TYPE REF TO cl_abap_matcher, + lt_result TYPE match_result_tab, + ls_match TYPE ty_match. + + FIELD-SYMBOLS: + LIKE LINE OF mt_rules, + TYPE match_result, + TYPE ty_match. + + CLEAR et_matches. + + " Process syntax-dependent regex table and find all matches + LOOP AT mt_rules ASSIGNING . + lo_regex = -regex. + lo_matcher = lo_regex->create_matcher( text = iv_line ). + lt_result = lo_matcher->find_all( ). + + " Save matches into custom table with predefined tokens + LOOP AT lt_result ASSIGNING . + CLEAR: ls_match. + ls_match-token = -token. + ls_match-offset = -offset. + ls_match-length = -length. + APPEND ls_match TO et_matches. + ENDLOOP. + ENDLOOP. + + ENDMETHOD. " parse_line + + METHOD extend_matches. + + DATA: + lv_line_len TYPE i, + lv_last_pos TYPE i VALUE 0, + lv_length TYPE i, + ls_match TYPE ty_match. + + FIELD-SYMBOLS TYPE ty_match. + + lv_line_len = strlen( iv_line ). + + SORT ct_matches BY offset. + + " Add entries refering to parts of text that should not be formatted + LOOP AT ct_matches ASSIGNING . + IF -offset > lv_last_pos. + lv_length = -offset - lv_last_pos. + ls_match-token = c_token_none. + ls_match-offset = lv_last_pos. + ls_match-length = lv_length. + INSERT ls_match INTO ct_matches INDEX sy-tabix. + ENDIF. + lv_last_pos = -offset + -length. + ENDLOOP. + + " Add remainder of the string + IF lv_line_len > lv_last_pos. + lv_length = lv_line_len - lv_last_pos. + ls_match-token = c_token_none. + ls_match-offset = lv_last_pos. + ls_match-length = lv_length. + APPEND ls_match TO ct_matches. + ENDIF. + + ENDMETHOD. " extend_matches + + METHOD format_line. + + DATA: + lv_chunk TYPE string, + ls_rule LIKE LINE OF mt_rules. + + FIELD-SYMBOLS TYPE ty_match. + + LOOP AT it_matches ASSIGNING . + lv_chunk = substring( val = iv_line off = -offset len = -length ). + + CLEAR ls_rule. " Failed read equals no style + READ TABLE mt_rules INTO ls_rule WITH KEY token = -token. + + lv_chunk = me->apply_style( iv_line = lv_chunk + iv_class = ls_rule-style ). + + rv_line = rv_line && lv_chunk. + ENDLOOP. + + ENDMETHOD. " format_line + + METHOD apply_style. + + DATA lv_escaped TYPE string. + + lv_escaped = escape( val = iv_line format = cl_abap_format=>e_html_attr ). + IF iv_class IS NOT INITIAL. + rv_line = |{ lv_escaped }|. + ELSE. + rv_line = lv_escaped. + ENDIF. + + ENDMETHOD. " apply_style + + METHOD process_line. + + DATA: lt_matches TYPE ty_match_tt. + + IF strlen( iv_line ) = 0. + RETURN. + ENDIF. + + me->parse_line( EXPORTING iv_line = iv_line + IMPORTING et_matches = lt_matches ). + + me->order_matches( EXPORTING iv_line = iv_line + CHANGING ct_matches = lt_matches ). + + me->extend_matches( EXPORTING iv_line = iv_line + CHANGING ct_matches = lt_matches ). + + rv_line = me->format_line( iv_line = iv_line + it_matches = lt_matches ). + + ENDMETHOD. " process_line + +ENDCLASS. " lcl_syntax_highlighter IMPLEMENTATION + +*----------------------------------------------------------------------* +* CLASS lcl_syntax_abap IMPLEMENTATION +*----------------------------------------------------------------------* +* Implementation of syntax highligther for XML source code +*----------------------------------------------------------------------* + +CLASS lcl_syntax_abap IMPLEMENTATION. METHOD class_constructor. - DATA: ls_regex_table TYPE ty_regex. + init_keywords( ). - c_regex-comment = '##|"|^\*'. - c_regex-text = '`|''|\||\{|\}'. - c_regex-keyword = '&&|\b(' && - '\*-INPUT|\?TO|ABAP-SOURCE|ABBREVIATED|ABS|ABSTRACT|ACCEPT|ACCEPTING|ACCESSPOLICY' && + ENDMETHOD. " class_constructor + + METHOD is_keyword. + + DATA lv_str TYPE string. + + lv_str = to_upper( iv_chunk ). + READ TABLE gt_keywords WITH KEY table_line = lv_str TRANSPORTING NO FIELDS. + rv_yes = boolc( sy-subrc = 0 ). + + ENDMETHOD. " is_keyword. + + METHOD constructor. + + DATA ls_rule LIKE LINE OF mt_rules. + + super->constructor( ). + + " Initialize instances of regular expression + _add_rule keyword. + _add_rule comment. + _add_rule text. + + ENDMETHOD. " constructor + + METHOD init_keywords. + + DATA: lv_keywords TYPE string, + lt_keywords TYPE STANDARD TABLE OF string. + + lv_keywords = + '&&|?TO|ABAP-SOURCE|ABBREVIATED|ABS|ABSTRACT|ACCEPT|ACCEPTING|ACCESSPOLICY' && '|ACCORDING|ACOS|ACTIVATION|ACTUAL|ADD|ADD-CORRESPONDING|ADJACENT|AFTER|ALIAS' && '|ALIASES|ALIGN|ALL|ALLOCATE|ALPHA|ANALYSIS|ANALYZER|AND|ANY|APPEND|APPENDAGE' && '|APPENDING|APPLICATION|ARCHIVE|AREA|ARITHMETIC|AS|ASCENDING|ASIN|ASPECT|ASSERT' && @@ -190,17 +432,18 @@ CLASS lcl_code_highlighter IMPLEMENTATION. '|REPLACEMENT|REPLACING|REPORT|REQUEST|REQUESTED|RESERVE|RESET|RESOLUTION' && '|RESPECTING|RESPONSIBLE|RESULT|RESULTS|RESUMABLE|RESUME|RETRY|RETURN|RETURNCODE' && '|RETURNING|RIGHT|RIGHT-JUSTIFIED|RIGHTPLUS|RIGHTSPACE|RISK|RMC_COMMUNICATION_FAILURE' && - '|RMC_INVALID_STATUS|RMC_SYSTEM_FAILURE|ROLE|ROLLBACK|ROUND|ROWS|RTTI|RUN|SAP|SAP-SPOOL' && - '|SAVING|SCALE_PRESERVING|SCALE_PRESERVING_SCIENTIFIC|SCAN|SCIENTIFIC|SCIENTIFIC_WITH_LEADING_ZERO' && - '|SCREEN|SCROLL|SCROLL-BOUNDARY|SCROLLING|SEARCH|SECONDARY|SECONDS|SECTION|SELECT|SELECTION' && - '|SELECTIONS|SELECTION-SCREEN|SELECTION-SET|SELECTION-SETS|SELECTION-TABLE|SELECT-OPTIONS' && - '|SELECTOR|SELECTOR|SEND|SEPARATE|SEPARATED|SET|SHARED|SHIFT|SHORT|SHORTDUMP-ID|SIGN' && - '|SIGN_AS_POSTFIX|SIMPLE|SIN|SINGLE|SINH|SIZE|SKIP|SKIPPING|SMART|SOME|SORT|SORTABLE' && - '|SORTED|SOURCE|SPACE|SPECIFIED|SPLIT|SPOOL|SPOTS|SQL|SQLSCRIPT|SQRT|STABLE|STAMP' && - '|STANDARD|STARTING|START-OF-SELECTION|STATE|STATEMENT|STATEMENTS|STATIC|STATICS|STATUSINFO' && - '|STEP-LOOP|STOP|STRLEN|STRUCTURE|STRUCTURES|STYLE|SUBKEY|SUBMATCHES|SUBMIT|SUBROUTINE' && - '|SUBSCREEN|SUBSTRING|SUBTRACT|SUBTRACT-CORRESPONDING|SUFFIX|SUM|SUMMARY|SUMMING|SUPPLIED' && - '|SUPPLY|SUPPRESS|SWITCH|SWITCHSTATES|SYMBOL|SYNCPOINTS|SYNTAX|SYNTAX-CHECK|SYNTAX-TRACE' && + '|RMC_INVALID_STATUS|RMC_SYSTEM_FAILURE|ROLE|ROLLBACK|ROUND|ROWS|RTTI|RUN|SAP' && + '|SAP-SPOOL|SAVING|SCALE_PRESERVING|SCALE_PRESERVING_SCIENTIFIC|SCAN|SCIENTIFIC' && + '|SCIENTIFIC_WITH_LEADING_ZERO|SCREEN|SCROLL|SCROLL-BOUNDARY|SCROLLING|SEARCH' && + '|SECONDARY|SECONDS|SECTION|SELECT|SELECTION|SELECTIONS|SELECTION-SCREEN|SELECTION-SET' && + '|SELECTION-SETS|SELECTION-TABLE|SELECT-OPTIONS|SELECTOR|SEND|SEPARATE|SEPARATED|SET' && + '|SHARED|SHIFT|SHORT|SHORTDUMP-ID|SIGN|SIGN_AS_POSTFIX|SIMPLE|SIN|SINGLE|SINH|SIZE' && + '|SKIP|SKIPPING|SMART|SOME|SORT|SORTABLE|SORTED|SOURCE|SPACE|SPECIFIED|SPLIT|SPOOL' && + '|SPOTS|SQL|SQLSCRIPT|SQRT|STABLE|STAMP|STANDARD|STARTING|START-OF-SELECTION|STATE' && + '|STATEMENT|STATEMENTS|STATIC|STATICS|STATUSINFO|STEP-LOOP|STOP|STRLEN|STRUCTURE' && + '|STRUCTURES|STYLE|SUBKEY|SUBMATCHES|SUBMIT|SUBROUTINE|SUBSCREEN|SUBSTRING|SUBTRACT' && + '|SUBTRACT-CORRESPONDING|SUFFIX|SUM|SUMMARY|SUMMING|SUPPLIED|SUPPLY|SUPPRESS|SWITCH' && + '|SWITCHSTATES|SYMBOL|SYNCPOINTS|SYNTAX|SYNTAX-CHECK|SYNTAX-TRACE' && '|SYSTEM-CALL|SYSTEM-EXCEPTIONS|SYSTEM-EXIT|TAB|TABBED|TABLE|TABLES|TABLEVIEW|TABSTRIP' && '|TAN|TANH|TARGET|TASK|TASKS|TEST|TESTING|TEXT|TEXTPOOL|THEN|THROW|TIME|TIMES|TIMESTAMP' && '|TIMEZONE|TITLE|TITLEBAR|TITLE-LINES|TO|TOKENIZATION|TOKENS|TOP-LINES|TOP-OF-PAGE' && @@ -210,58 +453,40 @@ CLASS lcl_code_highlighter IMPLEMENTATION. '|UNWIND|UP|UPDATE|UPPER|USER|USER-COMMAND|USING|UTF-8|VALID|VALUE|VALUE-REQUEST|VALUES' && '|VARY|VARYING|VERIFICATION-MESSAGE|VERSION|VIA|VIEW|VISIBLE|WAIT|WARNING|WHEN|WHENEVER' && '|WHERE|WHILE|WIDTH|WINDOW|WINDOWS|WITH|WITH-HEADING|WITHOUT|WITH-TITLE|WORD|WORK' && - '|WRITE|WRITER|X|XML|XOR|XSD|XSTRLEN|YELLOW|YES|YYMMDD|Z|ZERO|ZONE' && - ')\b'. + '|WRITE|WRITER|X|XML|XOR|XSD|XSTRLEN|YELLOW|YES|YYMMDD|Z|ZERO|ZONE'. - " Initialize instances of regular expressions - _add_regex keyword. - _add_regex comment. - _add_regex text. + SPLIT lv_keywords AT '|' INTO TABLE lt_keywords. + gt_keywords = lt_keywords. " Hash table - ENDMETHOD. "class_constructor + ENDMETHOD. " init_keywords - METHOD parse_line. + METHOD parse_line. "REDEFINITION - DATA: - lo_regex TYPE REF TO cl_abap_regex, - lo_matcher TYPE REF TO cl_abap_matcher, - lt_result TYPE match_result_tab, - ls_match TYPE ty_match. + DATA lv_index TYPE i. - FIELD-SYMBOLS: - TYPE ty_regex, - TYPE match_result, - TYPE ty_match. + FIELD-SYMBOLS LIKE LINE OF et_matches. - LOOP AT mo_regex_table ASSIGNING . - lo_regex = -regex. - lo_matcher = lo_regex->create_matcher( text = iv_line ). - lt_result = lo_matcher->find_all( ). + super->parse_line( EXPORTING iv_line = iv_line + IMPORTING et_matches = et_matches ). - LOOP AT lt_result ASSIGNING . - ls_match-token = -token. - ls_match-offset = -offset. - ls_match-length = -length. - - IF ls_match-token = c_token-text. - ls_match-text_tag = substring( val = iv_line off = ls_match-offset len = ls_match-length ). - ENDIF. - - APPEND ls_match TO rt_matches. - ENDLOOP. + " Remove non-keywords + LOOP AT et_matches ASSIGNING WHERE token = c_token-keyword. + lv_index = sy-tabix. + IF abap_false = is_keyword( substring( val = iv_line + off = -offset + len = -length ) ). + DELETE et_matches INDEX lv_index. + ENDIF. ENDLOOP. - ENDMETHOD. " parse_line + ENDMETHOD. " parse_line. METHOD order_matches. DATA: lv_index TYPE sy-tabix, lv_line_len TYPE i, - lv_prev_token TYPE c, - lv_last_pos TYPE i VALUE 0, - lv_length TYPE i, - ls_match TYPE ty_match. + lv_prev_token TYPE c. FIELD-SYMBOLS: TYPE ty_match, @@ -281,182 +506,205 @@ CLASS lcl_code_highlighter IMPLEMENTATION. ENDIF. CASE -token. + WHEN c_token-keyword. + IF -offset > 0. + " Delete match if keyword is part of structure or field symbol + IF substring( val = iv_line off = ( -offset - 1 ) len = 1 ) CA '-<'. + DELETE ct_matches INDEX lv_index. + CONTINUE. + ENDIF. + ENDIF. + WHEN c_token-comment. -length = lv_line_len - -offset. DELETE ct_matches FROM lv_index + 1. CONTINUE. + WHEN c_token-text. + -text_tag = substring( val = iv_line + off = -offset + len = -length ). IF lv_prev_token = c_token-text. IF -text_tag = -text_tag. -length = -offset + -length - -offset. CLEAR lv_prev_token. ELSEIF -text_tag = '}' AND -text_tag = '{'. - -length = -offset - -offset - 1. " Shifted } out of highlight - -offset = -offset + 1. " Shifted { out of highlight + -length = -offset - -offset - 1. " Shift } out of scope + -offset = -offset + 1. " Shift { out of scope CLEAR lv_prev_token. ELSEIF -text_tag = '{'. -length = -offset - -offset. CLEAR lv_prev_token. ELSEIF -text_tag = '}'. -length = -offset - -offset. - -offset = -offset + 1. " Shifted } out of highlight + -offset = -offset + 1. " Shift } out of scope CLEAR lv_prev_token. ENDIF. DELETE ct_matches INDEX lv_index. CONTINUE. ENDIF. + ENDCASE. lv_prev_token = -token. ASSIGN TO . ENDLOOP. - " Add entries refering to parts of text that should not be formatted - LOOP AT ct_matches ASSIGNING . - IF -offset > lv_last_pos. - lv_length = -offset - lv_last_pos. - ls_match-token = c_token-none. - ls_match-offset = lv_last_pos. - ls_match-length = lv_length. - INSERT ls_match INTO ct_matches INDEX sy-tabix. - ENDIF. - lv_last_pos = -offset + -length. - ENDLOOP. + ENDMETHOD. " order_matches. - " Add remainder of the string - IF lv_line_len > lv_last_pos. - lv_length = lv_line_len - lv_last_pos. - ls_match-token = c_token-none. - ls_match-offset = lv_last_pos. - ls_match-length = lv_length. - APPEND ls_match TO ct_matches. - ENDIF. +ENDCLASS. " lcl_syntax_abap IMPLEMENTATION - ENDMETHOD. " order_matches. +*----------------------------------------------------------------------* +* CLASS lcl_syntax_xml IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_syntax_xml IMPLEMENTATION. - METHOD format_line. + METHOD constructor. + + DATA ls_rule LIKE LINE OF mt_rules. + + super->constructor( ). + + " Initialize instances of regular expressions + _add_rule xml_tag. + _add_rule attr. + _add_rule attr_val. + + ENDMETHOD. + + METHOD order_matches. DATA: - lv_chunk TYPE string, - lv_css_class TYPE string. + lv_index TYPE sy-tabix, + lv_line_len TYPE i, + lv_prev_token TYPE c, + lv_state TYPE c VALUE 'O'. " O - for open tag; C - for closed tag; FIELD-SYMBOLS: - TYPE ty_match. + TYPE ty_match, + TYPE ty_match. - LOOP AT it_matches ASSIGNING . - lv_chunk = substring( val = iv_line off = -offset len = -length ). + SORT ct_matches BY offset. + + lv_line_len = strlen( iv_line ). + + LOOP AT ct_matches ASSIGNING . + lv_index = sy-tabix. CASE -token. - WHEN c_token-keyword. - lv_css_class = c_css-keyword. - WHEN c_token-comment. - lv_css_class = c_css-comment. - WHEN c_token-text. - lv_css_class = c_css-text. - WHEN c_token-none. - CLEAR: lv_css_class. + WHEN c_token-xml_tag. + -text_tag = substring( val = iv_line + off = -offset + len = -length ). + + " No other matches between two tags + IF -text_tag = '>' AND lv_prev_token = c_token-xml_tag. + lv_state = 'C'. + -length = -offset - -offset + -length. + DELETE ct_matches INDEX lv_index. + CONTINUE. + + " Adjust length and offset of closing tag + ELSEIF -text_tag = '>' AND lv_prev_token <> c_token-xml_tag. + lv_state = 'C'. + -length = -offset - -offset - -length + -length. + -offset = -offset + -length. + ELSE. + lv_state = 'O'. + ENDIF. + + WHEN OTHERS. + IF lv_prev_token = c_token-xml_tag. + -length = -offset - -offset. " Extend length of the opening tag + ENDIF. + + IF lv_state = 'C'. " Delete all matches between tags + DELETE ct_matches INDEX lv_index. + CONTINUE. + ENDIF. + ENDCASE. - lv_chunk = me->apply_style( iv_line = lv_chunk - iv_class = lv_css_class ). - - rv_line = rv_line && lv_chunk. + lv_prev_token = -token. + ASSIGN TO . ENDLOOP. - ENDMETHOD. "format_line + ENDMETHOD. " order_matches - METHOD apply_style. - - DATA lv_escaped TYPE string. - - lv_escaped = escape( val = iv_line format = cl_abap_format=>e_html_attr ). - IF iv_class IS NOT INITIAL. - rv_line = |{ lv_escaped }|. - ELSE. - rv_line = lv_escaped. - ENDIF. - - ENDMETHOD. "apply_style - - METHOD process_line. - - DATA: lt_matches TYPE ty_match_tt. - - IF strlen( iv_line ) = 0. - RETURN. - ENDIF. - - lt_matches = me->parse_line( iv_line ). - - me->order_matches( EXPORTING iv_line = iv_line - CHANGING ct_matches = lt_matches ). - - rv_line = me->format_line( iv_line = iv_line - it_matches = lt_matches ). - - ENDMETHOD. " process_line - -ENDCLASS. " lcl_code_highlighter IMPLEMENTATION +ENDCLASS. " lcl_syntax_xml IMPLEMENTATION *----------------------------------------------------------------------* -* CLASS ltcl_code_highlighter definition +* CLASS ltcl_syntax_cases definition *----------------------------------------------------------------------* -CLASS ltcl_code_highlighter1 DEFINITION FINAL +CLASS ltcl_syntax_cases DEFINITION FINAL FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. PRIVATE SECTION. DATA: - mo TYPE REF TO lcl_code_highlighter, - mt_after_parse TYPE lcl_code_highlighter=>ty_match_tt, - ms_match TYPE lcl_code_highlighter=>ty_match, - mt_after_order TYPE lcl_code_highlighter=>ty_match_tt. + mt_after_parse TYPE lcl_syntax_highlighter=>ty_match_tt, + mt_after_order TYPE lcl_syntax_highlighter=>ty_match_tt, + mt_after_extend TYPE lcl_syntax_highlighter=>ty_match_tt, + ms_match TYPE lcl_syntax_highlighter=>ty_match. METHODS: - setup, - test IMPORTING iv_line TYPE string, - test01 FOR TESTING, - test02 FOR TESTING, - test03 FOR TESTING, - test04 FOR TESTING, - test05 FOR TESTING, - test06 FOR TESTING, - test07 FOR TESTING. + do_test IMPORTING iv_line TYPE string + iv_filename TYPE string + RETURNING VALUE(ro_instance) TYPE REF TO lcl_syntax_highlighter, + test_abap_01 FOR TESTING, + test_abap_02 FOR TESTING, + test_abap_03 FOR TESTING, + test_abap_04 FOR TESTING, + test_abap_05 FOR TESTING, + test_abap_06 FOR TESTING, + test_abap_07 FOR TESTING, + test_abap_08 FOR TESTING, + test_xml_01 FOR TESTING, + test_xml_02 FOR TESTING, + test_xml_03 FOR TESTING, + test_xml_04 FOR TESTING, + test_xml_05 FOR TESTING. -ENDCLASS. " ltcl_code_highlighter +ENDCLASS. " ltcl_syntax_cases *----------------------------------------------------------------------* -* CLASS ltcl_code_highlighter IMPLEMENTATION +* CLASS ltcl_syntax_cases IMPLEMENTATION *----------------------------------------------------------------------* -CLASS ltcl_code_highlighter1 IMPLEMENTATION. +CLASS ltcl_syntax_cases IMPLEMENTATION. DEFINE _generate_parse. ms_match-token = &1. ms_match-offset = &2. ms_match-length = &3. - ms_match-text_tag = &4. - APPEND ms_match to mt_after_parse. - END-OF-DEFINITION. + append ms_match to mt_after_parse. + END-OF-DEFINITION. " _generate_parse DEFINE _generate_order. ms_match-token = &1. ms_match-offset = &2. ms_match-length = &3. ms_match-text_tag = &4. - APPEND ms_match to mt_after_order. - END-OF-DEFINITION. + append ms_match to mt_after_order. + END-OF-DEFINITION. " _generate_order - METHOD setup. - CREATE OBJECT mo. - CLEAR mt_after_parse. - CLEAR mt_after_order. - ENDMETHOD. " setup + DEFINE _generate_extend. + ms_match-token = &1. + ms_match-offset = &2. + ms_match-length = &3. + ms_match-text_tag = &4. + append ms_match to mt_after_extend. + END-OF-DEFINITION. " _generate_extend - METHOD test. + METHOD do_test. - DATA: lt_matches_act TYPE lcl_code_highlighter=>ty_match_tt. + DATA: lt_matches_act TYPE lcl_syntax_highlighter=>ty_match_tt, + lo TYPE REF TO lcl_syntax_highlighter. - lt_matches_act = mo->parse_line( iv_line ). + lo = lcl_syntax_highlighter=>create( iv_filename ). + lo->parse_line( EXPORTING iv_line = iv_line + IMPORTING et_matches = lt_matches_act ). SORT lt_matches_act BY offset. @@ -464,246 +712,471 @@ CLASS ltcl_code_highlighter1 IMPLEMENTATION. act = lt_matches_act msg = | Error during parsing: { iv_line }| ). - IF lines( mt_after_order ) > 0. - mo->order_matches( EXPORTING iv_line = iv_line - CHANGING ct_matches = lt_matches_act ). + lo->order_matches( EXPORTING iv_line = iv_line + CHANGING ct_matches = lt_matches_act ). - cl_abap_unit_assert=>assert_equals( exp = mt_after_order - act = lt_matches_act - msg = | Error during ordering: { iv_line }| ). - ENDIF. + cl_abap_unit_assert=>assert_equals( exp = mt_after_order + act = lt_matches_act + msg = | Error during ordering: { iv_line }| ). - ENDMETHOD. + lo->extend_matches( EXPORTING iv_line = iv_line + CHANGING ct_matches = lt_matches_act ). + cl_abap_unit_assert=>assert_equals( exp = mt_after_extend + act = lt_matches_act + msg = | Error during extending: { iv_line }| ). + + ENDMETHOD. "test ****************************************************** * Test parsing and ordering of comments * ****************************************************** - METHOD test01. + METHOD test_abap_01. - DATA: lv_line TYPE string. + DATA lv_line TYPE string. - lv_line = '* commented out line with key word data'. + lv_line = '* commented out line with key word data'. "#EC NOTEXT " Generate table with expected values after parsing - _generate_parse 'C' 0 1 ''. - _generate_parse 'K' 12 3 ''. - _generate_parse 'K' 16 4 ''. - _generate_parse 'K' 21 4 ''. - _generate_parse 'K' 26 3 ''. - _generate_parse 'K' 30 4 ''. - _generate_parse 'K' 35 4 ''. + _generate_parse 'C' 0 1. + _generate_parse 'K' 12 3. + _generate_parse 'K' 16 4. + _generate_parse 'K' 21 4. + _generate_parse 'K' 26 3. + _generate_parse 'K' 30 4. + _generate_parse 'K' 35 4. " Generate table with expected values after ordering _generate_order 'C' 0 39 ''. - test( lv_line ). + " Generate table with expected values after ordering + _generate_extend 'C' 0 39 ''. - ENDMETHOD. + do_test( iv_line = lv_line iv_filename = '*.abap' ). + + ENDMETHOD. " test_abap_01 ****************************************************** * Test parsing and ordering of remainder of string * ****************************************************** - METHOD test02. + METHOD test_abap_02. - DATA: lv_line TYPE string. + DATA lv_line TYPE string. - lv_line = 'data: lv_var_name type string.'. + lv_line = 'data: lv_var_name type string.'. "#EC NOTEXT " Generate table with expected values after parsing - _generate_parse 'K' 0 4 ''. - _generate_parse 'K' 18 4 ''. + _generate_parse 'K' 0 4. + _generate_parse 'K' 18 4. " Generate table with expected values after ordering _generate_order 'K' 0 4 ''. - _generate_order 'N' 4 14 ''. _generate_order 'K' 18 4 ''. - _generate_order 'N' 22 8 ''. - test( lv_line ). + " Generate table with expected values after extending + _generate_extend 'K' 0 4 ''. + _generate_extend '.' 4 14 ''. + _generate_extend 'K' 18 4 ''. + _generate_extend '.' 22 8 ''. - ENDMETHOD. + do_test( iv_line = lv_line iv_filename = '*.abap' ). + + ENDMETHOD. " test_abap_02 ****************************************************** * Test parsing and ordering of key words & texts * ****************************************************** - METHOD test03. + METHOD test_abap_03. - DATA: lv_line TYPE string. + DATA lv_line TYPE string. - lv_line = 'call function ''FM_NAME''. " Commented'. + + lv_line = 'call function ''FM_NAME''. " Commented'. "#EC NOTEXT " Generate table with expected values after parsing - _generate_parse 'K' 0 4 ''. - _generate_parse 'K' 5 8 ''. - _generate_parse 'T' 14 1 ''''. - _generate_parse 'T' 22 1 ''''. - _generate_parse 'C' 25 1 ''. + _generate_parse 'K' 0 4. + _generate_parse 'K' 5 8. + _generate_parse 'T' 14 1. + _generate_parse 'T' 22 1. + _generate_parse 'C' 25 1. " Generate table with expected values after ordering _generate_order 'K' 0 4 ''. - _generate_order 'N' 4 1 ''. _generate_order 'K' 5 8 ''. - _generate_order 'N' 13 1 ''. _generate_order 'T' 14 9 ''''. - _generate_order 'N' 23 2 ''. _generate_order 'C' 25 11 ''. - test( lv_line ). + " Generate table with expected values after extending + _generate_extend 'K' 0 4 ''. + _generate_extend '.' 4 1 ''. + _generate_extend 'K' 5 8 ''. + _generate_extend '.' 13 1 ''. + _generate_extend 'T' 14 9 ''''. + _generate_extend '.' 23 2 ''. + _generate_extend 'C' 25 11 ''. - ENDMETHOD. + do_test( iv_line = lv_line iv_filename = '*.abap' ). + + ENDMETHOD. " test_abap_03 ****************************************************** * Test parsing and ordering of key words in texts * ****************************************************** - METHOD test04. + METHOD test_abap_04. - DATA: lv_line TYPE string. + DATA lv_line TYPE string. - lv_line = 'constants: lc_var type string value ''simpletext data simpletext''.'. + lv_line = 'constants: lc_var type string value ''simpletext data simpletext''.'. "#EC NOTEXT " Generate table with expected values after parsing - _generate_parse 'K' 0 9 ''. - _generate_parse 'K' 18 4 ''. - _generate_parse 'K' 30 5 ''. - _generate_parse 'T' 36 1 ''''. - _generate_parse 'K' 48 4 ''. - _generate_parse 'T' 63 1 ''''. + _generate_parse 'K' 0 9. + _generate_parse 'K' 18 4. + _generate_parse 'K' 30 5. + _generate_parse 'T' 36 1. + _generate_parse 'K' 48 4. + _generate_parse 'T' 63 1. " Generate table with expected values after ordering _generate_order 'K' 0 9 ''. - _generate_order 'N' 9 9 ''. _generate_order 'K' 18 4 ''. - _generate_order 'N' 22 8 ''. _generate_order 'K' 30 5 ''. - _generate_order 'N' 35 1 ''. _generate_order 'T' 36 28 ''''. - _generate_order 'N' 64 1 ''. - test( lv_line ). + " Generate table with expected values after ordering + _generate_extend 'K' 0 9 ''. + _generate_extend '.' 9 9 ''. + _generate_extend 'K' 18 4 ''. + _generate_extend '.' 22 8 ''. + _generate_extend 'K' 30 5 ''. + _generate_extend '.' 35 1 ''. + _generate_extend 'T' 36 28 ''''. + _generate_extend '.' 64 1 ''. - ENDMETHOD. + do_test( iv_line = lv_line iv_filename = '*.abap' ). + + ENDMETHOD. " test_abap_04 ****************************************************** * Test parsing and ordering texts in curly brackets * ****************************************************** - METHOD test05. + METHOD test_abap_05. - DATA: lv_line TYPE string. + DATA lv_line TYPE string. - lv_line = 'a = |{ b }={ c }|.'. + lv_line = 'a = |{ b }={ c }|.'. "#EC NOTEXT " Generate table with expected values after parsing - _generate_parse 'T' 4 1 '|'. - _generate_parse 'T' 5 1 '{'. - _generate_parse 'T' 9 1 '}'. - _generate_parse 'T' 11 1 '{'. - _generate_parse 'K' 13 1 ''. - _generate_parse 'T' 15 1 '}'. - _generate_parse 'T' 16 1 '|'. + _generate_parse 'T' 4 1. + _generate_parse 'T' 5 1. + _generate_parse 'T' 9 1. + _generate_parse 'T' 11 1. + _generate_parse 'K' 13 1. + _generate_parse 'T' 15 1. + _generate_parse 'T' 16 1. " Generate table with expected values after ordering - _generate_order 'N' 0 4 ''. _generate_order 'T' 4 1 '|'. - _generate_order 'N' 5 5 ''. _generate_order 'T' 10 1 '}'. - _generate_order 'N' 11 2 ''. _generate_order 'K' 13 1 ''. - _generate_order 'N' 14 2 ''. _generate_order 'T' 16 1 '}'. - _generate_order 'N' 17 1 ''. - test( lv_line ). + " Generate table with expected values after extending + _generate_extend '.' 0 4 ''. + _generate_extend 'T' 4 1 '|'. + _generate_extend '.' 5 5 ''. + _generate_extend 'T' 10 1 '}'. + _generate_extend '.' 11 2 ''. + _generate_extend 'K' 13 1 ''. + _generate_extend '.' 14 2 ''. + _generate_extend 'T' 16 1 '}'. + _generate_extend '.' 17 1 ''. - ENDMETHOD. + do_test( iv_line = lv_line iv_filename = '*.abap' ). + + ENDMETHOD. " test_abap_05 ****************************************************** * Test parsing and ordering of texts * ****************************************************** - METHOD test06. + METHOD test_abap_06. - DATA: lv_line TYPE string. + DATA lv_line TYPE string. - lv_line = 'lv_line = lc_constant && |XYZ { ''ab'' && |ac{ ''UU'' }| }|'. + lv_line = 'lv_line = lc_constant && |XYZ { ''ab'' && |ac{ ''UU'' }| }|'. "#EC NOTEXT " Generate table with expected values after parsing - _generate_parse 'K' 22 2 ''. - _generate_parse 'T' 25 1 '|'. - _generate_parse 'T' 30 1 '{'. - _generate_parse 'T' 32 1 ''''. - _generate_parse 'T' 35 1 ''''. - _generate_parse 'K' 37 2 ''. - _generate_parse 'T' 40 1 '|'. - _generate_parse 'T' 43 1 '{'. - _generate_parse 'T' 45 1 ''''. - _generate_parse 'T' 48 1 ''''. - _generate_parse 'T' 50 1 '}'. - _generate_parse 'T' 51 1 '|'. - _generate_parse 'T' 53 1 '}'. - _generate_parse 'T' 54 1 '|'. + _generate_parse 'K' 22 2. + _generate_parse 'T' 25 1. + _generate_parse 'T' 30 1. + _generate_parse 'T' 32 1. + _generate_parse 'T' 35 1. + _generate_parse 'K' 37 2. + _generate_parse 'T' 40 1. + _generate_parse 'T' 43 1. + _generate_parse 'T' 45 1. + _generate_parse 'T' 48 1. + _generate_parse 'T' 50 1. + _generate_parse 'T' 51 1. + _generate_parse 'T' 53 1. + _generate_parse 'T' 54 1. " Generate table with expected values after ordering - _generate_order 'N' 00 22 ''. _generate_order 'K' 22 2 ''. - _generate_order 'N' 24 1 ''. _generate_order 'T' 25 5 '|'. - _generate_order 'N' 30 2 ''. _generate_order 'T' 32 4 ''''. - _generate_order 'N' 36 1 ''. _generate_order 'K' 37 2 ''. - _generate_order 'N' 39 1 ''. _generate_order 'T' 40 3 '|'. - _generate_order 'N' 43 2 ''. _generate_order 'T' 45 4 ''''. - _generate_order 'N' 49 2 ''. _generate_order 'T' 51 1 '}'. - _generate_order 'N' 52 2 ''. _generate_order 'T' 54 1 '}'. - test( lv_line ). + " Generate table with expected values after extending + _generate_extend '.' 00 22 ''. + _generate_extend 'K' 22 2 ''. + _generate_extend '.' 24 1 ''. + _generate_extend 'T' 25 5 '|'. + _generate_extend '.' 30 2 ''. + _generate_extend 'T' 32 4 ''''. + _generate_extend '.' 36 1 ''. + _generate_extend 'K' 37 2 ''. + _generate_extend '.' 39 1 ''. + _generate_extend 'T' 40 3 '|'. + _generate_extend '.' 43 2 ''. + _generate_extend 'T' 45 4 ''''. + _generate_extend '.' 49 2 ''. + _generate_extend 'T' 51 1 '}'. + _generate_extend '.' 52 2 ''. + _generate_extend 'T' 54 1 '}'. - ENDMETHOD. + do_test( iv_line = lv_line iv_filename = '*.abap' ). - METHOD test07. + ENDMETHOD. " test_abap_06 - DATA: lv_line TYPE string. +******************************************************** +* Check that '*' in select statement is not a match * +******************************************************** + METHOD test_abap_07. - lv_line = 'SELECT * FROM foo'. + DATA lv_line TYPE string. + + lv_line = 'SELECT * FROM foo'. "#EC NOTEXT " Generate table with expected values after parsing - _generate_parse 'K' 0 6 ''. - _generate_parse 'K' 9 4 ''. + _generate_parse 'K' 0 6. + _generate_parse 'K' 9 4. - test( lv_line ). + " Generate table with expected values after ordering + _generate_order 'K' 0 6 ''. + _generate_order 'K' 9 4 ''. - ENDMETHOD. + " Generate table with expected values after extending + _generate_extend 'K' 0 6 ''. + _generate_extend '.' 6 3 ''. + _generate_extend 'K' 9 4 ''. + _generate_extend '.' 13 4 ''. -ENDCLASS. + do_test( iv_line = lv_line iv_filename = '*.abap' ). -CLASS ltcl_code_highlighter2 DEFINITION FINAL + ENDMETHOD. " test_abap_07 + +******************************************************** +* Test parsing and ordering of key words in structures * +******************************************************** + METHOD test_abap_08. + + DATA lv_line TYPE string. + + lv_line = 'lv_length = -length.'. "#EC NOTEXT + + " Generate table with expected values after parsing + _generate_parse 'K' 13 5. + _generate_parse 'K' 20 6. + + " Generate table with expected values after extending + _generate_extend '.' 0 27 ''. + + do_test( iv_line = lv_line iv_filename = '*.abap' ). + + ENDMETHOD. " test_abap_08 + +******************************************************** +* Test parsing and ordering of tags in xml * +******************************************************** + METHOD test_xml_01. + + DATA lv_line TYPE string. + + lv_line = 'Text'. "#EC NOTEXT + + " Generate table with expected values after parsing + _generate_parse 'X' 0 1. + _generate_parse 'X' 4 1. + _generate_parse 'X' 9 1. + _generate_parse 'X' 14 1. + + " Generate table with expected values after ordering + _generate_order 'X' 0 5 '<'. + _generate_order 'X' 9 6 '<'. + + " Generate table with expected values after extending + _generate_extend 'X' 0 5 '<'. + _generate_extend '.' 5 4 ''. + _generate_extend 'X' 9 6 '<'. + + do_test( iv_line = lv_line iv_filename = '*.xml' ). + + ENDMETHOD. " test_xml_01 + + METHOD test_xml_02. + + DATA lv_line TYPE string. + + lv_line = ''. "#EC NOTEXT + + " Generate table with expected values after parsing + _generate_parse 'X' 0 1. + _generate_parse 'X' 5 1. + + " Generate table with expected values after ordering + _generate_order 'X' 0 6 '<'. + + " Generate table with expected values after extending + _generate_extend 'X' 0 6 '<'. + + do_test( iv_line = lv_line iv_filename = '*.xml' ). + + ENDMETHOD. " test_xml_02 + + METHOD test_xml_03. + + DATA lv_line TYPE string. + + lv_line = ''. "#EC NOTEXT + + " Generate table with expected values after parsing + _generate_parse 'X' 0 1. + _generate_parse 'A' 4 10. + _generate_parse 'V' 15 7. + _generate_parse 'X' 23 1. + + " Generate table with expected values after ordering + _generate_order 'X' 0 4 '<'. + _generate_order 'A' 4 10 ''. + _generate_order 'V' 15 7 ''. + _generate_order 'X' 22 2 '>'. + + " Generate table with expected values after extending + _generate_extend 'X' 0 4 '<'. + _generate_extend 'A' 4 10 ''. + _generate_extend '.' 14 1 ''. + _generate_extend 'V' 15 7 ''. + _generate_extend 'X' 22 2 '>'. + + do_test( iv_line = lv_line iv_filename = '*.xml' ). + + ENDMETHOD. " test_xml_03 + + METHOD test_xml_04. + + DATA lv_line TYPE string. + + lv_line = ''. "#EC NOTEXT + + " Generate table with expected values after parsing + _generate_parse 'X' 0 1. + _generate_parse 'A' 5 8. + _generate_parse 'V' 14 5. + _generate_parse 'X' 20 1. + + " Generate table with expected values after ordering + _generate_order 'X' 0 5 '<'. + _generate_order 'A' 5 8 ''. + _generate_order 'V' 14 5 ''. + _generate_order 'X' 19 2 '>'. + + " Generate table with expected values after extending + _generate_extend 'X' 0 5 '<'. + _generate_extend 'A' 5 8 ''. + _generate_extend '.' 13 1 ''. + _generate_extend 'V' 14 5 ''. + _generate_extend 'X' 19 2 '>'. + + do_test( iv_line = lv_line iv_filename = '*.xml' ). + + ENDMETHOD. " test_xml_04 + + METHOD test_xml_05. + + DATA lv_line TYPE string. + + lv_line = '"text"'. "#EC NOTEXT + + " Generate table with expected values after parsing + _generate_parse 'X' 0 1. + _generate_parse 'A' 7 6. + _generate_parse 'V' 14 4. + _generate_parse 'A' 18 6. + _generate_parse 'V' 25 4. + _generate_parse 'X' 29 1. + _generate_parse 'V' 30 6. + _generate_parse 'X' 36 1. + _generate_parse 'X' 44 1. + + " Generate table with expected values after ordering + _generate_order 'X' 0 7 '<'. + _generate_order 'A' 7 6 ''. + _generate_order 'V' 14 4 ''. + _generate_order 'A' 18 6 ''. + _generate_order 'V' 25 4 ''. + _generate_order 'X' 29 1 '>'. + _generate_order 'X' 36 9 '<'. + + " Generate table with expected values after extending + _generate_extend 'X' 0 7 '<'. + _generate_extend 'A' 7 6 ''. + _generate_extend '.' 13 1 ''. + _generate_extend 'V' 14 4 ''. + _generate_extend 'A' 18 6 ''. + _generate_extend '.' 24 1 ''. + _generate_extend 'V' 25 4 ''. + _generate_extend 'X' 29 1 '>'. + _generate_extend '.' 30 6 ''. + _generate_extend 'X' 36 9 '<'. + + do_test( iv_line = lv_line iv_filename = '*.xml' ). + + ENDMETHOD. " test_xml_05 + +ENDCLASS. " ltcl_syntax_cases IMPLEMENTATION + +*----------------------------------------------------------------------* +* CLASS ltcl_syntax_basic_logic DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS ltcl_syntax_basic_logic DEFINITION FINAL FOR TESTING RISK LEVEL HARMLESS DURATION SHORT. PRIVATE SECTION. - DATA: - mo TYPE REF TO lcl_code_highlighter. + DATA mo TYPE REF TO lcl_syntax_highlighter. - METHODS: setup. - METHODS: process_line FOR TESTING. - METHODS: format_line FOR TESTING. - METHODS: apply_style FOR TESTING. + METHODS: + setup, + process_line FOR TESTING, + format_line FOR TESTING, + apply_style FOR TESTING. -ENDCLASS. " ltcl_code_highlighter +ENDCLASS. " ltcl_syntax_basic_logic *----------------------------------------------------------------------* -* CLASS ltcl_code_highlighter IMPLEMENTATION +* CLASS ltcl_syntax_highlighter IMPLEMENTATION *----------------------------------------------------------------------* -CLASS ltcl_code_highlighter2 IMPLEMENTATION. - +CLASS ltcl_syntax_basic_logic IMPLEMENTATION. METHOD setup. - CREATE OBJECT mo. - ENDMETHOD. + mo = lcl_syntax_highlighter=>create( '*.abap' ). + ENDMETHOD. " setup METHOD format_line. @@ -712,15 +1185,15 @@ CLASS ltcl_code_highlighter2 IMPLEMENTATION. lv_line_act TYPE string, lv_line_exp TYPE string. - lv_line = 'call function ''FM_NAME''. " Commented'. + lv_line = 'call function ''FM_NAME''. " Commented'. "#EC NOTEXT lv_line_exp = - 'call' && - ' function' && - ' 'FM_NAME'.' && - ' " Commented'. + 'call' && "#EC NOTEXT + ' function' && "#EC NOTEXT + ' 'FM_NAME'.' && "#EC NOTEXT + ' " Commented'. "#EC NOTEXT - lv_line_act = mo->process_line( lv_line ). + lv_line_act = mo->process_line( iv_line = lv_line ). cl_abap_unit_assert=>assert_equals( exp = lv_line_exp act = lv_line_act @@ -729,35 +1202,40 @@ CLASS ltcl_code_highlighter2 IMPLEMENTATION. ENDMETHOD. " format_line METHOD apply_style. - DATA: - lv_line_act TYPE string. + + DATA lv_line_act TYPE string. " Call the method and compare results - lv_line_act = mo->apply_style( iv_line = 'CALL FUNCTION' - iv_class = lcl_code_highlighter=>c_css-keyword ). + lv_line_act = mo->apply_style( iv_line = 'CALL FUNCTION' "#EC NOTEXT + iv_class = lcl_syntax_abap=>c_css-keyword ). + + cl_abap_unit_assert=>assert_equals( + act = lv_line_act + exp = 'CALL FUNCTION' "#EC NOTEXT + msg = 'Failure during applying of style.' ). "#EC NOTEXT - cl_abap_unit_assert=>assert_equals( act = lv_line_act - exp = 'CALL FUNCTION' - msg = 'Failure during applying of style.' ). ENDMETHOD. " apply_style METHOD process_line. - DATA: - lv_line_act TYPE string. + + DATA lv_line_act TYPE string. " Call the method with empty parameter and compare results lv_line_act = mo->process_line( iv_line = '' ). - cl_abap_unit_assert=>assert_equals( act = lv_line_act - exp = '' - msg = 'Failure in method process_line.' ). + cl_abap_unit_assert=>assert_equals( + act = lv_line_act + exp = '' + msg = 'Failure in method process_line.' ). "#EC NOTEXT " Call the method with non-empty line and compare results - lv_line_act = mo->process_line( iv_line = '* CALL FUNCTION' ). + lv_line_act = mo->process_line( iv_line = '* CALL FUNCTION' ). "#EC NOTEXT + + cl_abap_unit_assert=>assert_equals( + act = lv_line_act + exp = '* CALL FUNCTION' "#EC NOTEXT + msg = 'Failure in method process_line.' ). "#EC NOTEXT - cl_abap_unit_assert=>assert_equals( act = lv_line_act - exp = '* CALL FUNCTION' - msg = 'Failure in method process_line.' ). ENDMETHOD. " process_line -ENDCLASS. " ltcl_code_highlighter \ No newline at end of file +ENDCLASS. " ltcl_syntax_highlighter \ No newline at end of file