Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -787,17 +787,18 @@ private NativeType calculateNativeType(
return new NativeType(builder.toString(), null, null, referencedTypes);
}

private String toNativeType(
private PrintableNativeType toNativeType(
TypeMirror typeMirror, ExecutableElement methodExecutable, List<TypeMirror> referencedTypes) {
String fullyQualifiedNameJavaName = TypeUtil.getQualifiedName(typeMirror);
String nativeType = JAVA_TO_NATIVE_TYPE_MAP.get(fullyQualifiedNameJavaName);
if (nativeType != null) {
return nativeType;
return new PrintableNativeType(nativeType, false);
}
TypeElement typeElement = TypeUtil.asTypeElement(typeMirror);
if (typeElement != null) {
referencedTypes.add(typeMirror);
return nameTable.getFullName(typeElement);
return new PrintableNativeType(
nameTable.getFullName(typeElement), TypeUtil.isInterface(typeMirror));
}
throw new IllegalArgumentException(
"Unsupported type: " + fullyQualifiedNameJavaName + " in method: " + methodExecutable);
Expand All @@ -820,6 +821,8 @@ private boolean isTypeSupported(TypeMirror typeMirror) {
* <li>{@code List<String>} becomes {@code NSArray<NSString *> *}
* <li>{@code Map<Integer, String>} becomes {@code NSDictionary<NSNumber *, NSString *> *}
* <li>{@code Set<List<String>>} becomes {@code NSSet<NSArray<NSString *> *> *}
* <li>{@code JavaInterface} becomes {@code id<JavaInterface>}
* <li>{@code List<JavaInterface>} becomes {@code NSArray<id<JavaInterface>> *}
* </ul>
*/
private class NativeTypeVisitor extends SimpleTypeVisitor9<Void, StringBuilder> {
Expand All @@ -835,13 +838,21 @@ private NativeTypeVisitor(

@Override
public Void visitDeclared(DeclaredType type, StringBuilder builder) {
builder.append(toNativeType(type, methodExecutable, referencedTypes));
PrintableNativeType nativeType = toNativeType(type, methodExecutable, referencedTypes);
if (nativeType.isUntranslatedInterface) {
builder.append("id<");
}
builder.append(nativeType.nativeTypeName);
List<? extends TypeMirror> typeArguments = type.getTypeArguments();
if (options.asObjCGenericDecl() && !typeArguments.isEmpty()) {
String typeArgsString = buildTypeArgumentString(typeArguments);
builder.append("<").append(typeArgsString).append(">");
}
builder.append(" *");
if (nativeType.isUntranslatedInterface) {
builder.append(">");
} else {
builder.append(" *");
}
return null;
}

Expand Down Expand Up @@ -937,4 +948,14 @@ abstract AdapterLookup.ConverterMatch findParamConverter(
abstract TypeMirror getReturnCastType(
TypeMirror originalMethodReturnType, TypeMirror adapterReturnType);
}

private static final class PrintableNativeType {
private final String nativeTypeName;
private final boolean isUntranslatedInterface;

PrintableNativeType(String nativeTypeName, boolean isUntranslatedInterface) {
this.nativeTypeName = nativeTypeName;
this.isUntranslatedInterface = isUntranslatedInterface;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1595,4 +1595,82 @@ public void setListSet(Set<List<String>> set) {}
assertThrows(Throwable.class, () -> translateSourceFile("FailList", "FailList.m"));
assertTrue(e.getMessage().contains("Exact converter required for mapped type"));
}

public void testInterfaceTypes() throws IOException {
addSourceFile(
"""
public interface TestInterface {
}
""",
"TestInterface.java");
addSourceFile(
"""
import com.google.j2objc.annotations.ObjectiveCKmpMethod;
import java.util.Set;
import java.util.List;
public class InterfaceUsage {
@ObjectiveCKmpMethod(selector="getInterface", adapter=Adapter.class)
public TestInterface getInterface() {
return null;
}

@ObjectiveCKmpMethod(selector="setInterface:", adapter=Adapter.class)
public void setInterface(TestInterface value) {
return;
}
}
""",
"InterfaceUsage.java");

String header = translateSourceFile("InterfaceUsage", "InterfaceUsage.h");
assertInTranslation(
header,
"""
- (id<TestInterface>)getInterface;
""");
assertInTranslation(
header,
"""
- (void)setInterface:(id<TestInterface>)value;
""");
}

public void testListOfInterface() throws IOException {
addSourceFile(
"""
public interface TestInterface {
}
""",
"TestInterface.java");
addSourceFile(
"""
import com.google.j2objc.annotations.ObjectiveCKmpMethod;
import java.util.Set;
import java.util.List;
public class ListOfInterface {
@ObjectiveCKmpMethod(selector="getListOfInterface", adapter=Adapter.class)
public List<TestInterface> getListOfInterface() {
return null;
}

@ObjectiveCKmpMethod(selector="setListOfInterface:", adapter=Adapter.class)
public void setListOfInterface(List<TestInterface> list) {
return;
}
}
""",
"ListOfInterface.java");

String header = translateSourceFile("ListOfInterface", "ListOfInterface.h");
assertInTranslation(
header,
"""
- (NSArray<id<TestInterface>> *)getListOfInterface;
""");
assertInTranslation(
header,
"""
- (void)setListOfInterface:(NSArray<id<TestInterface>> *)list;
""");
}
}