Commit f08cbfef authored by Aiden Benner's avatar Aiden Benner Committed by Commit Bot

Add array support and type exceptions to generated native method object casting

Even though String is an object (and so being casted to jobject across
the jni boundary would make sense), the JNI spec gives special treatment for java
string types and they're casted to jstrings instead of jobjects. This
change makes sure Strings stay as Strings in the native method declaration.
Previously all non-primitive types would be casted to objects.

Also fixed a bug where void was being cast to object (this happened because
void is non-primitive).

Also adds better array support. Arrays with a primitive component type
will stay as primitive arrays but arrays with a non-primitive component type
will be casted to an object array.

Change-Id: If795bcddf7a38f051d0c6fb515e1dd320dd3f30d
Bug: 898261
Reviewed-on: https://chromium-review.googlesource.com/c/1297083
Commit-Queue: Aiden Benner <abenner@google.com>
Reviewed-by: default avataragrieve <agrieve@chromium.org>
Reviewed-by: default avatarEric Stevenson <estevenson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#602230}
parent 86d36046
......@@ -10,6 +10,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ArrayTypeName;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
......@@ -39,6 +40,9 @@ import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
/**
......@@ -76,6 +80,11 @@ public class JniProcessor extends AbstractProcessor {
// native method in GEN_JNI (prefixed with "M")
private static final int MAX_CHARS_FOR_HASHED_NATIVE_METHODS = 8;
// Types that are non-primitives and should not be
// casted to objects in native method declarations.
static final ImmutableSet JNI_OBJECT_TYPE_EXCEPTIONS =
ImmutableSet.of("java.lang.String", "void");
static String getNameOfWrapperClass(String containingClassName) {
return containingClassName + NATIVE_WRAPPER_CLASS_POSTFIX;
}
......@@ -376,6 +385,25 @@ public class JniProcessor extends AbstractProcessor {
copyMethodParamsAndReturnType(builder, method, false);
}
boolean shouldDowncastToObjectForJni(TypeName t) {
if (t.isPrimitive()) {
return false;
}
// There are some non-primitives that should not be downcasted.
return !JNI_OBJECT_TYPE_EXCEPTIONS.contains(t.toString());
}
TypeName toTypeName(TypeMirror t, boolean useJni) {
if (t.getKind() == TypeKind.ARRAY) {
return ArrayTypeName.of(toTypeName(((ArrayType) t).getComponentType(), useJni));
}
TypeName typeName = TypeName.get(t);
if (useJni && shouldDowncastToObjectForJni(typeName)) {
return TypeName.OBJECT;
}
return typeName;
}
/**
* Since some types may decay to objects in the native method
* this method returns a javadoc string that contains the
......@@ -406,22 +434,18 @@ public class JniProcessor extends AbstractProcessor {
}
void copyMethodParamsAndReturnType(
MethodSpec.Builder builder, ExecutableElement method, boolean useObjects) {
MethodSpec.Builder builder, ExecutableElement method, boolean useJniTypes) {
for (VariableElement param : method.getParameters()) {
builder.addParameter(createParamSpec(param, useObjects));
}
TypeName returnType = TypeName.get(method.getReturnType());
if (useObjects && !returnType.isPrimitive()) {
returnType = TypeName.OBJECT;
builder.addParameter(createParamSpec(param, useJniTypes));
}
TypeMirror givenReturnType = method.getReturnType();
TypeName returnType = toTypeName(givenReturnType, useJniTypes);
builder.returns(returnType);
}
ParameterSpec createParamSpec(VariableElement param, boolean useObject) {
TypeName paramType = TypeName.get(param.asType());
if (useObject && !paramType.isPrimitive()) {
paramType = TypeName.OBJECT;
}
ParameterSpec createParamSpec(VariableElement param, boolean useJniObjects) {
TypeName paramType = toTypeName(param.asType(), useJniObjects);
return ParameterSpec.builder(paramType, param.getSimpleName().toString())
.addModifiers(param.getModifiers())
.build();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment