Commit ed11cb63 authored by Jacob Potter's avatar Jacob Potter

Merge branch 'FuegoFro-java_nullity_annotations'

parents a48d60eb 14af3b16
......@@ -28,6 +28,7 @@ android {
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.google.code.findbugs:jsr305:3.0.0'
}
task ndkBuild(type: Exec) {
......
......@@ -4,6 +4,8 @@
package com.dropbox.textsort;
import java.util.ArrayList;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class ItemList {
......@@ -11,10 +13,11 @@ public final class ItemList {
/*package*/ final ArrayList<String> mItems;
public ItemList(
ArrayList<String> items) {
@Nonnull ArrayList<String> items) {
this.mItems = items;
}
@Nonnull
public ArrayList<String> getItems() {
return mItems;
}
......
......@@ -4,10 +4,13 @@
package com.dropbox.textsort;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public abstract class SortItems {
public abstract void sort(SortOrder order, ItemList items);
public abstract void sort(@Nonnull SortOrder order, @Nonnull ItemList items);
@Nonnull
public static native SortItems createWithListener(TextboxListener listener);
public static final class CppProxy extends SortItems
......
......@@ -3,6 +3,9 @@
package com.dropbox.textsort;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public enum SortOrder {
ASCENDING,
DESCENDING,
......
......@@ -3,6 +3,9 @@
package com.dropbox.textsort;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public abstract class TextboxListener {
public abstract void update(ItemList items);
public abstract void update(@Nonnull ItemList items);
}
......@@ -53,6 +53,8 @@ fi
"$base_dir/../src/run-assume-built" \
--java-out "$temp_out/java" \
--java-package $java_package \
--java-nullable-annotation "javax.annotation.CheckForNull" \
--java-nonnull-annotation "javax.annotation.Nonnull" \
--ident-java-field mFooBar \
\
--cpp-out "$temp_out/cpp" \
......
......@@ -27,12 +27,15 @@ import scala.collection.mutable
class JavaGenerator(spec: Spec) extends Generator(spec) {
var javaAnnotationHeader = spec.javaAnnotation.map(pkg => '@' + pkg.split("\\.").last)
val javaNullableAnnotation = spec.javaNullableAnnotation.map(pkg => '@' + pkg.split("\\.").last)
val marshal = new JavaMarshal(spec)
class JavaRefs() {
var java = mutable.TreeSet[String]()
spec.javaAnnotation.foreach(pkg => java.add(pkg))
spec.javaNullableAnnotation.foreach(pkg => java.add(pkg))
spec.javaNonnullAnnotation.foreach(pkg => java.add(pkg))
def find(ty: TypeRef) { find(ty.resolved) }
def find(tm: MExpr) {
......@@ -89,6 +92,7 @@ class JavaGenerator(spec: Spec) extends Generator(spec) {
for (c <- consts) {
writeDoc(w, c.doc)
javaAnnotationHeader.foreach(w.wl)
marshal.nullityAnnotation(c.ty).foreach(w.wl)
w.w(s"public static final ${marshal.fieldType(c.ty)} ${idJava.const(c.ident)} = ")
writeJavaConst(w, c.ty, c.value)
w.wl(";")
......@@ -141,7 +145,11 @@ class JavaGenerator(spec: Spec) extends Generator(spec) {
skipFirst { w.wl }
writeDoc(w, m.doc)
val ret = marshal.returnType(m.ret)
val params = m.params.map(p => marshal.paramType(p.ty) + " " + idJava.local(p.ident))
val params = m.params.map(p => {
val nullityAnnotation = marshal.nullityAnnotation(p.ty).map(_ + " ").getOrElse("")
nullityAnnotation + marshal.paramType(p.ty) + " " + idJava.local(p.ident)
})
marshal.nullityAnnotation(m.ret).foreach(w.wl)
w.wl("public abstract " + ret + " " + idJava.method(m.ident) + params.mkString("(", ", ", ")") + throwException + ";")
}
for (m <- i.methods if m.static) {
......@@ -149,6 +157,7 @@ class JavaGenerator(spec: Spec) extends Generator(spec) {
writeDoc(w, m.doc)
val ret = marshal.returnType(m.ret)
val params = m.params.map(p => marshal.paramType(p.ty) + " " + idJava.local(p.ident))
marshal.nullityAnnotation(m.ret).foreach(w.wl)
w.wl("public static native "+ ret + " " + idJava.method(m.ident) + params.mkString("(", ", ", ")") + ";")
}
if (i.ext.cpp) {
......@@ -228,6 +237,7 @@ class JavaGenerator(spec: Spec) extends Generator(spec) {
val skipFirst = SkipFirst()
for (f <- r.fields) {
skipFirst { w.wl(",") }
marshal.nullityAnnotation(f.ty).map(annotation => w.w(annotation + " "))
w.w(marshal.typename(f.ty) + " " + idJava.local(f.ident))
}
w.wl(") {")
......@@ -243,6 +253,7 @@ class JavaGenerator(spec: Spec) extends Generator(spec) {
for (f <- r.fields) {
w.wl
writeDoc(w, f.doc)
marshal.nullityAnnotation(f.ty).foreach(w.wl)
w.w("public " + marshal.typename(f.ty) + " " + idJava.method("get_" + f.ident.name) + "()").braced {
w.wl("return " + idJava.field(f.ident) + ";")
}
......@@ -251,9 +262,10 @@ class JavaGenerator(spec: Spec) extends Generator(spec) {
if (r.derivingTypes.contains(DerivingType.Eq)) {
w.wl
w.wl("@Override")
w.w("public boolean equals(Object obj)").braced {
val nullableAnnotation = javaNullableAnnotation.map(_ + " ").getOrElse("")
w.w(s"public boolean equals(${nullableAnnotation}Object obj)").braced {
w.w(s"if (!(obj instanceof $self))").braced {
w.wl("return false;");
w.wl("return false;")
}
w.wl(s"$self other = ($self) obj;")
w.w(s"return ").nestedN(2) {
......
......@@ -6,6 +6,9 @@ import djinni.meta._
class JavaMarshal(spec: Spec) extends Marshal(spec) {
val javaNullableAnnotation = spec.javaNullableAnnotation.map(pkg => '@' + pkg.split("\\.").last)
val javaNonnullAnnotation = spec.javaNonnullAnnotation.map(pkg => '@' + pkg.split("\\.").last)
override def typename(tm: MExpr): String = toJavaType(tm, None)
def typename(name: String, ty: TypeDef): String = idJava.ty(name)
......@@ -36,6 +39,15 @@ class JavaMarshal(spec: Spec) extends Marshal(spec) {
case _ => List()
}
def nullityAnnotation(ty: Option[TypeRef]): Option[String] = ty.map(nullityAnnotation).getOrElse(None)
def nullityAnnotation(ty: TypeRef): Option[String] = {
ty.resolved.base match {
case MOptional => javaNullableAnnotation
case p: MPrimitive => None
case _ => javaNonnullAnnotation
}
}
private def toJavaType(tm: MExpr, packageName: Option[String]): String = {
def f(tm: MExpr, needRef: Boolean): String = {
tm.base match {
......
......@@ -35,6 +35,8 @@ object Main {
var javaPackage: Option[String] = None
var javaCppException: Option[String] = None
var javaAnnotation: Option[String] = None
var javaNullableAnnotation: Option[String] = None
var javaNonnullAnnotation: Option[String] = None
var jniOutFolder: Option[File] = None
var jniHeaderOutFolderOptional: Option[File] = None
var jniNamespace: String = "djinni_generated"
......@@ -88,6 +90,10 @@ object Main {
.text("The type for translated C++ exceptions in Java (default: java.lang.RuntimeException that is not checked)")
opt[String]("java-annotation").valueName("<annotation-class>").foreach(x => javaAnnotation = Some(x))
.text("Java annotation (@Foo) to place on all generated Java classes")
opt[String]("java-nullable-annotation").valueName("<nullable-annotation-class>").foreach(x => javaNullableAnnotation = Some(x))
.text("Java annotation (@Nullable) to place on all fields and return values that are optional")
opt[String]("java-nonnull-annotation").valueName("<nonnull-annotation-class>").foreach(x => javaNonnullAnnotation = Some(x))
.text("Java annotation (@Nonnull) to place on all fields and return values that are not optional")
note("")
opt[File]("cpp-out").valueName("<out-folder>").foreach(x => cppOutFolder = Some(x))
.text("The output folder for C++ files (Generator disabled if unspecified).")
......@@ -214,6 +220,8 @@ object Main {
javaIdentStyle,
javaCppException,
javaAnnotation,
javaNullableAnnotation,
javaNonnullAnnotation,
cppOutFolder,
cppHeaderOutFolder,
cppIncludePrefix,
......
......@@ -33,6 +33,8 @@ package object generatorTools {
javaIdentStyle: JavaIdentStyle,
javaCppException: Option[String],
javaAnnotation: Option[String],
javaNullableAnnotation: Option[String],
javaNonnullAnnotation: Option[String],
cppOutFolder: Option[File],
cppHeaderOutFolder: Option[File],
cppIncludePrefix: String,
......
......@@ -3,6 +3,9 @@
package com.dropbox.djinni.test;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class AssortedIntegers {
......@@ -27,10 +30,10 @@ public final class AssortedIntegers {
short sixteen,
int thirtytwo,
long sixtyfour,
Byte oEight,
Short oSixteen,
Integer oThirtytwo,
Long oSixtyfour) {
@CheckForNull Byte oEight,
@CheckForNull Short oSixteen,
@CheckForNull Integer oThirtytwo,
@CheckForNull Long oSixtyfour) {
this.mEight = eight;
this.mSixteen = sixteen;
this.mThirtytwo = thirtytwo;
......@@ -57,24 +60,28 @@ public final class AssortedIntegers {
return mSixtyfour;
}
@CheckForNull
public Byte getOEight() {
return mOEight;
}
@CheckForNull
public Short getOSixteen() {
return mOSixteen;
}
@CheckForNull
public Integer getOThirtytwo() {
return mOThirtytwo;
}
@CheckForNull
public Long getOSixtyfour() {
return mOSixtyfour;
}
@Override
public boolean equals(Object obj) {
public boolean equals(@CheckForNull Object obj) {
if (!(obj instanceof AssortedIntegers)) {
return false;
}
......
......@@ -3,9 +3,14 @@
package com.dropbox.djinni.test;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public abstract class ClientInterface {
/** Returns record of given string */
public abstract ClientReturnedRecord getRecord(long recordId, String utf8string, String misc);
@Nonnull
public abstract ClientReturnedRecord getRecord(long recordId, @Nonnull String utf8string, @CheckForNull String misc);
@Nonnull
public abstract String returnStr();
}
......@@ -3,6 +3,9 @@
package com.dropbox.djinni.test;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class ClientReturnedRecord {
......@@ -14,8 +17,8 @@ public final class ClientReturnedRecord {
public ClientReturnedRecord(
long recordId,
String content,
String misc) {
@Nonnull String content,
@CheckForNull String misc) {
this.mRecordId = recordId;
this.mContent = content;
this.mMisc = misc;
......@@ -25,10 +28,12 @@ public final class ClientReturnedRecord {
return mRecordId;
}
@Nonnull
public String getContent() {
return mContent;
}
@CheckForNull
public String getMisc() {
return mMisc;
}
......
......@@ -3,6 +3,9 @@
package com.dropbox.djinni.test;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public enum Color {
RED,
ORANGE,
......
......@@ -3,6 +3,9 @@
package com.dropbox.djinni.test;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class Constants {
public static final boolean BOOL_CONSTANT = true;
......@@ -17,10 +20,13 @@ public final class Constants {
public static final double F64_CONSTANT = 5.0;
@Nonnull
public static final String STRING_CONSTANT = "string-constant";
@CheckForNull
public static final Integer OPTIONAL_INTEGER_CONSTANT = 1;
@Nonnull
public static final Constants OBJECT_CONSTANT = new Constants(
I32_CONSTANT /* mSomeInteger */ ,
STRING_CONSTANT /* mSomeString */ );
......@@ -32,7 +38,7 @@ public final class Constants {
public Constants(
int someInteger,
String someString) {
@Nonnull String someString) {
this.mSomeInteger = someInteger;
this.mSomeString = someString;
}
......@@ -41,6 +47,7 @@ public final class Constants {
return mSomeInteger;
}
@Nonnull
public String getSomeString() {
return mSomeString;
}
......
......@@ -4,6 +4,8 @@
package com.dropbox.djinni.test;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public abstract class ConstantsInterface {
public static final boolean BOOL_CONSTANT = true;
......
......@@ -4,10 +4,13 @@
package com.dropbox.djinni.test;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public abstract class CppException {
public abstract int throwAnException();
@Nonnull
public static native CppException get();
public static final class CppProxy extends CppException
......
......@@ -4,6 +4,8 @@
package com.dropbox.djinni.test;
import java.util.Date;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class DateRecord {
......@@ -11,10 +13,11 @@ public final class DateRecord {
/*package*/ final Date mCreatedAt;
public DateRecord(
Date createdAt) {
@Nonnull Date createdAt) {
this.mCreatedAt = createdAt;
}
@Nonnull
public Date getCreatedAt() {
return mCreatedAt;
}
......
......@@ -5,6 +5,8 @@ package com.dropbox.djinni.test;
import java.util.Date;
import java.util.HashMap;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class MapDateRecord {
......@@ -12,10 +14,11 @@ public final class MapDateRecord {
/*package*/ final HashMap<String, Date> mDatesById;
public MapDateRecord(
HashMap<String, Date> datesById) {
@Nonnull HashMap<String, Date> datesById) {
this.mDatesById = datesById;
}
@Nonnull
public HashMap<String, Date> getDatesById() {
return mDatesById;
}
......
......@@ -5,6 +5,8 @@ package com.dropbox.djinni.test;
import java.util.ArrayList;
import java.util.HashMap;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class MapListRecord {
......@@ -12,10 +14,11 @@ public final class MapListRecord {
/*package*/ final ArrayList<HashMap<String, Long>> mMapList;
public MapListRecord(
ArrayList<HashMap<String, Long>> mapList) {
@Nonnull ArrayList<HashMap<String, Long>> mapList) {
this.mMapList = mapList;
}
@Nonnull
public ArrayList<HashMap<String, Long>> getMapList() {
return mMapList;
}
......
......@@ -4,6 +4,8 @@
package com.dropbox.djinni.test;
import java.util.HashMap;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class MapRecord {
......@@ -11,10 +13,11 @@ public final class MapRecord {
/*package*/ final HashMap<String, Long> mMap;
public MapRecord(
HashMap<String, Long> map) {
@Nonnull HashMap<String, Long> map) {
this.mMap = map;
}
@Nonnull
public HashMap<String, Long> getMap() {
return mMap;
}
......
......@@ -5,6 +5,8 @@ package com.dropbox.djinni.test;
import java.util.ArrayList;
import java.util.HashSet;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class NestedCollection {
......@@ -12,10 +14,11 @@ public final class NestedCollection {
/*package*/ final ArrayList<HashSet<String>> mSetList;
public NestedCollection(
ArrayList<HashSet<String>> setList) {
@Nonnull ArrayList<HashSet<String>> setList) {
this.mSetList = setList;
}
@Nonnull
public ArrayList<HashSet<String>> getSetList() {
return mSetList;
}
......
......@@ -4,6 +4,8 @@
package com.dropbox.djinni.test;
import java.util.ArrayList;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class PrimitiveList {
......@@ -11,10 +13,11 @@ public final class PrimitiveList {
/*package*/ final ArrayList<Long> mList;
public PrimitiveList(
ArrayList<Long> list) {
@Nonnull ArrayList<Long> list) {
this.mList = list;
}
@Nonnull
public ArrayList<Long> getList() {
return mList;
}
......
......@@ -3,6 +3,9 @@
package com.dropbox.djinni.test;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class RecordWithDerivings implements Comparable<RecordWithDerivings> {
......@@ -12,7 +15,7 @@ public final class RecordWithDerivings implements Comparable<RecordWithDerivings
public RecordWithDerivings(
int key1,
String key2) {
@Nonnull String key2) {
this.mKey1 = key1;
this.mKey2 = key2;
}
......@@ -21,12 +24,13 @@ public final class RecordWithDerivings implements Comparable<RecordWithDerivings
return mKey1;
}
@Nonnull
public String getKey2() {
return mKey2;
}
@Override
public boolean equals(Object obj) {
public boolean equals(@CheckForNull Object obj) {
if (!(obj instanceof RecordWithDerivings)) {
return false;
}
......
......@@ -3,6 +3,9 @@
package com.dropbox.djinni.test;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class RecordWithNestedDerivings implements Comparable<RecordWithNestedDerivings> {
......@@ -12,7 +15,7 @@ public final class RecordWithNestedDerivings implements Comparable<RecordWithNes
public RecordWithNestedDerivings(
int key,
RecordWithDerivings rec) {
@Nonnull RecordWithDerivings rec) {
this.mKey = key;
this.mRec = rec;
}
......@@ -21,12 +24,13 @@ public final class RecordWithNestedDerivings implements Comparable<RecordWithNes
return mKey;
}
@Nonnull
public RecordWithDerivings getRec() {
return mRec;
}
@Override
public boolean equals(Object obj) {
public boolean equals(@CheckForNull Object obj) {
if (!(obj instanceof RecordWithNestedDerivings)) {
return false;
}
......
......@@ -4,6 +4,8 @@
package com.dropbox.djinni.test;
import java.util.HashSet;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public final class SetRecord {
......@@ -11,10 +13,11 @@ public final class SetRecord {
/*package*/ final HashSet<String> mSet;
public SetRecord(
HashSet<String> set) {
@Nonnull HashSet<String> set) {
this.mSet = set;
}
@Nonnull
public HashSet<String> getSet() {
return mSet;
}
......
......@@ -5,28 +5,36 @@ package com.dropbox.djinni.test;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public abstract class TestHelpers {
@Nonnull
public static native SetRecord getSetRecord();
public static native boolean checkSetRecord(SetRecord rec);
@Nonnull
public static native PrimitiveList getPrimitiveList();
public static native boolean checkPrimitiveList(PrimitiveList pl);
@Nonnull
public static native NestedCollection getNestedCollection();
public static native boolean checkNestedCollection(NestedCollection nc);
@Nonnull
public static native HashMap<String, Long> getMap();
public static native boolean checkMap(HashMap<String, Long> m);
@Nonnull
public static native HashMap<String, Long> getEmptyMap();
public static native boolean checkEmptyMap(HashMap<String, Long> m);
@Nonnull
public static native MapListRecord getMapListRecord();
public static native boolean checkMapListRecord(MapListRecord m);
......@@ -39,8 +47,10 @@ public abstract class TestHelpers {
public static native void checkEnum(Color c);
@Nonnull
public static native Token tokenId(Token t);
@Nonnull
public static native Token createCppToken();
public static native void checkCppToken(Token t);
......@@ -49,11 +59,14 @@ public abstract class TestHelpers {
public static native void checkTokenType(Token t, String type);
@CheckForNull
public static native Integer returnNone();
/** Ensures that we generate integer translation code */
@Nonnull
public static native AssortedIntegers assortedIntegersId(AssortedIntegers i);
@Nonnull
public static native byte[] idBinary(byte[] b);
public static final class CppProxy extends TestHelpers
......
......@@ -4,8 +4,11 @@
package com.dropbox.djinni.test;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
public abstract class Token {
@Nonnull
public abstract String whoami();
public static final class CppProxy extends Token
......
......@@ -7,7 +7,7 @@
</exec>
<mkdir dir="classes"/>
<javac destdir="classes">
<classpath path="hamcrest-core-1.3.jar:junit-4.11.jar"/>
<classpath path="hamcrest-core-1.3.jar:junit-4.11.jar:jsr305-3.0.0.jar"/>
<src path="../generated-src"/>
<src path="../handwritten-src"/>
</javac>
......
......@@ -53,6 +53,8 @@ fi
"$base_dir/../src/run-assume-built" \
--java-out "$temp_out/java" \
--java-package $java_package \
--java-nullable-annotation "javax.annotation.CheckForNull" \
--java-nonnull-annotation "javax.annotation.Nonnull" \
--ident-java-field mFooBar \
\
--cpp-out "$temp_out/cpp" \
......
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