Skip to content

Commit

Permalink
Correctly generate type names for Java capture types.
Browse files Browse the repository at this point in the history
Fixes issue where a capture type was not cast correctly before invoking a method on it.
	Change on 2015/06/16 by kstanger <kstanger@google.com>
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=96109587
  • Loading branch information
kstanger committed Jun 17, 2015
1 parent 9e9a88b commit 388dabf
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 14 deletions.
Expand Up @@ -42,6 +42,7 @@

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -722,8 +723,7 @@ public String getObjCType(ITypeBinding type) {
return getObjCTypeInner(type, null, false);
}

private String getObjCTypeInner(
ITypeBinding type, String qualifiers, boolean expandTypeVariables) {
private String getObjCTypeInner(ITypeBinding type, String qualifiers, boolean expandBounds) {
String objCType;
if (type instanceof PointerTypeBinding) {
String pointeeQualifiers = null;
Expand All @@ -735,23 +735,20 @@ private String getObjCTypeInner(
}
}
objCType = getObjCTypeInner(
((PointerTypeBinding) type).getPointeeType(), pointeeQualifiers, expandTypeVariables);
((PointerTypeBinding) type).getPointeeType(), pointeeQualifiers, expandBounds);
objCType = objCType.endsWith("*") ? objCType + "*" : objCType + " *";
} else if (type.isTypeVariable()) {
if (expandTypeVariables) {
ITypeBinding[] bounds = type.getTypeBounds();
while (bounds.length > 0 && bounds[0].isTypeVariable()) {
type = bounds[0];
bounds = type.getTypeBounds();
}
} else if (type.isTypeVariable() || type.isCapture()) {
if (expandBounds) {
List<ITypeBinding> bounds = Lists.newArrayList();
collectBounds(type, bounds);
objCType = constructObjCType(bounds);
} else {
objCType = ID_TYPE;
}
} else if (type.isPrimitive()) {
objCType = getPrimitiveObjCType(type);
} else {
objCType = constructObjCType(type.getErasure());
objCType = constructObjCType(Collections.singletonList(type));
}
if (qualifiers != null) {
qualifiers = qualifiers.trim();
Expand All @@ -762,11 +759,25 @@ private String getObjCTypeInner(
return objCType;
}

private String constructObjCType(ITypeBinding... types) {
private boolean collectBounds(ITypeBinding type, Collection<ITypeBinding> bounds) {
ITypeBinding[] boundsArr = type.getTypeBounds();
if (boundsArr.length == 0) {
return false;
}
for (ITypeBinding bound : boundsArr) {
if (!collectBounds(bound, bounds)) {
bounds.add(bound);
}
}
return true;
}

private String constructObjCType(Iterable<ITypeBinding> types) {
String classType = null;
List<String> interfaces = Lists.newArrayListWithCapacity(types.length);
List<String> interfaces = Lists.newArrayList();
for (ITypeBinding type : types) {
if (type == null || isIdType(type) || typeEnv.isJavaVoidType(type)) {
type = type.getErasure();
if (isIdType(type) || typeEnv.isJavaVoidType(type)) {
continue;
}
if (type.isInterface()) {
Expand Down
Expand Up @@ -112,4 +112,14 @@ public void testDerivedTypeVariableInvocation() throws IOException {
// Verify that a cast can be added to a QualifiedName node.
assertTranslation(translation, "return ((Test_DerivedFoo *) foo_)->myInt_;");
}

public void testCapturedType() throws IOException {
String translation = translateSourceFile(
"class Test {"
+ " interface Bar { void bar(); }"
+ " static class Foo<T extends Bar> { T get() { return null; } }"
+ " void test(Foo<?> foo) { foo.get().bar(); } }", "Test", "Test.m");
assertTranslation(translation,
"[((id<Test_Bar>) nil_chk([((Test_Foo *) nil_chk(foo)) get])) bar];");
}
}

0 comments on commit 388dabf

Please sign in to comment.