Skip to content

Commit 2f5b0ae

Browse files
authored
Merge pull request #105 from paulocoutinhox/java-interface-support
java interface support
2 parents 60a4223 + 085b670 commit 2f5b0ae

23 files changed

+467
-4
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.DS_Store
22
.idea/
3+
.vscode
34
# bazel
45
/bazel-*
56
.ijwb/
@@ -22,3 +23,4 @@ test-suite/djinni/vendor/third-party/proto/ts/*.js
2223
.bsp
2324
/project
2425
/target
26+
/.metals

src/source/JavaGenerator.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
15-
*
15+
*
1616
* This file has been modified by Snap, Inc.
1717
*/
1818

@@ -174,8 +174,16 @@ class JavaGenerator(spec: Spec) extends Generator(spec) {
174174
val typeParamList = javaTypeParams(typeParams)
175175
writeDoc(w, doc)
176176

177+
val statics = i.methods.filter(m => m.static && m.lang.java)
178+
177179
javaAnnotationHeader.foreach(w.wl)
178-
w.w(s"${javaClassAccessModifierString}abstract class $javaClass$typeParamList").braced {
180+
181+
// if no static and no cpp will use interface instead of abstract class
182+
val genJavaInterface = spec.javaGenInterface && !statics.nonEmpty && !i.ext.cpp
183+
val classOrInterfaceDesc = if (genJavaInterface) "interface" else "abstract class";
184+
val methodPrefixDesc = if (genJavaInterface) "" else "public abstract ";
185+
186+
w.w(s"${javaClassAccessModifierString}${classOrInterfaceDesc} $javaClass$typeParamList").braced {
179187
val skipFirst = SkipFirst()
180188
generateJavaConstants(w, i.consts)
181189

@@ -189,7 +197,7 @@ class JavaGenerator(spec: Spec) extends Generator(spec) {
189197
nullityAnnotation + marshal.paramType(p.ty) + " " + idJava.local(p.ident)
190198
})
191199
marshal.nullityAnnotation(m.ret).foreach(w.wl)
192-
w.wl("public abstract " + ret + " " + idJava.method(m.ident) + params.mkString("(", ", ", ")") + throwException + ";")
200+
w.wl(methodPrefixDesc + ret + " " + idJava.method(m.ident) + params.mkString("(", ", ", ")") + throwException + ";")
193201
}
194202

195203
val statics = i.methods.filter(m => m.static && m.lang.java)

src/source/Main.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ object Main {
4949
var javaNonnullAnnotation: Option[String] = None
5050
var javaImplementAndroidOsParcelable : Boolean = false
5151
var javaUseFinalForRecord: Boolean = true
52+
var javaGenInterface: Boolean = false
5253
var jniOutFolder: Option[File] = None
5354
var jniHeaderOutFolderOptional: Option[File] = None
5455
var jniNamespace: String = "djinni_generated"
@@ -140,6 +141,8 @@ object Main {
140141
.text("all generated java classes will implement the interface android.os.Parcelable")
141142
opt[Boolean]("java-use-final-for-record").valueName("<use-final-for-record>").foreach(x => javaUseFinalForRecord = x)
142143
.text("Whether generated Java classes for records should be marked 'final' (default: true). ")
144+
opt[Boolean]("java-gen-interface").valueName("<true/false>").foreach(x => javaGenInterface = x)
145+
.text("Generate Java interface instead of abstract class.")
143146
note("")
144147
opt[File]("cpp-out").valueName("<out-folder>").foreach(x => cppOutFolder = Some(x))
145148
.text("The output folder for C++ files (Generator disabled if unspecified).")
@@ -373,6 +376,7 @@ object Main {
373376
javaNonnullAnnotation,
374377
javaImplementAndroidOsParcelable,
375378
javaUseFinalForRecord,
379+
javaGenInterface,
376380
cppOutFolder,
377381
cppHeaderOutFolder,
378382
cppIncludePrefix,

src/source/generator.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ package object generatorTools {
4141
javaNonnullAnnotation: Option[String],
4242
javaImplementAndroidOsParcelable: Boolean,
4343
javaUseFinalForRecord: Boolean,
44+
javaGenInterface: Boolean,
4445
cppOutFolder: Option[File],
4546
cppHeaderOutFolder: Option[File],
4647
cppIncludePrefix: String,
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
test_java_interface_only = interface +j {
2+
test_method(): bool;
3+
}
4+
5+
test_java_abstract_class_only = interface +c {
6+
static test_method(): bool;
7+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// AUTOGENERATED FILE - DO NOT MODIFY!
2+
// This file was generated by Djinni from interface_and_abstract_class.djinni
3+
4+
#pragma once
5+
6+
namespace testsuite {
7+
8+
class TestJavaAbstractClassOnly {
9+
public:
10+
virtual ~TestJavaAbstractClassOnly() = default;
11+
12+
static bool test_method();
13+
};
14+
15+
} // namespace testsuite
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// AUTOGENERATED FILE - DO NOT MODIFY!
2+
// This file was generated by Djinni from interface_and_abstract_class.djinni
3+
4+
#pragma once
5+
6+
namespace testsuite {
7+
8+
class TestJavaInterfaceOnly {
9+
public:
10+
virtual ~TestJavaInterfaceOnly() = default;
11+
12+
virtual bool test_method() = 0;
13+
};
14+
15+
} // namespace testsuite
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// AUTOGENERATED FILE - DO NOT MODIFY!
2+
// This file was generated by Djinni from interface_and_abstract_class.djinni
3+
4+
package com.dropbox.djinni.test;
5+
6+
import com.snapchat.djinni.NativeObjectManager;
7+
import java.util.concurrent.atomic.AtomicBoolean;
8+
import javax.annotation.CheckForNull;
9+
import javax.annotation.Nonnull;
10+
11+
public abstract class TestJavaAbstractClassOnly {
12+
public static native boolean testMethod();
13+
14+
public static final class CppProxy extends TestJavaAbstractClassOnly
15+
{
16+
private final long nativeRef;
17+
private final AtomicBoolean destroyed = new AtomicBoolean(false);
18+
19+
private CppProxy(long nativeRef)
20+
{
21+
if (nativeRef == 0) throw new RuntimeException("nativeRef is zero");
22+
this.nativeRef = nativeRef;
23+
NativeObjectManager.register(this, nativeRef);
24+
}
25+
public static native void nativeDestroy(long nativeRef);
26+
}
27+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// AUTOGENERATED FILE - DO NOT MODIFY!
2+
// This file was generated by Djinni from interface_and_abstract_class.djinni
3+
4+
package com.dropbox.djinni.test;
5+
6+
import javax.annotation.CheckForNull;
7+
import javax.annotation.Nonnull;
8+
9+
public interface TestJavaInterfaceOnly {
10+
boolean testMethod();
11+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// AUTOGENERATED FILE - DO NOT MODIFY!
2+
// This file was generated by Djinni from interface_and_abstract_class.djinni
3+
4+
#include "NativeTestJavaAbstractClassOnly.hpp" // my header
5+
#include "Marshal.hpp"
6+
7+
namespace djinni_generated {
8+
9+
NativeTestJavaAbstractClassOnly::NativeTestJavaAbstractClassOnly() : ::djinni::JniInterface<::testsuite::TestJavaAbstractClassOnly, NativeTestJavaAbstractClassOnly>("com/dropbox/djinni/test/TestJavaAbstractClassOnly$CppProxy") {}
10+
11+
NativeTestJavaAbstractClassOnly::~NativeTestJavaAbstractClassOnly() = default;
12+
13+
14+
CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestJavaAbstractClassOnly_00024CppProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef)
15+
{
16+
try {
17+
delete reinterpret_cast<::djinni::CppProxyHandle<::testsuite::TestJavaAbstractClassOnly>*>(nativeRef);
18+
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
19+
}
20+
21+
CJNIEXPORT jboolean JNICALL Java_com_dropbox_djinni_test_TestJavaAbstractClassOnly_testMethod(JNIEnv* jniEnv, jobject /*this*/)
22+
{
23+
try {
24+
auto r = ::testsuite::TestJavaAbstractClassOnly::test_method();
25+
return ::djinni::release(::djinni::Bool::fromCpp(jniEnv, r));
26+
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
27+
}
28+
29+
} // namespace djinni_generated

0 commit comments

Comments
 (0)