Commit 02cd03e1 authored by Danny Weinberg's avatar Danny Weinberg

Add the ability to specify Java nullity annotations which are added to...

Add the ability to specify Java nullity annotations which are added to constants, return values, and parameters based on whether or not they're optional.
parent 683dc7f0
......@@ -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,
......
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