diff --git a/fhircraft/fhir/resources/factory/builders/base.py b/fhircraft/fhir/resources/factory/builders/base.py index e33a9cdd..723db947 100644 --- a/fhircraft/fhir/resources/factory/builders/base.py +++ b/fhircraft/fhir/resources/factory/builders/base.py @@ -442,6 +442,7 @@ def resolve_type( def build_primitive_extension_placeholder( self, node: ElementNode, + name: str | None = None, ) -> FieldInformation: """ Build a placeholder field information for primitive type extensions. @@ -450,14 +451,16 @@ def build_primitive_extension_placeholder( Args: node: ElementNode representing the primitive FHIR element for which to create an extension placeholder. + name: When provided, use this name instead of ``node.name`` Returns: FieldInformation: Field information for the extension placeholder """ # Process the name for the placeholder field - original_name = f"_{node.name}" - placeholder_name = f"{node.name}_ext" + name = name if name is not None else node.name + original_name = f"_{name}" + placeholder_name = f"{name}_ext" safe_placeholder_name, ext_alias = self.handle_python_keyword(placeholder_name) # Get the appropriate Element type for the placeholder field @@ -470,7 +473,7 @@ def build_primitive_extension_placeholder( default=None, alias=original_name, validation_alias=ext_alias, - description=f"Placeholder element for {node.name} extensions", + description=f"Placeholder element for {name} extensions", ) return info diff --git a/fhircraft/fhir/resources/factory/builders/type_choice.py b/fhircraft/fhir/resources/factory/builders/type_choice.py index 893e41fe..ed1f1347 100644 --- a/fhircraft/fhir/resources/factory/builders/type_choice.py +++ b/fhircraft/fhir/resources/factory/builders/type_choice.py @@ -54,7 +54,9 @@ def build(self, node: ElementNode, _: DefinitionIndex) -> Build: # Add primitive extension field if applicable if field_type_info.requires_primitive_extension: - placeholder = self.build_primitive_extension_placeholder(node) + placeholder = self.build_primitive_extension_placeholder( + node, name=safe_name + ) build.fields.append(placeholder) # Type-choice validator & property go on the first FieldBuild diff --git a/test/test_fhir_resources_factory_builders_type_choice.py b/test/test_fhir_resources_factory_builders_type_choice.py index 6dd722aa..5a986115 100644 --- a/test/test_fhir_resources_factory_builders_type_choice.py +++ b/test/test_fhir_resources_factory_builders_type_choice.py @@ -214,7 +214,7 @@ def test_build__primitive_type_adds_ext_placeholder(builder, index): node = make_node("value", type_codes=["string"]) result = builder.build(node, index) names = [f.name for f in result.fields] - assert "value_ext" in names + assert "valueString_ext" in names def test_build__non_primitive_type_does_not_add_placeholder(builder, index): @@ -229,8 +229,51 @@ def test_build__non_primitive_type_does_not_add_placeholder(builder, index): def test_build__primitive_placeholder_alias_is_underscore_name(builder, index): node = make_node("value", type_codes=["string"]) result = builder.build(node, index) - placeholder = next(f for f in result.fields if f.name == "value_ext") - assert placeholder.alias == "_value" + placeholder = next(f for f in result.fields if f.name == "valueString_ext") + assert placeholder.alias == "_valueString" + + +def test_build__primitive_type_ext_placeholder_does_not_use_base_name(builder, index): + """No base-name _ext placeholder should be emitted for a type-choice element.""" + node = make_node("value", type_codes=["string"]) + result = builder.build(node, index) + names = [f.name for f in result.fields] + assert "value_ext" not in names + + +def test_build__primitive_type_ext_placeholder_uses_typed_name(builder, index): + """Ext placeholder for a type-choice primitive must use the full typed field name.""" + node = make_node("value", type_codes=["string"]) + result = builder.build(node, index) + names = [f.name for f in result.fields] + assert "valueString_ext" in names + + +def test_build__primitive_type_ext_placeholder_alias_uses_typed_name(builder, index): + """Ext placeholder alias must be the underscore-prefixed typed field name.""" + node = make_node("value", type_codes=["string"]) + result = builder.build(node, index) + placeholder = next(f for f in result.fields if f.name == "valueString_ext") + assert placeholder.alias == "_valueString" + + +def test_build__two_primitives_ext_placeholders_use_typed_names(builder, index): + """Each primitive type choice variant gets its own correctly named _ext placeholder.""" + node = make_node("value", type_codes=["string", "boolean"]) + result = builder.build(node, index) + ext_names = [f.name for f in result.fields if f.name.endswith("_ext")] + assert "valueString_ext" in ext_names + assert "valueBoolean_ext" in ext_names + assert "value_ext" not in ext_names + + +def test_build__different_base_name_primitive_ext_uses_typed_name(builder, index): + """The correctly-typed _ext placeholder is generated regardless of the base name.""" + node = make_node("effective", type_codes=["dateTime"]) + result = builder.build(node, index) + names = [f.name for f in result.fields] + assert "effectiveDateTime_ext" in names + assert "effective_ext" not in names def test_build__two_types_one_primitive_adds_exactly_one_placeholder(builder, index):