@@ -56,8 +56,10 @@ class TypeWithApplicatorToAllOf final : public SchemaTransformRule {
5656 const bool has_structural{has_type || has_enum || has_ref};
5757
5858 bool modern_ref_needs_wrapping{false };
59+ this ->ref_annotations_only_ = false ;
5960 if (this ->has_modern_ref_ || this ->has_dynamic_ref_ ||
6061 this ->has_recursive_ref_ ) {
62+ this ->ref_annotations_only_ = true ;
6163 for (const auto &entry : schema.as_object ()) {
6264 if (entry.first == " $ref" || entry.first == " $dynamicRef" ||
6365 entry.first == " $recursiveRef" ) {
@@ -68,7 +70,12 @@ class TypeWithApplicatorToAllOf final : public SchemaTransformRule {
6870 keyword_type != sourcemeta::core::SchemaKeywordType::Annotation &&
6971 keyword_type != sourcemeta::core::SchemaKeywordType::Comment) {
7072 modern_ref_needs_wrapping = true ;
71- break ;
73+ if (keyword_type != sourcemeta::core::SchemaKeywordType::Reference &&
74+ keyword_type != sourcemeta::core::SchemaKeywordType::Other &&
75+ keyword_type !=
76+ sourcemeta::core::SchemaKeywordType::LocationMembers) {
77+ this ->ref_annotations_only_ = false ;
78+ }
7279 }
7380 }
7481 }
@@ -94,9 +101,10 @@ class TypeWithApplicatorToAllOf final : public SchemaTransformRule {
94101 }
95102 }
96103
97- ONLY_CONTINUE_IF ((has_structural && applicator_count >= 1 ) ||
98- applicator_count >= 2 || modern_ref_needs_wrapping ||
99- has_orphaned_typed_keywords);
104+ ONLY_CONTINUE_IF (
105+ (has_structural && applicator_count >= 1 ) || applicator_count >= 2 ||
106+ modern_ref_needs_wrapping ||
107+ (has_orphaned_typed_keywords && !this ->ref_annotations_only_ ));
100108
101109 this ->strategy_ = Strategy::FullRestructure;
102110 this ->applicators_with_refs_ = 0 ;
@@ -222,8 +230,10 @@ class TypeWithApplicatorToAllOf final : public SchemaTransformRule {
222230 entry.first == " allOf" || entry.first == " oneOf" ||
223231 entry.first == " $schema" || entry.first == " id" ||
224232 entry.first == " $id" || entry.first == " definitions" ||
225- entry.first == " $defs" || entry.first == " dependencies" ||
226- entry.first == " dependentSchemas" ||
233+ entry.first == " $defs" || entry.first == " $anchor" ||
234+ entry.first == " $dynamicAnchor" ||
235+ entry.first == " $recursiveAnchor" || entry.first == " $vocabulary" ||
236+ entry.first == " dependencies" || entry.first == " dependentSchemas" ||
227237 (this ->has_if_then_else_ &&
228238 (entry.first == " if" || entry.first == " then" ||
229239 entry.first == " else" )) ||
@@ -253,6 +263,25 @@ class TypeWithApplicatorToAllOf final : public SchemaTransformRule {
253263 schema.assign (" allOf" , std::move (new_allof));
254264 }
255265
266+ if (this ->has_modern_ref_ && schema.defines (" $ref" )) {
267+ auto branch{JSON::make_object ()};
268+ branch.assign (" $ref" , schema.at (" $ref" ));
269+ schema.at (" allOf" ).push_back (std::move (branch));
270+ schema.erase (" $ref" );
271+ }
272+ if (this ->has_dynamic_ref_ && schema.defines (" $dynamicRef" )) {
273+ auto branch{JSON::make_object ()};
274+ branch.assign (" $dynamicRef" , schema.at (" $dynamicRef" ));
275+ schema.at (" allOf" ).push_back (std::move (branch));
276+ schema.erase (" $dynamicRef" );
277+ }
278+ if (this ->has_recursive_ref_ && schema.defines (" $recursiveRef" )) {
279+ auto branch{JSON::make_object ()};
280+ branch.assign (" $recursiveRef" , schema.at (" $recursiveRef" ));
281+ schema.at (" allOf" ).push_back (std::move (branch));
282+ schema.erase (" $recursiveRef" );
283+ }
284+
256285 for (const auto &applicator : APPLICATORS_WITHOUT_ALLOF) {
257286 if (!schema.defines (applicator)) {
258287 continue ;
@@ -291,16 +320,34 @@ class TypeWithApplicatorToAllOf final : public SchemaTransformRule {
291320 if (this ->has_modern_ref_ && schema.defines (" $ref" )) {
292321 auto branch{JSON::make_object ()};
293322 branch.assign (" $ref" , schema.at (" $ref" ));
323+ if (this ->ref_annotations_only_ && !this ->typed_keywords_ .empty ()) {
324+ for (const auto &entry : typed_branch.as_object ()) {
325+ branch.assign (entry.first , entry.second );
326+ }
327+ this ->typed_keywords_ .clear ();
328+ }
294329 new_allof.push_back (std::move (branch));
295330 }
296331 if (this ->has_dynamic_ref_ && schema.defines (" $dynamicRef" )) {
297332 auto branch{JSON::make_object ()};
298333 branch.assign (" $dynamicRef" , schema.at (" $dynamicRef" ));
334+ if (this ->ref_annotations_only_ && !this ->typed_keywords_ .empty ()) {
335+ for (const auto &entry : typed_branch.as_object ()) {
336+ branch.assign (entry.first , entry.second );
337+ }
338+ this ->typed_keywords_ .clear ();
339+ }
299340 new_allof.push_back (std::move (branch));
300341 }
301342 if (this ->has_recursive_ref_ && schema.defines (" $recursiveRef" )) {
302343 auto branch{JSON::make_object ()};
303344 branch.assign (" $recursiveRef" , schema.at (" $recursiveRef" ));
345+ if (this ->ref_annotations_only_ && !this ->typed_keywords_ .empty ()) {
346+ for (const auto &entry : typed_branch.as_object ()) {
347+ branch.assign (entry.first , entry.second );
348+ }
349+ this ->typed_keywords_ .clear ();
350+ }
304351 new_allof.push_back (std::move (branch));
305352 }
306353
@@ -342,6 +389,18 @@ class TypeWithApplicatorToAllOf final : public SchemaTransformRule {
342389 if (schema.defines (" $defs" )) {
343390 new_schema.assign (" $defs" , schema.at (" $defs" ));
344391 }
392+ if (schema.defines (" $anchor" )) {
393+ new_schema.assign (" $anchor" , schema.at (" $anchor" ));
394+ }
395+ if (schema.defines (" $dynamicAnchor" )) {
396+ new_schema.assign (" $dynamicAnchor" , schema.at (" $dynamicAnchor" ));
397+ }
398+ if (schema.defines (" $recursiveAnchor" )) {
399+ new_schema.assign (" $recursiveAnchor" , schema.at (" $recursiveAnchor" ));
400+ }
401+ if (schema.defines (" $vocabulary" )) {
402+ new_schema.assign (" $vocabulary" , schema.at (" $vocabulary" ));
403+ }
345404 if (schema.defines (" dependencies" )) {
346405 new_schema.assign (" dependencies" , schema.at (" dependencies" ));
347406 }
@@ -455,6 +514,7 @@ class TypeWithApplicatorToAllOf final : public SchemaTransformRule {
455514 mutable bool has_dynamic_ref_{false };
456515 mutable bool has_recursive_ref_{false };
457516 mutable bool has_unevaluated_{false };
517+ mutable bool ref_annotations_only_{false };
458518 mutable std::vector<std::string> typed_keywords_;
459519 mutable std::uint8_t applicator_indices_{0 };
460520 mutable std::uint8_t applicators_with_refs_{0 };
0 commit comments