diff --git a/.gitignore b/.gitignore index ada091c4..92285051 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store .idea/ +.vscode # bazel /bazel-* .ijwb/ @@ -22,3 +23,4 @@ test-suite/djinni/vendor/third-party/proto/ts/*.js .bsp /project /target +/.metals diff --git a/src/source/JavaGenerator.scala b/src/source/JavaGenerator.scala index 7da5231f..6481a841 100644 --- a/src/source/JavaGenerator.scala +++ b/src/source/JavaGenerator.scala @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * * This file has been modified by Snap, Inc. */ @@ -174,8 +174,16 @@ class JavaGenerator(spec: Spec) extends Generator(spec) { val typeParamList = javaTypeParams(typeParams) writeDoc(w, doc) + val statics = i.methods.filter(m => m.static && m.lang.java) + javaAnnotationHeader.foreach(w.wl) - w.w(s"${javaClassAccessModifierString}abstract class $javaClass$typeParamList").braced { + + // if no static and no cpp will use interface instead of abstract class + val genJavaInterface = spec.javaGenInterface && !statics.nonEmpty && !i.ext.cpp + val classOrInterfaceDesc = if (genJavaInterface) "interface" else "abstract class"; + val methodPrefixDesc = if (genJavaInterface) "" else "public abstract "; + + w.w(s"${javaClassAccessModifierString}${classOrInterfaceDesc} $javaClass$typeParamList").braced { val skipFirst = SkipFirst() generateJavaConstants(w, i.consts) @@ -189,7 +197,7 @@ class JavaGenerator(spec: Spec) extends Generator(spec) { 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 + ";") + w.wl(methodPrefixDesc + ret + " " + idJava.method(m.ident) + params.mkString("(", ", ", ")") + throwException + ";") } val statics = i.methods.filter(m => m.static && m.lang.java) diff --git a/src/source/Main.scala b/src/source/Main.scala index a59b46cf..eb40c8c4 100644 --- a/src/source/Main.scala +++ b/src/source/Main.scala @@ -49,6 +49,7 @@ object Main { var javaNonnullAnnotation: Option[String] = None var javaImplementAndroidOsParcelable : Boolean = false var javaUseFinalForRecord: Boolean = true + var javaGenInterface: Boolean = false var jniOutFolder: Option[File] = None var jniHeaderOutFolderOptional: Option[File] = None var jniNamespace: String = "djinni_generated" @@ -140,6 +141,8 @@ object Main { .text("all generated java classes will implement the interface android.os.Parcelable") opt[Boolean]("java-use-final-for-record").valueName("").foreach(x => javaUseFinalForRecord = x) .text("Whether generated Java classes for records should be marked 'final' (default: true). ") + opt[Boolean]("java-gen-interface").valueName("").foreach(x => javaGenInterface = x) + .text("Generate Java interface instead of abstract class.") note("") opt[File]("cpp-out").valueName("").foreach(x => cppOutFolder = Some(x)) .text("The output folder for C++ files (Generator disabled if unspecified).") @@ -373,6 +376,7 @@ object Main { javaNonnullAnnotation, javaImplementAndroidOsParcelable, javaUseFinalForRecord, + javaGenInterface, cppOutFolder, cppHeaderOutFolder, cppIncludePrefix, diff --git a/src/source/generator.scala b/src/source/generator.scala index 5bd55f5a..3e87a826 100644 --- a/src/source/generator.scala +++ b/src/source/generator.scala @@ -41,6 +41,7 @@ package object generatorTools { javaNonnullAnnotation: Option[String], javaImplementAndroidOsParcelable: Boolean, javaUseFinalForRecord: Boolean, + javaGenInterface: Boolean, cppOutFolder: Option[File], cppHeaderOutFolder: Option[File], cppIncludePrefix: String, diff --git a/test-suite/djinni/interface_and_abstract_class.djinni b/test-suite/djinni/interface_and_abstract_class.djinni new file mode 100644 index 00000000..723d80bc --- /dev/null +++ b/test-suite/djinni/interface_and_abstract_class.djinni @@ -0,0 +1,7 @@ +test_java_interface_only = interface +j { + test_method(): bool; +} + +test_java_abstract_class_only = interface +c { + static test_method(): bool; +} diff --git a/test-suite/generated-src/cpp/test_java_abstract_class_only.hpp b/test-suite/generated-src/cpp/test_java_abstract_class_only.hpp new file mode 100644 index 00000000..88d10b89 --- /dev/null +++ b/test-suite/generated-src/cpp/test_java_abstract_class_only.hpp @@ -0,0 +1,15 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +#pragma once + +namespace testsuite { + +class TestJavaAbstractClassOnly { +public: + virtual ~TestJavaAbstractClassOnly() = default; + + static bool test_method(); +}; + +} // namespace testsuite diff --git a/test-suite/generated-src/cpp/test_java_interface_only.hpp b/test-suite/generated-src/cpp/test_java_interface_only.hpp new file mode 100644 index 00000000..077dd128 --- /dev/null +++ b/test-suite/generated-src/cpp/test_java_interface_only.hpp @@ -0,0 +1,15 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +#pragma once + +namespace testsuite { + +class TestJavaInterfaceOnly { +public: + virtual ~TestJavaInterfaceOnly() = default; + + virtual bool test_method() = 0; +}; + +} // namespace testsuite diff --git a/test-suite/generated-src/java/com/dropbox/djinni/test/TestJavaAbstractClassOnly.java b/test-suite/generated-src/java/com/dropbox/djinni/test/TestJavaAbstractClassOnly.java new file mode 100644 index 00000000..3e49bbaf --- /dev/null +++ b/test-suite/generated-src/java/com/dropbox/djinni/test/TestJavaAbstractClassOnly.java @@ -0,0 +1,27 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +package com.dropbox.djinni.test; + +import com.snapchat.djinni.NativeObjectManager; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; + +public abstract class TestJavaAbstractClassOnly { + public static native boolean testMethod(); + + public static final class CppProxy extends TestJavaAbstractClassOnly + { + private final long nativeRef; + private final AtomicBoolean destroyed = new AtomicBoolean(false); + + private CppProxy(long nativeRef) + { + if (nativeRef == 0) throw new RuntimeException("nativeRef is zero"); + this.nativeRef = nativeRef; + NativeObjectManager.register(this, nativeRef); + } + public static native void nativeDestroy(long nativeRef); + } +} diff --git a/test-suite/generated-src/java/com/dropbox/djinni/test/TestJavaInterfaceOnly.java b/test-suite/generated-src/java/com/dropbox/djinni/test/TestJavaInterfaceOnly.java new file mode 100644 index 00000000..22306af6 --- /dev/null +++ b/test-suite/generated-src/java/com/dropbox/djinni/test/TestJavaInterfaceOnly.java @@ -0,0 +1,11 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +package com.dropbox.djinni.test; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; + +public interface TestJavaInterfaceOnly { + boolean testMethod(); +} diff --git a/test-suite/generated-src/jni/NativeTestJavaAbstractClassOnly.cpp b/test-suite/generated-src/jni/NativeTestJavaAbstractClassOnly.cpp new file mode 100644 index 00000000..d2730903 --- /dev/null +++ b/test-suite/generated-src/jni/NativeTestJavaAbstractClassOnly.cpp @@ -0,0 +1,29 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +#include "NativeTestJavaAbstractClassOnly.hpp" // my header +#include "Marshal.hpp" + +namespace djinni_generated { + +NativeTestJavaAbstractClassOnly::NativeTestJavaAbstractClassOnly() : ::djinni::JniInterface<::testsuite::TestJavaAbstractClassOnly, NativeTestJavaAbstractClassOnly>("com/dropbox/djinni/test/TestJavaAbstractClassOnly$CppProxy") {} + +NativeTestJavaAbstractClassOnly::~NativeTestJavaAbstractClassOnly() = default; + + +CJNIEXPORT void JNICALL Java_com_dropbox_djinni_test_TestJavaAbstractClassOnly_00024CppProxy_nativeDestroy(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef) +{ + try { + delete reinterpret_cast<::djinni::CppProxyHandle<::testsuite::TestJavaAbstractClassOnly>*>(nativeRef); + } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, ) +} + +CJNIEXPORT jboolean JNICALL Java_com_dropbox_djinni_test_TestJavaAbstractClassOnly_testMethod(JNIEnv* jniEnv, jobject /*this*/) +{ + try { + auto r = ::testsuite::TestJavaAbstractClassOnly::test_method(); + return ::djinni::release(::djinni::Bool::fromCpp(jniEnv, r)); + } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */) +} + +} // namespace djinni_generated diff --git a/test-suite/generated-src/jni/NativeTestJavaAbstractClassOnly.hpp b/test-suite/generated-src/jni/NativeTestJavaAbstractClassOnly.hpp new file mode 100644 index 00000000..6472c8c9 --- /dev/null +++ b/test-suite/generated-src/jni/NativeTestJavaAbstractClassOnly.hpp @@ -0,0 +1,32 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +#pragma once + +#include "djinni_support.hpp" +#include "test_java_abstract_class_only.hpp" + +namespace djinni_generated { + +class NativeTestJavaAbstractClassOnly final : ::djinni::JniInterface<::testsuite::TestJavaAbstractClassOnly, NativeTestJavaAbstractClassOnly> { +public: + using CppType = std::shared_ptr<::testsuite::TestJavaAbstractClassOnly>; + using CppOptType = std::shared_ptr<::testsuite::TestJavaAbstractClassOnly>; + using JniType = jobject; + + using Boxed = NativeTestJavaAbstractClassOnly; + + ~NativeTestJavaAbstractClassOnly(); + + static CppType toCpp(JNIEnv* jniEnv, JniType j) { return ::djinni::JniClass::get()._fromJava(jniEnv, j); } + static ::djinni::LocalRef fromCppOpt(JNIEnv* jniEnv, const CppOptType& c) { return {jniEnv, ::djinni::JniClass::get()._toJava(jniEnv, c)}; } + static ::djinni::LocalRef fromCpp(JNIEnv* jniEnv, const CppType& c) { return fromCppOpt(jniEnv, c); } + +private: + NativeTestJavaAbstractClassOnly(); + friend ::djinni::JniClass; + friend ::djinni::JniInterface<::testsuite::TestJavaAbstractClassOnly, NativeTestJavaAbstractClassOnly>; + +}; + +} // namespace djinni_generated diff --git a/test-suite/generated-src/jni/NativeTestJavaInterfaceOnly.cpp b/test-suite/generated-src/jni/NativeTestJavaInterfaceOnly.cpp new file mode 100644 index 00000000..ef0f48a9 --- /dev/null +++ b/test-suite/generated-src/jni/NativeTestJavaInterfaceOnly.cpp @@ -0,0 +1,26 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +#include "NativeTestJavaInterfaceOnly.hpp" // my header +#include "Marshal.hpp" + +namespace djinni_generated { + +NativeTestJavaInterfaceOnly::NativeTestJavaInterfaceOnly() : ::djinni::JniInterface<::testsuite::TestJavaInterfaceOnly, NativeTestJavaInterfaceOnly>() {} + +NativeTestJavaInterfaceOnly::~NativeTestJavaInterfaceOnly() = default; + +NativeTestJavaInterfaceOnly::JavaProxy::JavaProxy(JniType j) : Handle(::djinni::jniGetThreadEnv(), j) { } + +NativeTestJavaInterfaceOnly::JavaProxy::~JavaProxy() = default; + +bool NativeTestJavaInterfaceOnly::JavaProxy::test_method() { + auto jniEnv = ::djinni::jniGetThreadEnv(); + ::djinni::JniLocalScope jscope(jniEnv, 10); + const auto& data = ::djinni::JniClass<::djinni_generated::NativeTestJavaInterfaceOnly>::get(); + auto jret = jniEnv->CallBooleanMethod(Handle::get().get(), data.method_testMethod); + ::djinni::jniExceptionCheck(jniEnv); + return ::djinni::Bool::toCpp(jniEnv, jret); +} + +} // namespace djinni_generated diff --git a/test-suite/generated-src/jni/NativeTestJavaInterfaceOnly.hpp b/test-suite/generated-src/jni/NativeTestJavaInterfaceOnly.hpp new file mode 100644 index 00000000..e008325a --- /dev/null +++ b/test-suite/generated-src/jni/NativeTestJavaInterfaceOnly.hpp @@ -0,0 +1,46 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +#pragma once + +#include "djinni_support.hpp" +#include "test_java_interface_only.hpp" + +namespace djinni_generated { + +class NativeTestJavaInterfaceOnly final : ::djinni::JniInterface<::testsuite::TestJavaInterfaceOnly, NativeTestJavaInterfaceOnly> { +public: + using CppType = std::shared_ptr<::testsuite::TestJavaInterfaceOnly>; + using CppOptType = std::shared_ptr<::testsuite::TestJavaInterfaceOnly>; + using JniType = jobject; + + using Boxed = NativeTestJavaInterfaceOnly; + + ~NativeTestJavaInterfaceOnly(); + + static CppType toCpp(JNIEnv* jniEnv, JniType j) { return ::djinni::JniClass::get()._fromJava(jniEnv, j); } + static ::djinni::LocalRef fromCppOpt(JNIEnv* jniEnv, const CppOptType& c) { return {jniEnv, ::djinni::JniClass::get()._toJava(jniEnv, c)}; } + static ::djinni::LocalRef fromCpp(JNIEnv* jniEnv, const CppType& c) { return fromCppOpt(jniEnv, c); } + +private: + NativeTestJavaInterfaceOnly(); + friend ::djinni::JniClass; + friend ::djinni::JniInterface<::testsuite::TestJavaInterfaceOnly, NativeTestJavaInterfaceOnly>; + + class JavaProxy final : ::djinni::JavaProxyHandle, public ::testsuite::TestJavaInterfaceOnly + { + public: + JavaProxy(JniType j); + ~JavaProxy(); + + bool test_method() override; + + private: + friend ::djinni::JniInterface<::testsuite::TestJavaInterfaceOnly, ::djinni_generated::NativeTestJavaInterfaceOnly>; + }; + + const ::djinni::GlobalRef clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/TestJavaInterfaceOnly") }; + const jmethodID method_testMethod { ::djinni::jniGetMethodID(clazz.get(), "testMethod", "()Z") }; +}; + +} // namespace djinni_generated diff --git a/test-suite/generated-src/objc/DBTestJavaAbstractClassOnly+Private.h b/test-suite/generated-src/objc/DBTestJavaAbstractClassOnly+Private.h new file mode 100644 index 00000000..4c859c4f --- /dev/null +++ b/test-suite/generated-src/objc/DBTestJavaAbstractClassOnly+Private.h @@ -0,0 +1,31 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +#include "test_java_abstract_class_only.hpp" +#include + +static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for this file"); + +@class DBTestJavaAbstractClassOnly; + +namespace djinni_generated { + +class TestJavaAbstractClassOnly +{ +public: + using CppType = std::shared_ptr<::testsuite::TestJavaAbstractClassOnly>; + using CppOptType = std::shared_ptr<::testsuite::TestJavaAbstractClassOnly>; + using ObjcType = DBTestJavaAbstractClassOnly*; + + using Boxed = TestJavaAbstractClassOnly; + + static CppType toCpp(ObjcType objc); + static ObjcType fromCppOpt(const CppOptType& cpp); + static ObjcType fromCpp(const CppType& cpp) { return fromCppOpt(cpp); } + +private: + class ObjcProxy; +}; + +} // namespace djinni_generated + diff --git a/test-suite/generated-src/objc/DBTestJavaAbstractClassOnly+Private.mm b/test-suite/generated-src/objc/DBTestJavaAbstractClassOnly+Private.mm new file mode 100644 index 00000000..bf4d519c --- /dev/null +++ b/test-suite/generated-src/objc/DBTestJavaAbstractClassOnly+Private.mm @@ -0,0 +1,60 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +#import "DBTestJavaAbstractClassOnly+Private.h" +#import "DBTestJavaAbstractClassOnly.h" +#import "DJICppWrapperCache+Private.h" +#import "DJIError.h" +#import "DJIMarshal+Private.h" +#include +#include +#include + +static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for this file"); + +@interface DBTestJavaAbstractClassOnly () + +- (id)initWithCpp:(const std::shared_ptr<::testsuite::TestJavaAbstractClassOnly>&)cppRef; + +@end + +@implementation DBTestJavaAbstractClassOnly { + ::djinni::CppProxyCache::Handle> _cppRefHandle; +} + +- (id)initWithCpp:(const std::shared_ptr<::testsuite::TestJavaAbstractClassOnly>&)cppRef +{ + if (self = [super init]) { + _cppRefHandle.assign(cppRef); + } + return self; +} + ++ (BOOL)testMethod { + try { + auto objcpp_result_ = ::testsuite::TestJavaAbstractClassOnly::test_method(); + return ::djinni::Bool::fromCpp(objcpp_result_); + } DJINNI_TRANSLATE_EXCEPTIONS() +} + +namespace djinni_generated { + +auto TestJavaAbstractClassOnly::toCpp(ObjcType objc) -> CppType +{ + if (!objc) { + return nullptr; + } + return objc->_cppRefHandle.get(); +} + +auto TestJavaAbstractClassOnly::fromCppOpt(const CppOptType& cpp) -> ObjcType +{ + if (!cpp) { + return nil; + } + return ::djinni::get_cpp_proxy(cpp); +} + +} // namespace djinni_generated + +@end diff --git a/test-suite/generated-src/objc/DBTestJavaAbstractClassOnly.h b/test-suite/generated-src/objc/DBTestJavaAbstractClassOnly.h new file mode 100644 index 00000000..92547d88 --- /dev/null +++ b/test-suite/generated-src/objc/DBTestJavaAbstractClassOnly.h @@ -0,0 +1,11 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +#import + + +@interface DBTestJavaAbstractClassOnly : NSObject + ++ (BOOL)testMethod; + +@end diff --git a/test-suite/generated-src/objc/DBTestJavaInterfaceOnly+Private.h b/test-suite/generated-src/objc/DBTestJavaInterfaceOnly+Private.h new file mode 100644 index 00000000..28285b3d --- /dev/null +++ b/test-suite/generated-src/objc/DBTestJavaInterfaceOnly+Private.h @@ -0,0 +1,31 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +#include "test_java_interface_only.hpp" +#include + +static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for this file"); + +@class DBTestJavaInterfaceOnly; + +namespace djinni_generated { + +class TestJavaInterfaceOnly +{ +public: + using CppType = std::shared_ptr<::testsuite::TestJavaInterfaceOnly>; + using CppOptType = std::shared_ptr<::testsuite::TestJavaInterfaceOnly>; + using ObjcType = DBTestJavaInterfaceOnly*; + + using Boxed = TestJavaInterfaceOnly; + + static CppType toCpp(ObjcType objc); + static ObjcType fromCppOpt(const CppOptType& cpp); + static ObjcType fromCpp(const CppType& cpp) { return fromCppOpt(cpp); } + +private: + class ObjcProxy; +}; + +} // namespace djinni_generated + diff --git a/test-suite/generated-src/objc/DBTestJavaInterfaceOnly+Private.mm b/test-suite/generated-src/objc/DBTestJavaInterfaceOnly+Private.mm new file mode 100644 index 00000000..6d75c4ab --- /dev/null +++ b/test-suite/generated-src/objc/DBTestJavaInterfaceOnly+Private.mm @@ -0,0 +1,30 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +#import "DBTestJavaInterfaceOnly+Private.h" +#import "DBTestJavaInterfaceOnly.h" +#import "DJIError.h" +#import "DJIMarshal+Private.h" +#include + +static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for this file"); + +namespace djinni_generated { + +auto TestJavaInterfaceOnly::toCpp(ObjcType objc) -> CppType +{ + if (!objc) { + return nullptr; + } + DJINNI_UNIMPLEMENTED(@"Interface not implementable in any language."); +} + +auto TestJavaInterfaceOnly::fromCppOpt(const CppOptType& cpp) -> ObjcType +{ + if (!cpp) { + return nil; + } + DJINNI_UNIMPLEMENTED(@"Interface not implementable in any language."); +} + +} // namespace djinni_generated diff --git a/test-suite/generated-src/objc/DBTestJavaInterfaceOnly.h b/test-suite/generated-src/objc/DBTestJavaInterfaceOnly.h new file mode 100644 index 00000000..88fec57f --- /dev/null +++ b/test-suite/generated-src/objc/DBTestJavaInterfaceOnly.h @@ -0,0 +1,11 @@ +// AUTOGENERATED FILE - DO NOT MODIFY! +// This file was generated by Djinni from interface_and_abstract_class.djinni + +#import + + +@interface DBTestJavaInterfaceOnly : NSObject + +- (BOOL)testMethod; + +@end diff --git a/test-suite/handwritten-src/cpp/test_java_abstract_class_only.cpp b/test-suite/handwritten-src/cpp/test_java_abstract_class_only.cpp new file mode 100644 index 00000000..99c6ee9b --- /dev/null +++ b/test-suite/handwritten-src/cpp/test_java_abstract_class_only.cpp @@ -0,0 +1,10 @@ +#include "test_java_abstract_class_only.hpp" + +namespace testsuite { + +bool TestJavaAbstractClassOnly::test_method() +{ + return true; +} + +} // namespace testsuite diff --git a/test-suite/handwritten-src/java/com/dropbox/djinni/test/AllTests.java b/test-suite/handwritten-src/java/com/dropbox/djinni/test/AllTests.java index f3053211..6515a311 100644 --- a/test-suite/handwritten-src/java/com/dropbox/djinni/test/AllTests.java +++ b/test-suite/handwritten-src/java/com/dropbox/djinni/test/AllTests.java @@ -30,6 +30,7 @@ public static Test suite() { mySuite.addTestSuite(ArrayTest.class); mySuite.addTestSuite(DataTest.class); mySuite.addTestSuite(AsyncTest.class); + mySuite.addTestSuite(InterfaceAndAbstractClass.class); return mySuite; } diff --git a/test-suite/handwritten-src/java/com/dropbox/djinni/test/InterfaceAndAbstractClass.java b/test-suite/handwritten-src/java/com/dropbox/djinni/test/InterfaceAndAbstractClass.java new file mode 100644 index 00000000..a1b50920 --- /dev/null +++ b/test-suite/handwritten-src/java/com/dropbox/djinni/test/InterfaceAndAbstractClass.java @@ -0,0 +1,22 @@ +package com.dropbox.djinni.test; + +import junit.framework.TestCase; + +public class InterfaceAndAbstractClass extends TestCase { + + static class TestJavaInterfaceOnlyImpl implements TestJavaInterfaceOnly { + @Override + public boolean testMethod() { + return true; + } + } + + public void test() { + // interface + TestJavaInterfaceOnlyImpl impl1 = new TestJavaInterfaceOnlyImpl(); + assertEquals(impl1.testMethod(), true); + + // abstract class + assertEquals(TestJavaAbstractClassOnly.testMethod(), true); + } +} diff --git a/test-suite/run_djinni.sh b/test-suite/run_djinni.sh index 53bb5da7..61328b40 100755 --- a/test-suite/run_djinni.sh +++ b/test-suite/run_djinni.sh @@ -27,6 +27,7 @@ in_relative="djinni/all.djinni" wchar_in_relative="djinni/wchar_test.djinni" prologue_in_relative="djinni/function_prologue.djinni" ident_explicit_in_relative="djinni/ident_explicit.djinni" +interface_and_abstract_class_in_relative="djinni/interface_and_abstract_class.djinni" temp_out_relative="djinni-output-temp" cpp_out="$base_dir/generated-src/cpp" @@ -196,7 +197,39 @@ fi --ident-objc-enum NativeFooBar! \ --ident-objc-const NativeFooBar! \ \ - --idl "$ident_explicit_in_relative" \ + --idl "$ident_explicit_in_relative" && \ +"$base_dir/../src/run-assume-built" \ + --java-out "$temp_out_relative/java" \ + --java-package $java_package \ + --java-nullable-annotation "javax.annotation.CheckForNull" \ + --java-nonnull-annotation "javax.annotation.Nonnull" \ + --java-use-final-for-record false \ + --java-implement-android-os-parcelable true \ + --java-gen-interface true \ + --ident-java-field mFooBar \ + \ + --cpp-out "$temp_out_relative/cpp" \ + --cpp-namespace testsuite \ + --ident-cpp-enum-type foo_bar \ + --cpp-optional-template "std::experimental::optional" \ + --cpp-optional-header "\"../../handwritten-src/cpp/optional.hpp\"" \ + --cpp-extended-record-include-prefix "../../handwritten-src/cpp/" \ + \ + --jni-out "$temp_out_relative/jni" \ + --jni-use-on-load-initializer false \ + --ident-jni-class NativeFooBar \ + --ident-jni-file NativeFooBar \ + \ + --objc-out "$temp_out_relative/objc" \ + --objcpp-out "$temp_out_relative/objc" \ + --objc-type-prefix DB \ + \ + --yaml-out "$temp_out_relative/yaml" \ + --yaml-out-file "yaml-interface-test.yaml" \ + --yaml-prefix "test_" \ + \ + --idl "$interface_and_abstract_class_in_relative" \ + --idl-include-path "djinni/vendor" \ ) # Make sure we can parse back our own generated YAML file