fixed issue #1799 (dump for < or > in attributes) (#1923)

* fixed issue #1799 (dump for  < or > in attributes)

* added unit tests and extended support
This commit is contained in:
Marcello Urbani 2018-09-16 17:23:52 +01:00 committed by Lars Hvam
parent 30a11218f9
commit af8a7abb9c
4 changed files with 174 additions and 23 deletions

View File

@ -30,9 +30,10 @@ CLASS zcl_abapgit_syntax_highlighter DEFINITION
TYPES:
BEGIN OF ty_rule,
regex TYPE REF TO cl_abap_regex,
token TYPE char1,
style TYPE string,
regex TYPE REF TO cl_abap_regex,
token TYPE char1,
style TYPE string,
relevant_submatch TYPE i,
END OF ty_rule.
CONSTANTS c_token_none TYPE c VALUE '.'.
@ -41,9 +42,10 @@ CLASS zcl_abapgit_syntax_highlighter DEFINITION
METHODS add_rule
IMPORTING
iv_regex TYPE string
iv_token TYPE c
iv_style TYPE string.
iv_regex TYPE string
iv_token TYPE c
iv_style TYPE string
iv_submatch TYPE i OPTIONAL.
METHODS parse_line
IMPORTING iv_line TYPE string
@ -66,12 +68,11 @@ CLASS zcl_abapgit_syntax_highlighter DEFINITION
IMPORTING iv_line TYPE string
iv_class TYPE string
RETURNING VALUE(rv_line) TYPE string.
ENDCLASS.
CLASS ZCL_ABAPGIT_SYNTAX_HIGHLIGHTER IMPLEMENTATION.
CLASS zcl_abapgit_syntax_highlighter IMPLEMENTATION.
METHOD add_rule.
@ -83,8 +84,9 @@ CLASS ZCL_ABAPGIT_SYNTAX_HIGHLIGHTER IMPLEMENTATION.
pattern = iv_regex
ignore_case = abap_true.
ls_rule-token = iv_token.
ls_rule-style = iv_style.
ls_rule-token = iv_token.
ls_rule-style = iv_style.
ls_rule-relevant_submatch = iv_submatch.
APPEND ls_rule TO mt_rules.
ENDMETHOD.
@ -188,7 +190,8 @@ CLASS ZCL_ABAPGIT_SYNTAX_HIGHLIGHTER IMPLEMENTATION.
FIELD-SYMBOLS:
<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.
@ -202,10 +205,21 @@ CLASS ZCL_ABAPGIT_SYNTAX_HIGHLIGHTER IMPLEMENTATION.
" Save matches into custom table with predefined tokens
LOOP AT lt_result ASSIGNING <ls_result>.
CLEAR: ls_match.
ls_match-token = <ls_regex>-token.
ls_match-offset = <ls_result>-offset.
ls_match-length = <ls_result>-length.
APPEND ls_match TO et_matches.
IF <ls_regex>-relevant_submatch = 0.
ls_match-token = <ls_regex>-token.
ls_match-offset = <ls_result>-offset.
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.

View File

@ -30,7 +30,10 @@ CLASS ltcl_syntax_cases DEFINITION FINAL FOR TESTING RISK LEVEL HARMLESS
test_xml_02 FOR TESTING,
test_xml_03 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.
*----------------------------------------------------------------------*
@ -515,6 +518,87 @@ CLASS ltcl_syntax_cases IMPLEMENTATION.
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.
CLASS ltcl_syntax_basic_logic DEFINITION DEFERRED.

View File

@ -19,9 +19,11 @@ CLASS zcl_abapgit_syntax_xml DEFINITION
END OF c_token .
CONSTANTS:
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
"for XML tags, we will use a submatch
" main pattern includes quoted strings so we can ignore < and > in attr values
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 .
METHODS constructor .
@ -42,9 +44,10 @@ CLASS zcl_abapgit_syntax_xml IMPLEMENTATION.
" Initialize instances of regular expressions
add_rule( iv_regex = c_regex-xml_tag
iv_token = c_token-xml_tag
iv_style = c_css-xml_tag ).
add_rule( iv_regex = c_regex-xml_tag
iv_token = c_token-xml_tag
iv_style = c_css-xml_tag
iv_submatch = 1 ).
add_rule( iv_regex = c_regex-attr
iv_token = c_token-attr
@ -114,5 +117,18 @@ CLASS zcl_abapgit_syntax_xml IMPLEMENTATION.
ASSIGN <ls_match> TO <ls_prev>.
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.
ENDCLASS.

View File

@ -11,7 +11,9 @@ CLASS abapgit_syntax_xml DEFINITION FINAL FOR TESTING
sole_closing_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,
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.
@ -63,4 +65,39 @@ CLASS abapgit_syntax_xml IMPLEMENTATION.
ENDMETHOD.
METHOD attributes_only.
cl_abap_unit_assert=>assert_equals(
exp = |<span class="attr"> SAPRL</span>=|
&& |<span class="attr_val">&quot;751&quot;</span>|
&& |<span class="attr"> VERSION</span>=|
&& |<span class="attr_val">&quot;&gt;1.5&quot;</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">&quot;751&quot;</span>|
&& |<span class="attr"> VERSION</span>=|
&& |<span class="attr_val">&#39;&gt;1.5&#39;</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">&lt;ECTD</span>|
act = mo_cut->process_line( |<ECTD| ) ).
cl_abap_unit_assert=>assert_equals(
exp = |<span class="xml_tag">&lt;ECTD</span>|
&& |<span class="attr"> SAPRL</span>=|
&& |<span class="attr_val">&quot;751&quot;</span>|
&& |<span class="attr"> VERSION</span>=|
&& |<span class="attr_val">&quot;1.5&quot;</span>|
act = mo_cut->process_line( |<ECTD SAPRL="751" VERSION="1.5"| ) ).
ENDMETHOD.
ENDCLASS.