diff --git a/.github/workflows/website-build.yml b/.github/workflows/website-build.yml index f40f41b82..52d6df2f0 100644 --- a/.github/workflows/website-build.yml +++ b/.github/workflows/website-build.yml @@ -43,6 +43,5 @@ jobs: -DSOURCEMETA_CORE_GZIP:BOOL=OFF -DSOURCEMETA_CORE_HTML:BOOL=OFF -DSOURCEMETA_CORE_MARKDOWN:BOOL=OFF - -DSOURCEMETA_CORE_EXTENSION_EDITORSCHEMA:BOOL=OFF -DSOURCEMETA_CORE_DOCS:BOOL=ON - run: cmake --build ./build --config Release --target doxygen diff --git a/.github/workflows/website-deploy.yml b/.github/workflows/website-deploy.yml index f8f1e35a5..03c095fed 100644 --- a/.github/workflows/website-deploy.yml +++ b/.github/workflows/website-deploy.yml @@ -53,7 +53,6 @@ jobs: -DSOURCEMETA_CORE_GZIP:BOOL=OFF -DSOURCEMETA_CORE_HTML:BOOL=OFF -DSOURCEMETA_CORE_MARKDOWN:BOOL=OFF - -DSOURCEMETA_CORE_EXTENSION_EDITORSCHEMA:BOOL=OFF -DSOURCEMETA_CORE_DOCS:BOOL=ON - run: cmake --build ./build --config Release --target doxygen - name: Setup Pages diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d37f11d1..c154cb89a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,6 @@ option(SOURCEMETA_CORE_SEMVER "Build the Sourcemeta Core SemVer library" ON) option(SOURCEMETA_CORE_GZIP "Build the Sourcemeta Core GZIP library" ON) option(SOURCEMETA_CORE_HTML "Build the Sourcemeta Core HTML library" ON) option(SOURCEMETA_CORE_MARKDOWN "Build the Sourcemeta Core Markdown library" ON) -option(SOURCEMETA_CORE_EXTENSION_EDITORSCHEMA "Build the Sourcemeta Core EditorSchema library" ON) option(SOURCEMETA_CORE_TESTS "Build the Sourcemeta Core tests" OFF) option(SOURCEMETA_CORE_BENCHMARK "Build the Sourcemeta Core benchmarks" OFF) option(SOURCEMETA_CORE_DOCS "Build the Sourcemeta Core docs" OFF) @@ -182,10 +181,6 @@ if(SOURCEMETA_CORE_MARKDOWN) add_subdirectory(src/core/markdown) endif() -if(SOURCEMETA_CORE_EXTENSION_EDITORSCHEMA) - add_subdirectory(src/extension/editorschema) -endif() - if(SOURCEMETA_CORE_ADDRESS_SANITIZER) sourcemeta_sanitizer(TYPE address) elseif(SOURCEMETA_CORE_UNDEFINED_SANITIZER) @@ -321,10 +316,6 @@ if(SOURCEMETA_CORE_TESTS) add_subdirectory(test/markdown) endif() - if(SOURCEMETA_CORE_EXTENSION_EDITORSCHEMA) - add_subdirectory(test/editorschema) - endif() - if(PROJECT_IS_TOP_LEVEL) # Otherwise we need the child project to link # against the sanitizers too. diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index 9922e96e4..cc8dc75fe 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -16,10 +16,6 @@ if(SOURCEMETA_CORE_JSONSCHEMA) list(APPEND BENCHMARK_SOURCES jsonschema.cc) endif() -if(SOURCEMETA_CORE_EXTENSION_EDITORSCHEMA) - list(APPEND BENCHMARK_SOURCES editorschema.cc) -endif() - if(SOURCEMETA_CORE_URITEMPLATE) list(APPEND BENCHMARK_SOURCES uritemplate.cc) endif() @@ -62,11 +58,6 @@ if(BENCHMARK_SOURCES) PRIVATE sourcemeta::core::jsonschema) endif() - if(SOURCEMETA_CORE_EXTENSION_EDITORSCHEMA) - target_link_libraries(sourcemeta_core_benchmark - PRIVATE sourcemeta::core::editorschema) - endif() - if(SOURCEMETA_CORE_URITEMPLATE) target_link_libraries(sourcemeta_core_benchmark PRIVATE sourcemeta::core::uritemplate) diff --git a/benchmark/editorschema.cc b/benchmark/editorschema.cc deleted file mode 100644 index 46ae3d3a9..000000000 --- a/benchmark/editorschema.cc +++ /dev/null @@ -1,22 +0,0 @@ -#include - -#include // std::filesystem - -#include -#include -#include - -static void EditorSchema_ForEditor_EmbeddedResources(benchmark::State &state) { - for (auto _ : state) { - state.PauseTiming(); - auto schema{sourcemeta::core::read_json( - std::filesystem::path{CURRENT_DIRECTORY} / "files" / - "2020_12_embedded_resources.json")}; - state.ResumeTiming(); - sourcemeta::core::for_editor(schema, sourcemeta::core::schema_walker, - sourcemeta::core::schema_resolver); - benchmark::DoNotOptimize(schema); - } -} - -BENCHMARK(EditorSchema_ForEditor_EmbeddedResources); diff --git a/config.cmake.in b/config.cmake.in index ed2c352c2..1b2c336e0 100644 --- a/config.cmake.in +++ b/config.cmake.in @@ -29,7 +29,6 @@ if(NOT SOURCEMETA_CORE_COMPONENTS) list(APPEND SOURCEMETA_CORE_COMPONENTS gzip) list(APPEND SOURCEMETA_CORE_COMPONENTS html) list(APPEND SOURCEMETA_CORE_COMPONENTS markdown) - list(APPEND SOURCEMETA_CORE_COMPONENTS editorschema) list(APPEND SOURCEMETA_CORE_COMPONENTS error) list(APPEND SOURCEMETA_CORE_COMPONENTS options) endif() @@ -143,16 +142,6 @@ foreach(component ${SOURCEMETA_CORE_COMPONENTS}) elseif(component STREQUAL "markdown") find_dependency(cmark_gfm CONFIG) include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_markdown.cmake") - elseif(component STREQUAL "editorschema") - include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_ip.cmake") - include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_uri.cmake") - include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_numeric.cmake") - include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_io.cmake") - include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_unicode.cmake") - include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_json.cmake") - include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_jsonpointer.cmake") - include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_jsonschema.cmake") - include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_editorschema.cmake") elseif(component STREQUAL "error") include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_error.cmake") elseif(component STREQUAL "options") diff --git a/src/extension/editorschema/CMakeLists.txt b/src/extension/editorschema/CMakeLists.txt deleted file mode 100644 index 2b665d8d8..000000000 --- a/src/extension/editorschema/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME editorschema - SOURCES editorschema.cc) - -if(SOURCEMETA_CORE_INSTALL) - sourcemeta_library_install(NAMESPACE sourcemeta PROJECT core NAME editorschema) -endif() - -target_link_libraries(sourcemeta_core_editorschema PUBLIC sourcemeta::core::jsonschema) diff --git a/src/extension/editorschema/editorschema.cc b/src/extension/editorschema/editorschema.cc deleted file mode 100644 index d595efdcd..000000000 --- a/src/extension/editorschema/editorschema.cc +++ /dev/null @@ -1,203 +0,0 @@ -#include - -#include // assert -#include // std::map - -namespace { - -// Note that we don't take into account dynamic resources behind conditionals, -// etc. We probably should, but the complexity of this transformation would -// massively grow, plus such case is quite uncommon in practice. -// See https://arxiv.org/abs/2503.11288 for an academic study of this topic -auto top_dynamic_anchor_location( - const sourcemeta::core::SchemaFrame &frame, - const sourcemeta::core::WeakPointer ¤t, - const std::string_view fragment, - const sourcemeta::core::JSON::String &default_uri) - -> std::optional< - std::reference_wrapper> { - // Get the location object of where we are at the moment - const auto uri{frame.uri(current)}; - assert(uri.has_value()); - const auto match{frame.traverse(uri.value().get())}; - assert(match.has_value()); - const auto &location{match.value().get()}; - - // Try to locate an anchor with the given name on the current base - assert(!fragment.starts_with('#')); - sourcemeta::core::JSON::String anchor_uri{location.base}; - anchor_uri += '#'; - anchor_uri += fragment; - const auto anchor{frame.traverse(anchor_uri)}; - - if (location.parent.has_value()) { - // If there is a parent resource, keep looking there, but update the default - // if the current resource has the dynamic anchor we want - return top_dynamic_anchor_location(frame, location.parent.value(), fragment, - anchor.has_value() ? anchor_uri - : default_uri); - - // If we are at the top of the schema and it declares the dynamic anchor, we - // should use that - } else if (anchor.has_value()) { - return std::cref(anchor.value().get().pointer); - - // Otherwise, if we are at the top and the dynamic anchor is not there, use - // the default we have so far - } else { - const auto default_location{frame.traverse(default_uri)}; - assert(default_location.has_value()); - return std::cref(default_location.value().get().pointer); - } -} - -} // namespace - -namespace sourcemeta::core { - -// Collected information about a reference to modify -struct ReferenceChange { - Pointer pointer; - JSON::String new_value; - JSON::String keyword; - bool rename_to_ref; -}; - -// Collected information about a subschema to modify -struct SubschemaChange { - Pointer pointer; - SchemaBaseDialect base_dialect; - bool add_schema_declaration; - bool erase_2020_12_keywords; - bool erase_2019_09_keywords; -}; - -auto for_editor(JSON &schema, const SchemaWalker &walker, - const SchemaResolver &resolver, - std::string_view default_dialect) -> void { - // (1) Frame the schema and collect all changes we need to make - std::vector reference_changes; - std::vector subschema_changes; - - { - SchemaFrame frame{SchemaFrame::Mode::References}; - frame.analyse(schema, walker, resolver, default_dialect); - - // Otherwise the input is not bundled - assert(frame.standalone()); - - // Note that `std::unordered_map` is slower here due to high collision rates - // from the simple pointer hashes - std::map> - pointer_to_uri; - for (const auto &entry : frame.locations()) { - pointer_to_uri.emplace(entry.second.pointer, - std::cref(entry.first.second)); - } - - // Collect reference changes - for (const auto &[key, reference] : frame.references()) { - assert(!key.second.empty()); - assert(key.second.back().is_property()); - const auto &keyword{key.second.back().to_property()}; - - if (key.first == SchemaReferenceType::Dynamic) { - if (reference.fragment.has_value()) { - const auto destination{top_dynamic_anchor_location( - frame, key.second, reference.fragment.value(), - reference.destination)}; - if (!destination.has_value()) { - continue; - } - - reference_changes.push_back( - {to_pointer(key.second), - to_uri(destination.value().get()).recompose(), keyword, true}); - } else { - reference_changes.push_back( - {to_pointer(key.second), "", keyword, true}); - } - } else { - if (keyword == "$schema") { - // Use pre-built index instead of O(n) frame.uri() scan - const auto uri_it{pointer_to_uri.find(key.second)}; - assert(uri_it != pointer_to_uri.end()); - const auto origin{frame.traverse(uri_it->second.get())}; - assert(origin.has_value()); - reference_changes.push_back( - {to_pointer(key.second), - JSON::String{to_string(origin.value().get().base_dialect)}, - keyword, false}); - continue; - } - - const auto result{frame.traverse(reference.destination)}; - if (result.has_value()) { - const bool should_rename = - keyword == "$dynamicRef" || keyword == "$recursiveRef"; - reference_changes.push_back( - {to_pointer(key.second), - to_uri(result.value().get().pointer).recompose(), keyword, - should_rename}); - } else { - reference_changes.push_back( - {to_pointer(key.second), reference.destination, keyword, false}); - } - } - } - - // Collect subschema changes - for (const auto &entry : frame.locations()) { - if (entry.second.type != SchemaFrame::LocationType::Resource && - entry.second.type != SchemaFrame::LocationType::Subschema) { - continue; - } - - const auto &subschema{get(schema, entry.second.pointer)}; - if (subschema.is_boolean()) { - continue; - } - - const bool add_schema = - entry.second.pointer.empty() && !subschema.defines("$schema"); - const auto vocabularies{frame.vocabularies(entry.second, resolver)}; - - subschema_changes.push_back( - {to_pointer(entry.second.pointer), entry.second.base_dialect, - add_schema, - vocabularies.contains(Vocabularies::Known::JSON_Schema_2020_12_Core), - vocabularies.contains( - Vocabularies::Known::JSON_Schema_2019_09_Core)}); - } - } - - // (2) Apply reference changes - for (const auto &change : reference_changes) { - if (!change.new_value.empty()) { - set(schema, change.pointer, JSON{change.new_value}); - } - if (change.rename_to_ref) { - get(schema, change.pointer.initial()).rename(change.keyword, "$ref"); - } - } - - // (3) Apply subschema changes - for (const auto &change : subschema_changes) { - auto &subschema{get(schema, change.pointer)}; - - if (change.add_schema_declaration) { - subschema.assign_assume_new( - "$schema", JSON{JSON::String{to_string(change.base_dialect)}}); - } - - anonymize(subschema, change.base_dialect); - - if (change.erase_2020_12_keywords) { - subschema.erase_keys({"$vocabulary", "$anchor", "$dynamicAnchor"}); - } else if (change.erase_2019_09_keywords) { - subschema.erase_keys({"$vocabulary", "$anchor", "$recursiveAnchor"}); - } - } -} - -} // namespace sourcemeta::core diff --git a/src/extension/editorschema/include/sourcemeta/core/editorschema.h b/src/extension/editorschema/include/sourcemeta/core/editorschema.h deleted file mode 100644 index 8d871ba93..000000000 --- a/src/extension/editorschema/include/sourcemeta/core/editorschema.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef SOURCEMETA_CORE_EXTENSION_EDITORSCHEMA_H_ -#define SOURCEMETA_CORE_EXTENSION_EDITORSCHEMA_H_ - -/// @defgroup editorschema EditorSchema -/// @brief A JSON Schema compatibility layer for code editors -/// -/// This functionality is included as follows: -/// -/// ```cpp -/// #include -/// ``` - -#ifndef SOURCEMETA_CORE_EDITORSCHEMA_EXPORT -#include -#endif - -#include -#include - -#include // std::string_view - -namespace sourcemeta::core { - -/// @ingroup editorschema -/// -/// This function aims to transform the schema (in potentially non-strictly -/// compliant manners) to workaround JSON Schema limitations of popular code -/// editors. -/// -/// Keep in mind that this is not a real solution, but a workaround, and there -/// might be edge cases that we cannot cover. The real solution is for popular -/// editors to fix their JSON Schema language support. -/// -/// Note that the input schema is expected to be already bundled. -/// -/// ```cpp -/// #include -/// #include -/// -/// auto schema = sourcemeta::core::parse_json(R"JSON({ -/// "$id": "https://www.example.com/schema", -/// "$schema": "https://json-schema.org/draft/2020-12/schema", -/// "$ref": "another" -/// })JSON"); -/// -/// sourcemeta::core::bundle(schema, -/// sourcemeta::core::schema_walker, -/// sourcemeta::core::schema_resolver); -/// sourcemeta::core::for_editor(schema, -/// sourcemeta::core::schema_walker, -/// sourcemeta::core::schema_resolver); -/// ``` -SOURCEMETA_CORE_EDITORSCHEMA_EXPORT -auto for_editor(JSON &schema, const SchemaWalker &walker, - const SchemaResolver &resolver, - std::string_view default_dialect = "") -> void; - -} // namespace sourcemeta::core - -#endif diff --git a/test/editorschema/CMakeLists.txt b/test/editorschema/CMakeLists.txt deleted file mode 100644 index f522ddb6b..000000000 --- a/test/editorschema/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -sourcemeta_googletest(NAMESPACE sourcemeta PROJECT core NAME editorschema - SOURCES editorschema_test.cc) - -target_link_libraries(sourcemeta_core_editorschema_unit - PRIVATE sourcemeta::core::editorschema) -target_link_libraries(sourcemeta_core_editorschema_unit - PRIVATE sourcemeta::core::json) -target_link_libraries(sourcemeta_core_editorschema_unit - PRIVATE sourcemeta::core::jsonschema) diff --git a/test/editorschema/editorschema_test.cc b/test/editorschema/editorschema_test.cc deleted file mode 100644 index 7477fff01..000000000 --- a/test/editorschema/editorschema_test.cc +++ /dev/null @@ -1,767 +0,0 @@ -#include - -#include - -static auto test_resolver_2020_12(std::string_view identifier) - -> std::optional { - if (identifier == "https://example.com/foo/bar") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/foo/bar", - "$anchor": "baz" - })JSON"); - } else if (identifier == "https://example.com/baz-anchor") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/baz-anchor", - "$defs": { - "baz": { - "$anchor": "baz", - "type": "string" - } - } - })JSON"); - } else if (identifier == "https://www.sourcemeta.com/recursive") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://www.sourcemeta.com/recursive", - "properties": { - "foo": { "$ref": "#" } - } - })JSON"); - } else if (identifier == "https://example.com/meta/1.json") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://example.com/meta/2.json", - "$id": "https://example.com/meta/1.json", - "$vocabulary": { "https://json-schema.org/draft/2020-12/vocab/core": true } - })JSON"); - } else if (identifier == "https://example.com/meta/2.json") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/meta/2.json", - "$vocabulary": { "https://json-schema.org/draft/2020-12/vocab/core": true } - })JSON"); - } else { - return sourcemeta::core::schema_resolver(identifier); - } -} - -static auto test_resolver_2019_09(std::string_view identifier) - -> std::optional { - if (identifier == "https://example.com/foo/bar") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://example.com/foo/bar", - "$anchor": "baz" - })JSON"); - } else if (identifier == "https://example.com/baz-anchor") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://example.com/baz-anchor", - "$defs": { - "baz": { - "$anchor": "baz", - "type": "string" - } - } - })JSON"); - } else if (identifier == "https://www.sourcemeta.com/recursive") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://www.sourcemeta.com/recursive", - "properties": { - "foo": { "$ref": "#" } - } - })JSON"); - } else if (identifier == "https://example.com/meta/1.json") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://example.com/meta/2.json", - "$id": "https://example.com/meta/1.json", - "$vocabulary": { "https://json-schema.org/draft/2019-09/vocab/core": true } - })JSON"); - } else if (identifier == "https://example.com/meta/2.json") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://example.com/meta/2.json", - "$vocabulary": { "https://json-schema.org/draft/2019-09/vocab/core": true } - })JSON"); - } else { - return sourcemeta::core::schema_resolver(identifier); - } -} - -static auto test_resolver_draft7(std::string_view identifier) - -> std::optional { - if (identifier == "https://www.sourcemeta.com/recursive") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://www.sourcemeta.com/recursive", - "properties": { - "foo": { "$ref": "#" } - } - })JSON"); - } else if (identifier == "https://example.com/meta/1.json") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://example.com/meta/2.json", - "$id": "https://example.com/meta/1.json" - })JSON"); - } else if (identifier == "https://example.com/meta/2.json") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://example.com/meta/2.json" - })JSON"); - } else { - return sourcemeta::core::schema_resolver(identifier); - } -} - -static auto test_resolver_draft6(std::string_view identifier) - -> std::optional { - if (identifier == "https://www.sourcemeta.com/recursive") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-06/schema#", - "$id": "https://www.sourcemeta.com/recursive", - "properties": { - "foo": { "$ref": "#" } - } - })JSON"); - } else if (identifier == "https://example.com/meta/1.json") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://example.com/meta/2.json", - "$id": "https://example.com/meta/1.json" - })JSON"); - } else if (identifier == "https://example.com/meta/2.json") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-06/schema#", - "$id": "https://example.com/meta/2.json" - })JSON"); - } else { - return sourcemeta::core::schema_resolver(identifier); - } -} - -static auto test_resolver_draft4(std::string_view identifier) - -> std::optional { - if (identifier == "https://www.sourcemeta.com/recursive") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "https://www.sourcemeta.com/recursive", - "properties": { - "foo": { "$ref": "#" } - } - })JSON"); - } else if (identifier == "https://example.com/meta/1.json") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://example.com/meta/2.json", - "id": "https://example.com/meta/1.json" - })JSON"); - } else if (identifier == "https://example.com/meta/2.json") { - return sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "https://example.com/meta/2.json" - })JSON"); - } else { - return sourcemeta::core::schema_resolver(identifier); - } -} - -TEST(EditorSchema, 2020_12_bundle) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$id": "https://www.sourcemeta.com/top-level", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": { - "$ref": "recursive#/properties/foo" - }, - "baz": { - "$ref": "https://example.com/baz-anchor#baz" - } - } - })JSON"); - - sourcemeta::core::bundle(document, sourcemeta::core::schema_walker, - test_resolver_2020_12); - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_2020_12); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": { - "$ref": "#/$defs/https:~1~1www.sourcemeta.com~1recursive/properties/foo" - }, - "baz": { - "$ref": "#/$defs/https:~1~1example.com~1baz-anchor/$defs/baz" - } - }, - "$defs": { - "https://www.sourcemeta.com/recursive": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": { - "$ref": "#/$defs/https:~1~1www.sourcemeta.com~1recursive" - } - } - }, - "https://example.com/baz-anchor": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "baz": { - "type": "string" - } - } - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, 2020_12_static_dynamic_reference) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$id": "https://www.sourcemeta.com/top-level", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": { - "$dynamicRef": "https://example.com/foo/bar" - } - } - })JSON"); - - sourcemeta::core::bundle(document, sourcemeta::core::schema_walker, - test_resolver_2020_12); - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_2020_12); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": { - "$ref": "#/$defs/https:~1~1example.com~1foo~1bar" - } - }, - "$defs": { - "https://example.com/foo/bar": { - "$schema": "https://json-schema.org/draft/2020-12/schema" - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, 2020_12_dynamic_reference_to_static_anchor) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$id": "https://www.sourcemeta.com/top-level", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$anchor": "foo", - "properties": { - "foo": { - "$dynamicRef": "#foo" - } - } - })JSON"); - - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_2020_12); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": { - "$ref": "#" - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, 2020_12_dynamic_anchors_1) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$id": "https://www.sourcemeta.com/top-level", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$dynamicAnchor": "meta", - "properties": { - "foo": { - "$dynamicRef": "#meta" - } - }, - "$defs": { - "nested": { - "$id": "https://www.sourcemeta.com/nested", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$dynamicRef": "#meta", - "$defs": { - "default": { - "$dynamicAnchor": "meta" - } - } - } - } - })JSON"); - - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_2020_12); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": { - "$ref": "#" - } - }, - "$defs": { - "nested": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$ref": "#", - "$defs": { - "default": {} - } - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, 2020_12_bundle_boolean_subschema) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$id": "https://www.sourcemeta.com/top-level", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": true - } - })JSON"); - - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_2020_12); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": true - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, 2020_12_default_base_dialect) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$id": "https://www.sourcemeta.com/top-level", - "properties": { - "foo": true - } - })JSON"); - - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_2020_12, - "https://json-schema.org/draft/2020-12/schema"); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": true - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, 2020_12_default_dialect) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$id": "https://www.sourcemeta.com/top-level", - "properties": { - "foo": true - } - })JSON"); - - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_2020_12, - "https://example.com/meta/1.json"); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": true - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, 2020_12_bundle_metaschema) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://example.com/meta/1.json", - "type": "string" - })JSON"); - - sourcemeta::core::bundle(document, sourcemeta::core::schema_walker, - test_resolver_2020_12); - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_2020_12); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string", - "$defs": { - "https://example.com/meta/1.json": { - "$schema": "https://json-schema.org/draft/2020-12/schema" - }, - "https://example.com/meta/2.json": { - "$schema": "https://json-schema.org/draft/2020-12/schema" - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, 2019_09_bundle) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$id": "https://www.sourcemeta.com/top-level", - "$schema": "https://json-schema.org/draft/2019-09/schema", - "properties": { - "foo": { - "$ref": "recursive#/properties/foo" - }, - "baz": { - "$ref": "https://example.com/baz-anchor#baz" - } - } - })JSON"); - - sourcemeta::core::bundle(document, sourcemeta::core::schema_walker, - test_resolver_2019_09); - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_2019_09); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "properties": { - "foo": { - "$ref": "#/$defs/https:~1~1www.sourcemeta.com~1recursive/properties/foo" - }, - "baz": { - "$ref": "#/$defs/https:~1~1example.com~1baz-anchor/$defs/baz" - } - }, - "$defs": { - "https://www.sourcemeta.com/recursive": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "properties": { - "foo": { - "$ref": "#/$defs/https:~1~1www.sourcemeta.com~1recursive" - } - } - }, - "https://example.com/baz-anchor": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "baz": { - "type": "string" - } - } - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, 2019_09_bundle_metaschema) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://example.com/meta/1.json", - "type": "string" - })JSON"); - - sourcemeta::core::bundle(document, sourcemeta::core::schema_walker, - test_resolver_2019_09); - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_2019_09); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "type": "string", - "$defs": { - "https://example.com/meta/1.json": { - "$schema": "https://json-schema.org/draft/2019-09/schema" - }, - "https://example.com/meta/2.json": { - "$schema": "https://json-schema.org/draft/2019-09/schema" - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, draft7_bundle) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$id": "https://www.sourcemeta.com/top-level", - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "foo": { - "$ref": "recursive#/properties/foo" - } - } - })JSON"); - - sourcemeta::core::bundle(document, sourcemeta::core::schema_walker, - test_resolver_draft7); - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_draft7); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "foo": { - "$ref": "#/definitions/https:~1~1www.sourcemeta.com~1recursive/properties/foo" - } - }, - "definitions": { - "https://www.sourcemeta.com/recursive": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "foo": { - "$ref": "#/definitions/https:~1~1www.sourcemeta.com~1recursive" - } - } - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, 2019_09_static_recursive_reference) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$id": "https://www.sourcemeta.com/top-level", - "$schema": "https://json-schema.org/draft/2019-09/schema", - "properties": { - "foo": { - "$recursiveRef": "#" - } - } - })JSON"); - - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_2020_12); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "properties": { - "foo": { - "$ref": "#" - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, 2019_09_recursive_anchors_1) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$id": "https://www.sourcemeta.com/top-level", - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$recursiveAnchor": true, - "properties": { - "foo": { - "$recursiveRef": "#" - } - }, - "$defs": { - "nested": { - "$id": "https://www.sourcemeta.com/nested", - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$recursiveRef": "#", - "$defs": { - "default": { - "$recursiveAnchor": true - } - } - } - } - })JSON"); - - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_2020_12); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "properties": { - "foo": { - "$ref": "#" - } - }, - "$defs": { - "nested": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$ref": "#", - "$defs": { - "default": {} - } - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, draft7_bundle_metaschema) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://example.com/meta/1.json", - "type": "string" - })JSON"); - - sourcemeta::core::bundle(document, sourcemeta::core::schema_walker, - test_resolver_draft7); - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_draft7); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "string", - "definitions": { - "https://example.com/meta/1.json": { - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "https://example.com/meta/2.json": { - "$schema": "http://json-schema.org/draft-07/schema#" - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, draft6_bundle) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$id": "https://www.sourcemeta.com/top-level", - "$schema": "http://json-schema.org/draft-06/schema#", - "properties": { - "foo": { - "$ref": "recursive#/properties/foo" - } - } - })JSON"); - - sourcemeta::core::bundle(document, sourcemeta::core::schema_walker, - test_resolver_draft6); - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_draft6); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-06/schema#", - "properties": { - "foo": { - "$ref": "#/definitions/https:~1~1www.sourcemeta.com~1recursive/properties/foo" - } - }, - "definitions": { - "https://www.sourcemeta.com/recursive": { - "$schema": "http://json-schema.org/draft-06/schema#", - "properties": { - "foo": { - "$ref": "#/definitions/https:~1~1www.sourcemeta.com~1recursive" - } - } - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, draft6_bundle_metaschema) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://example.com/meta/1.json", - "type": "string" - })JSON"); - - sourcemeta::core::bundle(document, sourcemeta::core::schema_walker, - test_resolver_draft6); - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_draft6); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-06/schema#", - "type": "string", - "definitions": { - "https://example.com/meta/1.json": { - "$schema": "http://json-schema.org/draft-06/schema#" - }, - "https://example.com/meta/2.json": { - "$schema": "http://json-schema.org/draft-06/schema#" - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, draft4_bundle) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "id": "https://www.sourcemeta.com/top-level", - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "foo": { - "$ref": "recursive#/properties/foo" - } - } - })JSON"); - - sourcemeta::core::bundle(document, sourcemeta::core::schema_walker, - test_resolver_draft4); - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_draft4); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "foo": { - "$ref": "#/definitions/https:~1~1www.sourcemeta.com~1recursive/properties/foo" - } - }, - "definitions": { - "https://www.sourcemeta.com/recursive": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "foo": { - "$ref": "#/definitions/https:~1~1www.sourcemeta.com~1recursive" - } - } - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - -TEST(EditorSchema, draft4_bundle_metaschema) { - auto document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://example.com/meta/1.json", - "type": "string" - })JSON"); - - sourcemeta::core::bundle(document, sourcemeta::core::schema_walker, - test_resolver_draft4); - sourcemeta::core::for_editor(document, sourcemeta::core::schema_walker, - test_resolver_draft4); - - const auto expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "string", - "definitions": { - "https://example.com/meta/1.json": { - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "https://example.com/meta/2.json": { - "$schema": "http://json-schema.org/draft-04/schema#" - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} diff --git a/test/packaging/find_package/CMakeLists.txt b/test/packaging/find_package/CMakeLists.txt index b106c4715..9a91d4603 100644 --- a/test/packaging/find_package/CMakeLists.txt +++ b/test/packaging/find_package/CMakeLists.txt @@ -23,7 +23,6 @@ target_link_libraries(core_hello PRIVATE sourcemeta::core::yaml) target_link_libraries(core_hello PRIVATE sourcemeta::core::gzip) target_link_libraries(core_hello PRIVATE sourcemeta::core::html) target_link_libraries(core_hello PRIVATE sourcemeta::core::markdown) -target_link_libraries(core_hello PRIVATE sourcemeta::core::editorschema) target_link_libraries(core_hello PRIVATE sourcemeta::core::options) target_link_libraries(core_hello PRIVATE sourcemeta::core::preprocessor) target_link_libraries(core_hello PRIVATE sourcemeta::core::jsonrpc) diff --git a/test/packaging/find_package/hello.cc b/test/packaging/find_package/hello.cc index 7f0cdfd92..70f967c20 100644 --- a/test/packaging/find_package/hello.cc +++ b/test/packaging/find_package/hello.cc @@ -1,5 +1,4 @@ #include -#include #include #include #include