diff --git a/src/zcl_aff_abap_doc_parser.clas.abap b/src/zcl_aff_abap_doc_parser.clas.abap index db16aabe..dbe5a4ae 100644 --- a/src/zcl_aff_abap_doc_parser.clas.abap +++ b/src/zcl_aff_abap_doc_parser.clas.abap @@ -20,6 +20,7 @@ CLASS zcl_aff_abap_doc_parser DEFINITION content_media_type TYPE string VALUE `$contentMediaType`, content_encoding TYPE string VALUE `$contentEncoding`, enum_value TYPE string VALUE `$enumValue`, + pattern TYPE string VALUE `$pattern`, END OF abap_doc_annotation. TYPES: @@ -41,6 +42,7 @@ CLASS zcl_aff_abap_doc_parser DEFINITION content_media_type TYPE string, content_encoding TYPE string, enum_value TYPE string, + pattern TYPE string, END OF abap_doc. METHODS: parse @@ -99,6 +101,7 @@ CLASS zcl_aff_abap_doc_parser DEFINITION annotation_name TYPE string RETURNING VALUE(number) TYPE string, + parse_pattern, check_next_word IMPORTING offset TYPE i @@ -164,7 +167,7 @@ CLASS zcl_aff_abap_doc_parser IMPLEMENTATION. ENDMETHOD. METHOD parse_description. - FIND FIRST OCCURRENCE OF PCRE `(\$callbackClass|\$default|\$values|\$required|\$showAlways|\$minimum|\$maximum|\$exclusiveMinimum|\$exclusiveMaximum|\$multipleOf|\$maxLength|\$minLength|\$enumValue|\$contentMediaType|\$contentEncoding)` + FIND FIRST OCCURRENCE OF PCRE `(\$callbackClass|\$default|\$values|\$required|\$showAlways|\$minimum|\$maximum|\$exclusiveMinimum|\$exclusiveMaximum|\$multipleOf|\$maxLength|\$minLength|\$enumValue|\$contentMediaType|\$contentEncoding|\$pattern)` IN abap_doc_string MATCH OFFSET DATA(offset). IF sy-subrc = 0. DATA(description) = abap_doc_string+0(offset). @@ -195,6 +198,8 @@ CLASS zcl_aff_abap_doc_parser IMPLEMENTATION. parse_required( ). WHEN abap_doc_annotation-show_always. parse_show_always( ). + WHEN abap_doc_annotation-pattern. + parse_pattern( ). WHEN abap_doc_annotation-minimum OR abap_doc_annotation-maximum OR abap_doc_annotation-exclusive_minimum OR abap_doc_annotation-exclusive_maximum OR abap_doc_annotation-max_length OR abap_doc_annotation-multiple_of OR abap_doc_annotation-min_length. parse_number_annotations( key_word = key_word ). @@ -543,4 +548,35 @@ CLASS zcl_aff_abap_doc_parser IMPLEMENTATION. ENDIF. ENDMETHOD. + METHOD parse_pattern. + IF decoded_abap_doc-pattern IS NOT INITIAL. + RETURN. + ENDIF. + + DATA(string_to_parse) = abap_doc_string. + + FIND ALL OCCURRENCES OF PCRE `\$pattern[\s]*(:[\s]*)?'([^']*)'` IN string_to_parse RESULTS DATA(result_table). + + IF lines( result_table ) = 0. + DATA(msg) = parser_log->get_message_text( msgno = 109 msgv1 = CONV #( abap_doc_annotation-pattern ) ). + parser_log->add_warning( message_text = msg component_name = component_name ). + RETURN. + ENDIF. + write_log_for_multiple_entries( result_table = result_table annotaion = abap_doc_annotation-pattern ). + + LOOP AT result_table ASSIGNING FIELD-SYMBOL(). + IF lines( -submatches ) = 2 AND decoded_abap_doc-pattern IS INITIAL. + DATA(submatch) = -submatches[ 2 ]. + IF submatch-length = 0. + msg = parser_log->get_message_text( msgno = 109 msgv1 = CONV #( abap_doc_annotation-pattern ) ). + parser_log->add_warning( message_text = msg component_name = component_name ). + ENDIF. + + decoded_abap_doc-pattern = substring( val = string_to_parse off = submatch-offset len = submatch-length ). + ENDIF. + ENDLOOP. + + ENDMETHOD. + ENDCLASS. + diff --git a/src/zcl_aff_abap_doc_parser.clas.testclasses.abap b/src/zcl_aff_abap_doc_parser.clas.testclasses.abap index a1585a6f..fd1e4377 100644 --- a/src/zcl_aff_abap_doc_parser.clas.testclasses.abap +++ b/src/zcl_aff_abap_doc_parser.clas.testclasses.abap @@ -39,7 +39,11 @@ CLASS ltcl_aff_abap_doc_parser DEFINITION FINAL FOR TESTING METHODS content_media_multiple_entries FOR TESTING RAISING cx_static_check. METHODS content_media_type_used_wrong FOR TESTING RAISING cx_static_check. METHODS content_encoding_used_wrong FOR TESTING RAISING cx_static_check. - + METHODS too_many_patterns FOR TESTING RAISING cx_static_check. + METHODS pattern_with_colon FOR TESTING RAISING cx_static_check. + METHODS pattern_no_single_quotes FOR TESTING RAISING cx_static_check. + METHODS pattern_no_value FOR TESTING RAISING cx_static_check. + METHODS pattern FOR TESTING RAISING cx_static_check. ENDCLASS. @@ -582,4 +586,79 @@ CLASS ltcl_aff_abap_doc_parser IMPLEMENTATION. exp_component_name = `Component Name` ). ENDMETHOD. + METHOD pattern. + DATA(abap_doc_to_parse) = `

Title

This is the description. $pattern '[a-z]*'`. + DATA(act_abap_doc) = parser->parse( + EXPORTING + component_name = `Component Name` + to_parse = abap_doc_to_parse + CHANGING + log = log ). + exp_abap_doc = VALUE #( title = `Title` description = `This is the description.` pattern = `[a-z]*` ). + cl_abap_unit_assert=>assert_equals( exp = exp_abap_doc act = act_abap_doc ). + zcl_aff_tools_unit_test_helper=>assert_log_has_no_message( log = log message_severity_threshold = zif_aff_log=>c_message_type-info ). + ENDMETHOD. + + METHOD pattern_with_colon. + DATA(abap_doc_to_parse) = `

Title

This is the description. $pattern : '[a-z]*'`. + DATA(act_abap_doc) = parser->parse( + EXPORTING + component_name = `Component Name` + to_parse = abap_doc_to_parse + CHANGING + log = log ). + exp_abap_doc = VALUE #( title = `Title` description = `This is the description.` pattern = `[a-z]*` ). + cl_abap_unit_assert=>assert_equals( exp = exp_abap_doc act = act_abap_doc ). + zcl_aff_tools_unit_test_helper=>assert_log_has_no_message( log = log message_severity_threshold = zif_aff_log=>c_message_type-info ). + ENDMETHOD. + + METHOD pattern_no_single_quotes. + DATA(abap_doc_to_parse) = `

Title

This is the description. $pattern [a-z]*`. + DATA(act_abap_doc) = parser->parse( + EXPORTING + component_name = `Component Name` + to_parse = abap_doc_to_parse + CHANGING + log = log ). + exp_abap_doc = VALUE #( title = `Title` description = `This is the description.` ). + cl_abap_unit_assert=>assert_equals( exp = exp_abap_doc act = act_abap_doc ). + zcl_aff_tools_unit_test_helper=>assert_log_contains_text( log = log + exp_text = `Annotation $pattern was used incorrectly` + exp_type = zif_aff_log=>c_message_type-warning + exp_component_name = `Component Name` ). + ENDMETHOD. + + METHOD pattern_no_value. + DATA(abap_doc_to_parse) = `

Title

This is the description. $pattern ''`. + DATA(act_abap_doc) = parser->parse( + EXPORTING + component_name = `Component Name` + to_parse = abap_doc_to_parse + CHANGING + log = log ). + exp_abap_doc = VALUE #( title = `Title` description = `This is the description.` ). + cl_abap_unit_assert=>assert_equals( exp = exp_abap_doc act = act_abap_doc ). + zcl_aff_tools_unit_test_helper=>assert_log_contains_text( log = log + exp_text = `Annotation $pattern was used incorrectly` + exp_type = zif_aff_log=>c_message_type-warning + exp_component_name = `Component Name` ). + ENDMETHOD. + + METHOD too_many_patterns. + DATA(abap_doc_to_parse) = `

Title

This is the description. $pattern '[a-z]*' $pattern '[A-Z]*'`. + DATA(act_abap_doc) = parser->parse( + EXPORTING + component_name = `Component Name` + to_parse = abap_doc_to_parse + CHANGING + log = log ). + exp_abap_doc = VALUE #( title = `Title` description = `This is the description.` pattern = `[a-z]*` ). + cl_abap_unit_assert=>assert_equals( exp = exp_abap_doc act = act_abap_doc ). + zcl_aff_tools_unit_test_helper=>assert_log_contains_text( log = log + exp_text = |There are several occurrences of annotation { zcl_aff_abap_doc_parser=>abap_doc_annotation-pattern } . First valid is used| + exp_type = zif_aff_log=>c_message_type-info + exp_component_name = `Component Name` ). + + ENDMETHOD. + ENDCLASS. diff --git a/src/zcl_aff_test_types.clas.abap b/src/zcl_aff_test_types.clas.abap index b109c3c2..ea787758 100644 --- a/src/zcl_aff_test_types.clas.abap +++ b/src/zcl_aff_test_types.clas.abap @@ -67,6 +67,28 @@ CLASS zcl_aff_test_types DEFINITION default_link TYPE default_link, END OF struc_link_wrong_type. + TYPES: + "! $pattern '[a-Z]*' + ty_string TYPE string. + + TYPES: + "!

Structure With Pattern Annotation

+ "! Structure with pattern annotation + BEGIN OF string_pattern_complex, + "!

String with pattern

+ "! description + string_pattern TYPE ty_string, + END OF string_pattern_complex. + + TYPES: + "!

Structure With Pattern Annotation

+ "! Structure with pattern annotation + BEGIN OF string_pattern_simple, + "!

String with pattern

+ "! description + "! $pattern '[a-Z]*' + string_pattern TYPE string, + END OF string_pattern_simple. TYPES: "! in ST val(I()) only allow integers diff --git a/src/zcl_aff_writer.clas.abap b/src/zcl_aff_writer.clas.abap index 72603943..291c421f 100644 --- a/src/zcl_aff_writer.clas.abap +++ b/src/zcl_aff_writer.clas.abap @@ -567,6 +567,9 @@ CLASS zcl_aff_writer IMPLEMENTATION. IF abap_doc_base-content_media_type IS INITIAL. abap_doc_base-content_media_type = abap_doc_additional-content_media_type. ENDIF. + IF abap_doc_base-pattern IS INITIAL. + abap_doc_base-pattern = abap_doc_additional-pattern. + ENDIF. ENDMETHOD. diff --git a/src/zcl_aff_writer_json_schema.clas.abap b/src/zcl_aff_writer_json_schema.clas.abap index d86488dc..af50361d 100644 --- a/src/zcl_aff_writer_json_schema.clas.abap +++ b/src/zcl_aff_writer_json_schema.clas.abap @@ -440,6 +440,9 @@ CLASS zcl_aff_writer_json_schema IMPLEMENTATION. write_tag( `"pattern": "^[0-9]+$",` ). ENDIF. ENDIF. + IF abap_doc-pattern IS NOT INITIAL. + write_tag( |"pattern": "{ abap_doc-pattern }",| ). + ENDIF. ENDMETHOD. diff --git a/src/zcl_aff_writer_json_schema.clas.testclasses.abap b/src/zcl_aff_writer_json_schema.clas.testclasses.abap index 8df94c74..6693ce58 100644 --- a/src/zcl_aff_writer_json_schema.clas.testclasses.abap +++ b/src/zcl_aff_writer_json_schema.clas.testclasses.abap @@ -559,7 +559,9 @@ CLASS ltcl_json_writer_abap_doc DEFINITION FINAL FOR TESTING content_encoding FOR TESTING RAISING cx_static_check, content_media_type_integer FOR TESTING RAISING cx_static_check, content_media_type_string FOR TESTING RAISING cx_static_check, - encoding_type_next_level FOR TESTING RAISING cx_static_check. + encoding_type_next_level FOR TESTING RAISING cx_static_check, + pattern_simple FOR TESTING RAISING cx_static_check, + pattern_complex FOR TESTING RAISING cx_static_check. ENDCLASS. @@ -2788,4 +2790,57 @@ CLASS ltcl_json_writer_abap_doc IMPLEMENTATION. zcl_aff_tools_unit_test_helper=>assert_log_has_no_message( log = log message_severity_threshold = zif_aff_log=>c_message_type-info ). ENDMETHOD. + + METHOD pattern_simple. + DATA(act_schema) = test_generator->generate_type( VALUE zcl_aff_test_types=>string_pattern_simple( ) ). + DATA(exp_schema) = VALUE string_table( + ( ` { ` ) + ( | "$comment": "This file is autogenerated, do not edit manually, see { zcl_aff_writer_json_schema=>c_link_to_repository } for more information.", | ) + ( | "$schema": "{ zcl_aff_writer_json_schema=>c_schema_specification }",| ) + ( | "$id": "{ schema_id }",| ) + ( ` "title": "Structure With Pattern Annotation", ` ) + ( ` "description": "Structure with pattern annotation", ` ) + ( ` "type": "object", ` ) + ( ` "properties": { ` ) + ( ` "stringPattern": { ` ) + ( ` "title": "String with pattern",` ) + ( ` "description": "description",` ) + ( ` "type": "string", ` ) + ( ` "pattern": "[a-Z]*" ` ) + ( ` } ` ) + ( ` }, ` ) + ( ` "additionalProperties": false ` ) + ( ` } ` ) + ( ) ). + zcl_aff_tools_unit_test_helper=>assert_equals_ignore_spaces( act_data = act_schema exp_data = exp_schema ). + log = cut->zif_aff_writer~get_log( ). + zcl_aff_tools_unit_test_helper=>assert_log_has_no_message( log = log message_severity_threshold = zif_aff_log=>c_message_type-info ). + ENDMETHOD. + + METHOD pattern_complex. + DATA(act_schema) = test_generator->generate_type( VALUE zcl_aff_test_types=>string_pattern_complex( ) ). + DATA(exp_schema) = VALUE string_table( + ( ` { ` ) + ( | "$comment": "This file is autogenerated, do not edit manually, see { zcl_aff_writer_json_schema=>c_link_to_repository } for more information.", | ) + ( | "$schema": "{ zcl_aff_writer_json_schema=>c_schema_specification }",| ) + ( | "$id": "{ schema_id }",| ) + ( ` "title": "Structure With Pattern Annotation", ` ) + ( ` "description": "Structure with pattern annotation", ` ) + ( ` "type": "object", ` ) + ( ` "properties": { ` ) + ( ` "stringPattern": { ` ) + ( ` "title": "String with pattern",` ) + ( ` "description": "description",` ) + ( ` "type": "string", ` ) + ( ` "pattern": "[a-Z]*" ` ) + ( ` } ` ) + ( ` }, ` ) + ( ` "additionalProperties": false ` ) + ( ` } ` ) + ( ) ). + zcl_aff_tools_unit_test_helper=>assert_equals_ignore_spaces( act_data = act_schema exp_data = exp_schema ). + log = cut->zif_aff_writer~get_log( ). + zcl_aff_tools_unit_test_helper=>assert_log_has_no_message( log = log message_severity_threshold = zif_aff_log=>c_message_type-info ). + ENDMETHOD. + ENDCLASS.