diff --git a/package.json b/package.json index 85bf4f75d..9ecc0b3e4 100644 --- a/package.json +++ b/package.json @@ -25,12 +25,12 @@ ] }, "devDependencies": { - "@abaplint/cli": "^2.91.1", - "@abaplint/runtime": "^2.0.34", - "@abaplint/transpiler-cli": "^2.0.34", + "@abaplint/cli": "^2.91.4", + "@abaplint/runtime": "^2.0.45", + "@abaplint/transpiler-cli": "^2.0.45", "@abaplint/database-sqlite": "^2.0.30", - "abapmerge": "^0.14.6", + "abapmerge": "^0.14.7", "c8": "^7.11.3", - "eslint": "^8.17.0" + "eslint": "^8.18.0" } } diff --git a/src/json/zcl_abapgit_ajson.clas.locals_imp.abap b/src/json/zcl_abapgit_ajson.clas.locals_imp.abap index 5faf4e8b3..6e4362736 100644 --- a/src/json/zcl_abapgit_ajson.clas.locals_imp.abap +++ b/src/json/zcl_abapgit_ajson.clas.locals_imp.abap @@ -2,6 +2,57 @@ * UTILS ********************************************************************** +INTERFACE lif_kind. + + TYPES ty_kind TYPE c LENGTH 1. + + CONSTANTS: + any TYPE ty_kind VALUE cl_abap_typedescr=>typekind_any, + date TYPE ty_kind VALUE cl_abap_typedescr=>typekind_date, + time TYPE ty_kind VALUE cl_abap_typedescr=>typekind_time, + packed TYPE ty_kind VALUE cl_abap_typedescr=>typekind_packed, + table TYPE ty_kind VALUE cl_abap_typedescr=>typekind_table, + struct_flat TYPE ty_kind VALUE cl_abap_typedescr=>typekind_struct1, + struct_deep TYPE ty_kind VALUE cl_abap_typedescr=>typekind_struct2, + data_ref TYPE ty_kind VALUE cl_abap_typedescr=>typekind_dref, + object_ref TYPE ty_kind VALUE cl_abap_typedescr=>typekind_oref. + + CONSTANTS: + BEGIN OF numeric, + int1 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_int1, + int2 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_int2, + int4 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_int, + int8 TYPE ty_kind VALUE '8', " cl_abap_tabledescr=>typekind_int8 not in lower releases + float TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_float, + packed TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_packed, + decfloat16 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_decfloat16, + decfloat34 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_decfloat34, + END OF numeric. + + CONSTANTS: + BEGIN OF texts, + char TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_char, + numc TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_num, + string TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_string, + END OF texts. + + CONSTANTS: + BEGIN OF binary, + hex TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_hex, + xstring TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_xstring, + END OF binary. + + CONSTANTS: + BEGIN OF deep_targets, + table TYPE ty_kind VALUE cl_abap_typedescr=>typekind_table, + struct_flat TYPE ty_kind VALUE cl_abap_typedescr=>typekind_struct1, + struct_deep TYPE ty_kind VALUE cl_abap_typedescr=>typekind_struct2, + data_ref TYPE ty_kind VALUE cl_abap_typedescr=>typekind_dref, + object_ref TYPE ty_kind VALUE cl_abap_typedescr=>typekind_oref, + END OF deep_targets. + +ENDINTERFACE. + CLASS lcl_utils DEFINITION FINAL. PUBLIC SECTION. @@ -589,7 +640,7 @@ CLASS lcl_json_to_abap DEFINITION FINAL. type_path TYPE string, target_field_name TYPE string, dd TYPE REF TO cl_abap_datadescr, - type_kind LIKE cl_abap_typedescr=>typekind_any, + type_kind LIKE lif_kind=>any, tab_item_buf TYPE REF TO data, END OF ty_type_cache. DATA mt_node_type_cache TYPE HASHED TABLE OF ty_type_cache WITH UNIQUE KEY type_path. @@ -658,7 +709,7 @@ CLASS lcl_json_to_abap IMPLEMENTATION. DATA lo_ddescr TYPE REF TO cl_abap_datadescr. " Calculate type path - IF is_parent_type-type_kind = cl_abap_typedescr=>typekind_table. + IF is_parent_type-type_kind = lif_kind=>table. lv_node_type_path = is_parent_type-type_path && '/-'. " table item type ELSEIF is_parent_type-type_kind IS NOT INITIAL. lv_node_type_path = is_parent_type-type_path && '/' && is_node-name. @@ -682,11 +733,11 @@ CLASS lcl_json_to_abap IMPLEMENTATION. ENDIF. CASE is_parent_type-type_kind. - WHEN 'h'. " Table + WHEN lif_kind=>table. lo_tdescr ?= is_parent_type-dd. rs_node_type-dd = lo_tdescr->get_table_line_type( ). - WHEN 'u' OR 'v'. " Structure + WHEN lif_kind=>struct_flat OR lif_kind=>struct_deep. lo_sdescr ?= is_parent_type-dd. lo_sdescr->get_component_type( EXPORTING @@ -707,9 +758,9 @@ CLASS lcl_json_to_abap IMPLEMENTATION. ENDCASE. rs_node_type-type_kind = rs_node_type-dd->type_kind. " for caching and cleaner unintialized access - IF rs_node_type-type_kind = 'h'. " Table + IF rs_node_type-type_kind = lif_kind=>table. lo_tdescr ?= rs_node_type-dd. - IF lo_tdescr->table_kind <> 'S'. " standard + IF lo_tdescr->table_kind <> cl_abap_tabledescr=>tablekind_std. lo_ddescr = lo_tdescr->get_table_line_type( ). CREATE DATA rs_node_type-tab_item_buf TYPE HANDLE lo_ddescr. ENDIF. @@ -735,7 +786,7 @@ CLASS lcl_json_to_abap IMPLEMENTATION. " Assign container CASE is_parent_type-type_kind. - WHEN 'h'. " Table + WHEN lif_kind=>table. IF is_parent_type-tab_item_buf IS BOUND. " Indirect hint that table was sorted/hashed, see get_node_type. ASSIGN i_container_ref->* TO . ASSERT sy-subrc = 0. @@ -749,7 +800,7 @@ CLASS lcl_json_to_abap IMPLEMENTATION. ASSERT sy-subrc = 0. ENDIF. - WHEN 'u' OR 'v'. " Structure + WHEN lif_kind=>struct_flat OR lif_kind=>struct_deep. ASSIGN i_container_ref->* TO . ASSERT sy-subrc = 0. ENDCASE. @@ -760,7 +811,7 @@ CLASS lcl_json_to_abap IMPLEMENTATION. LOOP AT mr_nodes->* ASSIGNING USING KEY array_index WHERE path = iv_path. " Get or create type cache record - IF is_parent_type-type_kind <> 'h' OR ls_node_type-type_kind IS INITIAL. + IF is_parent_type-type_kind <> lif_kind=>table OR ls_node_type-type_kind IS INITIAL. " table records are the same, no need to refetch twice ls_node_type = get_node_type( is_node = @@ -768,14 +819,15 @@ CLASS lcl_json_to_abap IMPLEMENTATION. ENDIF. " Validate node type - IF ls_node_type-type_kind CA 'lr'. " data/obj ref + IF ls_node_type-type_kind = lif_kind=>data_ref OR + ls_node_type-type_kind = lif_kind=>object_ref. " TODO maybe in future zcx_abapgit_ajson_error=>raise( 'Cannot assign to ref' ). ENDIF. " Find target field reference CASE is_parent_type-type_kind. - WHEN 'h'. " Table + WHEN lif_kind=>table. IF NOT ls_node_type-target_field_name CO '0123456789'. " Does not affect anything actually but for integrity zcx_abapgit_ajson_error=>raise( 'Need index to access tables' ). @@ -786,7 +838,7 @@ CLASS lcl_json_to_abap IMPLEMENTATION. ASSERT sy-subrc = 0. ENDIF. - WHEN 'u' OR 'v'. + WHEN lif_kind=>struct_flat OR lif_kind=>struct_deep. FIELD-SYMBOLS TYPE any. ASSIGN COMPONENT ls_node_type-target_field_name OF STRUCTURE TO . ASSERT sy-subrc = 0. @@ -802,7 +854,8 @@ CLASS lcl_json_to_abap IMPLEMENTATION. " Process value assignment CASE -type. WHEN zif_abapgit_ajson=>node_type-object. - IF NOT ls_node_type-type_kind CO 'uv'. + IF ls_node_type-type_kind <> lif_kind=>struct_flat AND + ls_node_type-type_kind <> lif_kind=>struct_deep. zcx_abapgit_ajson_error=>raise( 'Expected structure' ). ENDIF. any_to_abap( @@ -811,7 +864,7 @@ CLASS lcl_json_to_abap IMPLEMENTATION. i_container_ref = lr_target_field ). WHEN zif_abapgit_ajson=>node_type-array. - IF NOT ls_node_type-type_kind = 'h'. + IF NOT ls_node_type-type_kind = lif_kind=>table. zcx_abapgit_ajson_error=>raise( 'Expected table' ). ENDIF. any_to_abap( @@ -860,7 +913,7 @@ CLASS lcl_json_to_abap IMPLEMENTATION. FIELD-SYMBOLS TYPE any. - IF is_node_type-type_kind CA 'lruvh'. " refs, table, strucs + IF is_node_type-type_kind CA lif_kind=>deep_targets. zcx_abapgit_ajson_error=>raise( |Unsupported target for value [{ is_node_type-type_kind }]| ). ENDIF. @@ -879,9 +932,9 @@ CLASS lcl_json_to_abap IMPLEMENTATION. WHEN zif_abapgit_ajson=>node_type-string. " TODO: check type ? - IF is_node_type-type_kind = 'D' AND is_node-value IS NOT INITIAL. + IF is_node_type-type_kind = lif_kind=>date AND is_node-value IS NOT INITIAL. = to_date( is_node-value ). - ELSEIF is_node_type-type_kind = 'P' AND is_node-value IS NOT INITIAL. + ELSEIF is_node_type-type_kind = lif_kind=>packed AND is_node-value IS NOT INITIAL. = to_timestamp( is_node-value ). ELSE. = is_node-value. @@ -1206,7 +1259,7 @@ CLASS lcl_abap_to_json IMPLEMENTATION. WHEN OTHERS. - IF io_type->type_kind = cl_abap_typedescr=>typekind_dref OR iv_data IS INITIAL. + IF io_type->type_kind = lif_kind=>data_ref OR iv_data IS INITIAL. " Convert data references and initial references to other types (like ref to class or interface) " Initial references will result in "null" convert_ref( @@ -1218,7 +1271,7 @@ CLASS lcl_abap_to_json IMPLEMENTATION. CHANGING ct_nodes = ct_nodes ). - ELSEIF io_type->type_kind = cl_abap_typedescr=>typekind_oref + ELSEIF io_type->type_kind = lif_kind=>object_ref AND cl_abap_typedescr=>describe_by_object_ref( iv_data )->absolute_name = gv_ajson_absolute_type_name. convert_ajson( EXPORTING @@ -1334,24 +1387,25 @@ CLASS lcl_abap_to_json IMPLEMENTATION. ls_node-type = zif_abapgit_ajson=>node_type-number. ls_node-value = |{ iv_data }|. ENDIF. - ELSEIF io_type->type_kind CO 'CNgXy'. " Char like, xstring + ELSEIF io_type->type_kind CO lif_kind=>texts OR + io_type->type_kind CO lif_kind=>binary. ls_node-type = zif_abapgit_ajson=>node_type-string. ls_node-value = |{ iv_data }|. - ELSEIF io_type->type_kind = 'D'. " Date + ELSEIF io_type->type_kind = lif_kind=>date. ls_node-type = zif_abapgit_ajson=>node_type-string. IF mv_format_datetime = abap_true. ls_node-value = format_date( iv_data ). ELSE. ls_node-value = |{ iv_data }|. ENDIF. - ELSEIF io_type->type_kind = 'T'. " Time + ELSEIF io_type->type_kind = lif_kind=>time. ls_node-type = zif_abapgit_ajson=>node_type-string. IF mv_format_datetime = abap_true. ls_node-value = format_time( iv_data ). ELSE. ls_node-value = |{ iv_data }|. ENDIF. - ELSEIF io_type->type_kind CO 'bsI8aeFP'. " Numeric + ELSEIF io_type->type_kind CO lif_kind=>numeric. ls_node-type = zif_abapgit_ajson=>node_type-number. ls_node-value = |{ iv_data }|. ELSE. @@ -1571,7 +1625,9 @@ CLASS lcl_abap_to_json IMPLEMENTATION. DATA ls_node LIKE LINE OF ct_nodes. lv_prefix = is_prefix-path && is_prefix-name. - IF io_type->type_kind CO 'CNgXyDT'. " Char like, date/time, xstring + IF io_type->type_kind CO lif_kind=>texts OR + io_type->type_kind CO lif_kind=>date OR + io_type->type_kind CO lif_kind=>time. IF iv_type = zif_abapgit_ajson=>node_type-boolean AND iv_data <> 'true' AND iv_data <> 'false'. zcx_abapgit_ajson_error=>raise( |Unexpected boolean value [{ iv_data }] @{ lv_prefix }| ). ELSEIF iv_type = zif_abapgit_ajson=>node_type-null AND iv_data IS NOT INITIAL. @@ -1582,7 +1638,7 @@ CLASS lcl_abap_to_json IMPLEMENTATION. AND iv_type <> zif_abapgit_ajson=>node_type-null AND iv_type <> zif_abapgit_ajson=>node_type-number. zcx_abapgit_ajson_error=>raise( |Unexpected type for value [{ iv_type },{ iv_data }] @{ lv_prefix }| ). ENDIF. - ELSEIF io_type->type_kind CO 'bsI8PaeF'. " Numeric + ELSEIF io_type->type_kind CO lif_kind=>numeric. IF iv_type <> zif_abapgit_ajson=>node_type-number. zcx_abapgit_ajson_error=>raise( |Unexpected value for numeric [{ iv_data }] @{ lv_prefix }| ). ENDIF. diff --git a/test/abap_transpile.json b/test/abap_transpile.json index e306c5f4b..97abc8144 100644 --- a/test/abap_transpile.json +++ b/test/abap_transpile.json @@ -143,16 +143,27 @@ {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_w_tab_of_struc", "note": "ASSIGN, not a structure"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_array_of_arrays", "note": "Right-hand side of 'instanceof' is not an object"}, - {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_obj", "note": "https://github.com/abaplint/transpiler/pull/750"}, - {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_ajson"}, - {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_tab"}, - {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_tab_hashed", "note": "runtime error, SortByLengthZero"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "arrays_negative"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "arrays"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "ignore_empty"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "read_only"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "root_assignment"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_ajson"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_array_obj"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_bool_abap_bool"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_bool_int"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_bool_tab"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_date"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_int"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_obj_w_date_time"}, - {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "root_assignment"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_obj", "note": "https://github.com/abaplint/transpiler/pull/750"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_str"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_tab_hashed", "note": "runtime error, SortByLengthZero"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_tab_nested_struct"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_tab"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_timestamp"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_value"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_with_type"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_parser_test", "method": "parse_error"}, @@ -161,12 +172,29 @@ {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_integrated", "method": "array_simple", "note": "Right-hand side of 'instanceof' is not an object"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_integrated", "method": "item_order_integrated"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_integrated", "method": "stringify"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_integrated", "method": "chaining"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_integrated", "method": "push_json"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_abap_to_json", "method": "set_obj"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_abap_to_json", "method": "set_array"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_abap_to_json", "method": "prefix"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_abap_to_json", "method": "set_value_number"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_abap_to_json", "method": "set_value_string"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_abap_to_json", "method": "set_complex_obj"}, - {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_tab_nested_struct"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_filter_test", "method": "simple_test"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_filter_test", "method": "array_test"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_filter_test", "method": "visit_types"}, + + {"object": "ZCL_ABAPGIT_AJSON_FILTER_LIB", "class": "ltcl_filters_test", "method": "empty_filter_simple"}, + {"object": "ZCL_ABAPGIT_AJSON_FILTER_LIB", "class": "ltcl_filters_test", "method": "empty_filter_deep"}, + {"object": "ZCL_ABAPGIT_AJSON_FILTER_LIB", "class": "ltcl_filters_test", "method": "path_filter"}, + {"object": "ZCL_ABAPGIT_AJSON_FILTER_LIB", "class": "ltcl_filters_test", "method": "path_filter_deep"}, + {"object": "ZCL_ABAPGIT_AJSON_FILTER_LIB", "class": "ltcl_filters_test", "method": "and_filter"}, + + {"object": "ZCL_ABAPGIT_AJSON_UTILITIES", "class": "ltcl_json_utils", "method": "json_diff"}, + {"object": "ZCL_ABAPGIT_AJSON_UTILITIES", "class": "ltcl_json_utils", "method": "json_diff_types"}, + {"object": "ZCL_ABAPGIT_AJSON_UTILITIES", "class": "ltcl_json_utils", "method": "json_merge"}, {"object": "ZCL_ABAPGIT_UI_INJECTOR", "class": "ltcl_no_dependency_injection", "method": "no_injection", "note": "RTTI? class absolute_name"}, {"object": "ZCL_ABAPGIT_UI_INJECTOR", "class": "ltcl_simple_dependency_inject", "method": "simple_injection", "note": "RTTI?"}, @@ -205,8 +233,6 @@ {"object": "ZCL_ABAPGIT_INJECTOR", "class": "ltcl_no_dependency_injection", "method": "no_injection"}, {"object": "ZCL_ABAPGIT_INJECTOR", "class": "ltcl_simple_dependency_inject", "method": "simple_injection"}, - {"object": "ZCL_ABAPGIT_HTML_FORM_UTILS", "class": "ltcl_test_form", "method": "validate3", "note": "https://github.com/abaplint/transpiler/pull/750"}, - {"object": "ZCL_ABAPGIT_FILE_DESERIALIZE", "class": "ltcl_prio_deserialization", "method": "clas_before_pinf", "note": "hmm, something with promises?"}, {"object": "ZCL_ABAPGIT_FILE_DESERIALIZE", "class": "ltcl_prio_deserialization", "method": "ddls_before_dcls", "note": "hmm, something with promises?"}, {"object": "ZCL_ABAPGIT_FILE_DESERIALIZE", "class": "ltcl_prio_deserialization", "method": "enho_before_enhc", "note": "hmm, something with promises?"},