mirror of
https://github.com/abapGit/abapGit.git
synced 2025-05-02 13:03:01 +08:00
* fixed issue #1799 (dump for < or > in attributes) * added unit tests and extended support
This commit is contained in:
parent
30a11218f9
commit
af8a7abb9c
|
@ -30,9 +30,10 @@ CLASS zcl_abapgit_syntax_highlighter DEFINITION
|
||||||
|
|
||||||
TYPES:
|
TYPES:
|
||||||
BEGIN OF ty_rule,
|
BEGIN OF ty_rule,
|
||||||
regex TYPE REF TO cl_abap_regex,
|
regex TYPE REF TO cl_abap_regex,
|
||||||
token TYPE char1,
|
token TYPE char1,
|
||||||
style TYPE string,
|
style TYPE string,
|
||||||
|
relevant_submatch TYPE i,
|
||||||
END OF ty_rule.
|
END OF ty_rule.
|
||||||
|
|
||||||
CONSTANTS c_token_none TYPE c VALUE '.'.
|
CONSTANTS c_token_none TYPE c VALUE '.'.
|
||||||
|
@ -41,9 +42,10 @@ CLASS zcl_abapgit_syntax_highlighter DEFINITION
|
||||||
|
|
||||||
METHODS add_rule
|
METHODS add_rule
|
||||||
IMPORTING
|
IMPORTING
|
||||||
iv_regex TYPE string
|
iv_regex TYPE string
|
||||||
iv_token TYPE c
|
iv_token TYPE c
|
||||||
iv_style TYPE string.
|
iv_style TYPE string
|
||||||
|
iv_submatch TYPE i OPTIONAL.
|
||||||
|
|
||||||
METHODS parse_line
|
METHODS parse_line
|
||||||
IMPORTING iv_line TYPE string
|
IMPORTING iv_line TYPE string
|
||||||
|
@ -66,12 +68,11 @@ CLASS zcl_abapgit_syntax_highlighter DEFINITION
|
||||||
IMPORTING iv_line TYPE string
|
IMPORTING iv_line TYPE string
|
||||||
iv_class TYPE string
|
iv_class TYPE string
|
||||||
RETURNING VALUE(rv_line) TYPE string.
|
RETURNING VALUE(rv_line) TYPE string.
|
||||||
|
|
||||||
ENDCLASS.
|
ENDCLASS.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CLASS ZCL_ABAPGIT_SYNTAX_HIGHLIGHTER IMPLEMENTATION.
|
CLASS zcl_abapgit_syntax_highlighter IMPLEMENTATION.
|
||||||
|
|
||||||
|
|
||||||
METHOD add_rule.
|
METHOD add_rule.
|
||||||
|
@ -83,8 +84,9 @@ CLASS ZCL_ABAPGIT_SYNTAX_HIGHLIGHTER IMPLEMENTATION.
|
||||||
pattern = iv_regex
|
pattern = iv_regex
|
||||||
ignore_case = abap_true.
|
ignore_case = abap_true.
|
||||||
|
|
||||||
ls_rule-token = iv_token.
|
ls_rule-token = iv_token.
|
||||||
ls_rule-style = iv_style.
|
ls_rule-style = iv_style.
|
||||||
|
ls_rule-relevant_submatch = iv_submatch.
|
||||||
APPEND ls_rule TO mt_rules.
|
APPEND ls_rule TO mt_rules.
|
||||||
|
|
||||||
ENDMETHOD.
|
ENDMETHOD.
|
||||||
|
@ -188,7 +190,8 @@ CLASS ZCL_ABAPGIT_SYNTAX_HIGHLIGHTER IMPLEMENTATION.
|
||||||
|
|
||||||
FIELD-SYMBOLS:
|
FIELD-SYMBOLS:
|
||||||
<ls_regex> LIKE LINE OF mt_rules,
|
<ls_regex> LIKE LINE OF mt_rules,
|
||||||
<ls_result> TYPE match_result.
|
<ls_result> TYPE match_result,
|
||||||
|
<ls_submatch> LIKE LINE OF <ls_result>-submatches.
|
||||||
|
|
||||||
|
|
||||||
CLEAR et_matches.
|
CLEAR et_matches.
|
||||||
|
@ -202,10 +205,21 @@ CLASS ZCL_ABAPGIT_SYNTAX_HIGHLIGHTER IMPLEMENTATION.
|
||||||
" Save matches into custom table with predefined tokens
|
" Save matches into custom table with predefined tokens
|
||||||
LOOP AT lt_result ASSIGNING <ls_result>.
|
LOOP AT lt_result ASSIGNING <ls_result>.
|
||||||
CLEAR: ls_match.
|
CLEAR: ls_match.
|
||||||
ls_match-token = <ls_regex>-token.
|
IF <ls_regex>-relevant_submatch = 0.
|
||||||
ls_match-offset = <ls_result>-offset.
|
ls_match-token = <ls_regex>-token.
|
||||||
ls_match-length = <ls_result>-length.
|
ls_match-offset = <ls_result>-offset.
|
||||||
APPEND ls_match TO et_matches.
|
ls_match-length = <ls_result>-length.
|
||||||
|
APPEND ls_match TO et_matches.
|
||||||
|
ELSE.
|
||||||
|
READ TABLE <ls_result>-submatches ASSIGNING <ls_submatch> INDEX <ls_regex>-relevant_submatch.
|
||||||
|
"submatch might be empty if only discarted parts matched
|
||||||
|
IF sy-subrc = 0 and <ls_submatch>-offset >= 0 and <ls_submatch>-length > 0.
|
||||||
|
ls_match-token = <ls_regex>-token.
|
||||||
|
ls_match-offset = <ls_submatch>-offset.
|
||||||
|
ls_match-length = <ls_submatch>-length.
|
||||||
|
APPEND ls_match TO et_matches.
|
||||||
|
ENDIF.
|
||||||
|
ENDIF.
|
||||||
ENDLOOP.
|
ENDLOOP.
|
||||||
ENDLOOP.
|
ENDLOOP.
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,10 @@ CLASS ltcl_syntax_cases DEFINITION FINAL FOR TESTING RISK LEVEL HARMLESS
|
||||||
test_xml_02 FOR TESTING,
|
test_xml_02 FOR TESTING,
|
||||||
test_xml_03 FOR TESTING,
|
test_xml_03 FOR TESTING,
|
||||||
test_xml_04 FOR TESTING,
|
test_xml_04 FOR TESTING,
|
||||||
test_xml_05 FOR TESTING.
|
test_xml_05 FOR TESTING,
|
||||||
|
test_xml_06 FOR TESTING,
|
||||||
|
test_xml_07 FOR TESTING,
|
||||||
|
test_xml_08 FOR TESTING.
|
||||||
|
|
||||||
ENDCLASS.
|
ENDCLASS.
|
||||||
*----------------------------------------------------------------------*
|
*----------------------------------------------------------------------*
|
||||||
|
@ -515,6 +518,87 @@ CLASS ltcl_syntax_cases IMPLEMENTATION.
|
||||||
|
|
||||||
ENDMETHOD.
|
ENDMETHOD.
|
||||||
|
|
||||||
|
METHOD test_xml_06.
|
||||||
|
DATA lv_line TYPE string.
|
||||||
|
|
||||||
|
"unclosed tag
|
||||||
|
lv_line = '<ns:tag ns:a1="v1"'. "#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 table with expected values after ordering
|
||||||
|
_generate_order 'X' 0 7 '<'.
|
||||||
|
_generate_order 'A' 7 6 ''.
|
||||||
|
_generate_order 'V' 14 4 ''.
|
||||||
|
|
||||||
|
" 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 ''.
|
||||||
|
|
||||||
|
do_test( iv_line = lv_line iv_filename = '*.xml' ).
|
||||||
|
ENDMETHOD.
|
||||||
|
|
||||||
|
METHOD test_xml_07.
|
||||||
|
"invalid XML characters in a string
|
||||||
|
DATA lv_line TYPE string.
|
||||||
|
|
||||||
|
"xml special characters in attribute
|
||||||
|
lv_line = '<tag attribute=" '' > "/>'. "#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.
|
||||||
|
|
||||||
|
|
||||||
|
METHOD test_xml_08.
|
||||||
|
"invalid XML characters in a string
|
||||||
|
DATA lv_line TYPE string.
|
||||||
|
|
||||||
|
"attribute at beginning of line
|
||||||
|
lv_line = 'attribute=''>" '''. "#EC NOTEXT
|
||||||
|
|
||||||
|
" Generate table with expected values after parsing
|
||||||
|
_generate_parse 'A' 0 9.
|
||||||
|
_generate_parse 'V' 10 5.
|
||||||
|
|
||||||
|
" Generate table with expected values after ordering
|
||||||
|
_generate_order 'A' 0 9 ''.
|
||||||
|
_generate_order 'V' 10 5 ''.
|
||||||
|
|
||||||
|
" Generate table with expected values after extending
|
||||||
|
_generate_extend 'A' 0 9 ''.
|
||||||
|
_generate_extend '.' 9 1 ''.
|
||||||
|
_generate_extend 'V' 10 5 ''.
|
||||||
|
|
||||||
|
do_test( iv_line = lv_line iv_filename = '*.xml' ).
|
||||||
|
|
||||||
|
ENDMETHOD.
|
||||||
|
|
||||||
ENDCLASS.
|
ENDCLASS.
|
||||||
|
|
||||||
CLASS ltcl_syntax_basic_logic DEFINITION DEFERRED.
|
CLASS ltcl_syntax_basic_logic DEFINITION DEFERRED.
|
||||||
|
|
|
@ -19,9 +19,11 @@ CLASS zcl_abapgit_syntax_xml DEFINITION
|
||||||
END OF c_token .
|
END OF c_token .
|
||||||
CONSTANTS:
|
CONSTANTS:
|
||||||
BEGIN OF c_regex,
|
BEGIN OF c_regex,
|
||||||
xml_tag TYPE string VALUE '[<>]', "#EC NOTEXT
|
"for XML tags, we will use a submatch
|
||||||
attr TYPE string VALUE '\s[-a-z:_0-9]+\s*(?==)', "#EC NOTEXT
|
" main pattern includes quoted strings so we can ignore < and > in attr values
|
||||||
attr_val TYPE string VALUE '["''][^''"]*[''"]', "#EC NOTEXT
|
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 .
|
END OF c_regex .
|
||||||
|
|
||||||
METHODS constructor .
|
METHODS constructor .
|
||||||
|
@ -42,9 +44,10 @@ CLASS zcl_abapgit_syntax_xml IMPLEMENTATION.
|
||||||
|
|
||||||
" Initialize instances of regular expressions
|
" Initialize instances of regular expressions
|
||||||
|
|
||||||
add_rule( iv_regex = c_regex-xml_tag
|
add_rule( iv_regex = c_regex-xml_tag
|
||||||
iv_token = c_token-xml_tag
|
iv_token = c_token-xml_tag
|
||||||
iv_style = c_css-xml_tag ).
|
iv_style = c_css-xml_tag
|
||||||
|
iv_submatch = 1 ).
|
||||||
|
|
||||||
add_rule( iv_regex = c_regex-attr
|
add_rule( iv_regex = c_regex-attr
|
||||||
iv_token = c_token-attr
|
iv_token = c_token-attr
|
||||||
|
@ -114,5 +117,18 @@ CLASS zcl_abapgit_syntax_xml IMPLEMENTATION.
|
||||||
ASSIGN <ls_match> TO <ls_prev>.
|
ASSIGN <ls_match> TO <ls_prev>.
|
||||||
ENDLOOP.
|
ENDLOOP.
|
||||||
|
|
||||||
|
"if the last XML tag is not closed, extend it to the end of the tag
|
||||||
|
IF lv_prev_token = c_token-xml_tag
|
||||||
|
AND <ls_prev> IS ASSIGNED
|
||||||
|
AND <ls_prev>-length = 1
|
||||||
|
AND <ls_prev>-text_tag = '<'.
|
||||||
|
|
||||||
|
FIND REGEX '<\s*[^\s]*' IN iv_line+<ls_prev>-offset MATCH LENGTH <ls_prev>-length.
|
||||||
|
IF sy-subrc <> 0.
|
||||||
|
<ls_prev>-length = 1.
|
||||||
|
ENDIF.
|
||||||
|
|
||||||
|
ENDIF.
|
||||||
|
|
||||||
ENDMETHOD.
|
ENDMETHOD.
|
||||||
ENDCLASS.
|
ENDCLASS.
|
||||||
|
|
|
@ -11,7 +11,9 @@ CLASS abapgit_syntax_xml DEFINITION FINAL FOR TESTING
|
||||||
sole_closing_xml_tag FOR TESTING RAISING cx_static_check,
|
sole_closing_xml_tag FOR TESTING RAISING cx_static_check,
|
||||||
complete_xml_tag FOR TESTING RAISING cx_static_check,
|
complete_xml_tag FOR TESTING RAISING cx_static_check,
|
||||||
complete_xml_tag_with_closing FOR TESTING RAISING cx_static_check,
|
complete_xml_tag_with_closing FOR TESTING RAISING cx_static_check,
|
||||||
empty_attributes FOR TESTING RAISING cx_static_check.
|
empty_attributes FOR TESTING RAISING cx_static_check,
|
||||||
|
open_tags FOR TESTING RAISING cx_static_check,
|
||||||
|
attributes_only FOR TESTING RAISING cx_static_check.
|
||||||
|
|
||||||
ENDCLASS.
|
ENDCLASS.
|
||||||
|
|
||||||
|
@ -63,4 +65,39 @@ CLASS abapgit_syntax_xml IMPLEMENTATION.
|
||||||
|
|
||||||
ENDMETHOD.
|
ENDMETHOD.
|
||||||
|
|
||||||
|
METHOD attributes_only.
|
||||||
|
|
||||||
|
cl_abap_unit_assert=>assert_equals(
|
||||||
|
exp = |<span class="attr"> SAPRL</span>=|
|
||||||
|
&& |<span class="attr_val">"751"</span>|
|
||||||
|
&& |<span class="attr"> VERSION</span>=|
|
||||||
|
&& |<span class="attr_val">">1.5"</span>|
|
||||||
|
act = mo_cut->process_line( | SAPRL="751" VERSION=">1.5"| ) ).
|
||||||
|
|
||||||
|
cl_abap_unit_assert=>assert_equals(
|
||||||
|
exp = |<span class="attr">SAPRL</span>=|
|
||||||
|
&& |<span class="attr_val">"751"</span>|
|
||||||
|
&& |<span class="attr"> VERSION</span>=|
|
||||||
|
&& |<span class="attr_val">'>1.5'</span>|
|
||||||
|
act = mo_cut->process_line( |SAPRL="751" VERSION='>1.5'| ) ).
|
||||||
|
|
||||||
|
ENDMETHOD.
|
||||||
|
|
||||||
|
METHOD open_tags.
|
||||||
|
|
||||||
|
cl_abap_unit_assert=>assert_equals(
|
||||||
|
exp = |<span class="xml_tag"><ECTD</span>|
|
||||||
|
act = mo_cut->process_line( |<ECTD| ) ).
|
||||||
|
|
||||||
|
cl_abap_unit_assert=>assert_equals(
|
||||||
|
exp = |<span class="xml_tag"><ECTD</span>|
|
||||||
|
&& |<span class="attr"> SAPRL</span>=|
|
||||||
|
&& |<span class="attr_val">"751"</span>|
|
||||||
|
&& |<span class="attr"> VERSION</span>=|
|
||||||
|
&& |<span class="attr_val">"1.5"</span>|
|
||||||
|
act = mo_cut->process_line( |<ECTD SAPRL="751" VERSION="1.5"| ) ).
|
||||||
|
|
||||||
|
|
||||||
|
ENDMETHOD.
|
||||||
|
|
||||||
ENDCLASS.
|
ENDCLASS.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user