def test_parse_java_type_with_generic(java_type_prefix, generic_prefix,
                                      generic_name):
    type_element = ET.Element("type")
    type_element.text = f"{java_type_prefix}Position<{generic_prefix or ''}{generic_name}>"

    driver_mock = MagicMock()
    type_ref = JavaTypeParser.parse_xml(type_element, driver=driver_mock)

    assert type_ref is not None
    assert not type_ref.id
    assert not type_ref.kind
    assert type_ref.language == "java"
    assert type_ref.name == "Position"
    assert_equal_or_none_if_empty(type_ref.prefix, java_type_prefix)
    assert not type_ref.suffix
    assert len(type_ref.nested) == 1
    assert type_ref.nested[0].prefix == generic_prefix
    assert type_ref.nested[0].name == generic_name.strip()
    assert not type_ref.nested[0].suffix

    if generic_name.strip() == "T":
        driver_mock.unresolved_ref.assert_called_with(type_ref)
        assert driver_mock.unresolved_ref.call_count == 1
    else:
        assert (sorted([
            args[0].name
            for args, _ in driver_mock.unresolved_ref.call_args_list
        ]) == sorted(["Position", generic_name.strip()]))
def test_parse_java_type_with_nested_wildcard_generic():
    type_element = ET.Element("type")
    type_element.text = "Position<? extends Getter<?>>"

    driver_mock = MagicMock()
    type_ref = JavaTypeParser.parse_xml(type_element, driver=driver_mock)

    assert type_ref is not None
    assert type_ref.language == "java"
    assert not type_ref.prefix
    assert type_ref.name == "Position"
    assert not type_ref.suffix
    assert len(type_ref.nested) == 1

    assert type_ref.nested[0].prefix == "? extends "
    assert type_ref.nested[0].name == "Getter"
    assert not type_ref.nested[0].suffix
    assert len(type_ref.nested[0].nested) == 1

    assert not type_ref.nested[0].nested[0].prefix
    assert type_ref.nested[0].nested[0].name == "?"
    assert not type_ref.nested[0].nested[0].suffix

    assert (sorted([
        args[0].name for args, _ in driver_mock.unresolved_ref.call_args_list
    ]) == sorted(["Position", "Getter"]))
def test_parse_java_type_with_separate_wildcard_bounds():
    type_element = ET.Element("type")
    type_element.text = "<T extends Getter<?>> T"

    driver_mock = MagicMock()
    type_ref = JavaTypeParser.parse_xml(type_element, driver=driver_mock)

    assert type_ref is not None
    assert type_ref.language == "java"
    assert type_ref.prefix == "<T extends Getter<?>> "
    assert type_ref.name == "T"
    assert not type_ref.suffix
    assert not type_ref.nested

    driver_mock.unresolved_ref.assert_not_called()
def test_parse_java_type_with_original_annotation(java_type_prefix):
    type_element = ET.Element("type")
    type_element.text = f"{java_type_prefix}@Nullable Data"

    driver_mock = MagicMock()
    type_ref = JavaTypeParser.parse_xml(type_element, driver=driver_mock)
    driver_mock.unresolved_ref.assert_called_once_with(type_ref)

    assert type_ref is not None
    assert type_ref.id is None
    assert type_ref.kind is None
    assert type_ref.language == "java"
    assert type_ref.name == "Data"
    assert type_ref.prefix == f"{java_type_prefix}@Nullable "
    assert not type_ref.suffix
    assert not type_ref.nested
def test_parse_java_type_from_text_simple(java_type_prefix):
    type_element = ET.Element("type")
    type_element.text = f"{java_type_prefix}double"

    driver_mock = MagicMock()
    type_ref = JavaTypeParser.parse_xml(type_element, driver=driver_mock)
    driver_mock.unresolved_ref.assert_not_called()  # built-in type

    assert type_ref is not None
    assert type_ref.id is None
    assert type_ref.kind is None
    assert type_ref.language == "java"
    assert type_ref.name == "double"
    assert_equal_or_none_if_empty(type_ref.prefix, java_type_prefix)
    assert not type_ref.suffix
    assert not type_ref.nested
def test_java_type_parser__adapt_tokens__separate_wildcard_bounds_are_ignored(
        tokens, expected):
    assert JavaTypeParser.adapt_tokens(tokens) == expected
def test_java_type_parser__adapt_tokens__invalid_tokens(tokens, expected):
    assert JavaTypeParser.adapt_tokens(tokens) == expected
def test_java_type_parser__adapt_tokens__wildcard_bounds(tokens, expected):
    assert JavaTypeParser.adapt_tokens(tokens) == expected