Merge: Include extra Java files in a project
authorJean Privat <jean@pryen.org>
Tue, 17 Jun 2014 20:03:06 +0000 (16:03 -0400)
committerJean Privat <jean@pryen.org>
Tue, 17 Jun 2014 20:03:06 +0000 (16:03 -0400)
Will be used to declare implement new Activities and sub classes like Listeners.

Pull-Request: #496
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Frédéric Vachon <fredvac@gmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

src/common_ffi/common_ffi.nit
src/common_ffi/extra_java_files.nit [new file with mode: 0644]
src/common_ffi/java.nit
tests/sav/test_ffi_java_annot_files.res [new file with mode: 0644]
tests/test_ffi_java_annot_files.nit [new file with mode: 0644]
tests/test_ffi_java_annot_files_a.java [new file with mode: 0644]

index 6fcef86..c22180c 100644 (file)
@@ -32,6 +32,7 @@ import c_compiler_options
 import c
 import cpp
 import java
+import extra_java_files
 
 redef class MModule
        # Does this module uses the FFI?
diff --git a/src/common_ffi/extra_java_files.nit b/src/common_ffi/extra_java_files.nit
new file mode 100644 (file)
index 0000000..632a322
--- /dev/null
@@ -0,0 +1,110 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# 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.
+
+# Intro the annotation `extra_java_files` to compile extra java files
+#
+# It is mainly used to declare public Java classes.
+module extra_java_files
+
+import literal
+import java
+
+redef class ToolContext
+       var extra_java_files_phase: Phase = new JavaExtraFilesPhase(self, [literal_phase])
+end
+
+redef class MModule
+       # Extra Java files to compile with the project
+       private var extra_java_files: nullable Array[JavaFile] = null
+end
+
+private class JavaExtraFilesPhase
+       super Phase
+
+       redef fun process_annotated_node(nmoduledecl, nat)
+       do
+               # Skip if we are not interested
+               var annot_name = "extra_java_files"
+               if nat.n_atid.n_id.text != annot_name then return
+
+               # Do some validity checks and print errors if the annotation is used incorrectly
+               var modelbuilder = toolcontext.modelbuilder
+
+               if not nmoduledecl isa AModuledecl then
+                       modelbuilder.error(nat, "Syntax error: only the declaration of modules may use \"{annot_name}\".")
+                       return
+               end
+
+               var args = nat.n_args
+               if args.is_empty then
+                       modelbuilder.error(nat, "Syntax error: \"{annot_name}\" expects at least one argument.")
+                       return
+               end
+
+               # retrieve module
+               var nmodule = nmoduledecl.parent.as(AModule)
+               var mmodule = nmodule.mmodule.as(not null)
+               var java_files = mmodule.extra_java_files
+               if java_files == null then
+                       java_files = new Array[JavaFile]
+                       mmodule.extra_java_files = java_files
+               end
+
+               var format_error = "Syntax error: \"{annot_name}\" expects its arguments to be paths to java files."
+               for arg in args do
+                       if not arg isa AExprAtArg then
+                               modelbuilder.error(nat, format_error)
+                               return
+                       end
+
+                       var expr = arg.n_expr
+                       if not expr isa AStringFormExpr then
+                               modelbuilder.error(nat, format_error)
+                               return
+                       end
+
+                       var path = expr.value
+                       assert path != null
+
+                       # Append specified path to directory of the Nit source file
+                       var source_file = nat.location.file
+                       if source_file != null then path = "{source_file.filename.dirname}/{path}"
+
+                       if not path.file_exists then
+                               modelbuilder.error(nat, "FFI with Java error: file \"{path}\" not found.")
+                               continue
+                       end
+
+                       var file = new JavaFile(path)
+                       mmodule.ffi_files.add file
+                       java_files.add file
+               end
+       end
+end
+
+redef class JavaLanguage
+       redef fun compile_to_files(mmodule, compdir)
+       do
+               super
+
+               # also copy over the java files
+               var extra_java_files = mmodule.extra_java_files
+               if extra_java_files != null then for file in extra_java_files do
+                       var path = file.filename
+                       path.file_copy_to("{compdir}/{path.basename("")}")
+               end
+       end
+end
index 330336f..68ba1e9 100644 (file)
@@ -290,8 +290,10 @@ redef class AExternPropdef
                var sys_class = modelbuilder.try_get_mclass_by_name(self, mmodule, "Sys")
                assert sys_class != null
                var sys_jni_env_meth = modelbuilder.try_get_mproperty_by_name2(self, mmodule, sys_class.mclass_type, "jni_env")
-               assert sys_jni_env_meth != null
-               assert sys_jni_env_meth isa MMethod
+               if sys_jni_env_meth == null or not sys_jni_env_meth isa MMethod then
+                       toolcontext.error(self.location, "Java FFI error: you must import the `java` module when using the FFI with Java")
+                       return
+               end
 
                explicit_call = new MExplicitCall(sys_class.mclass_type, sys_jni_env_meth, mmodule)
                fcc.callbacks.add(explicit_call)
@@ -349,7 +351,7 @@ class JavaFile
        super ExternFile
 
        redef fun makefile_rule_name do return "{filename.basename(".java")}.class"
-       redef fun makefile_rule_content do return "javac {filename} -d ."
+       redef fun makefile_rule_content do return "javac {filename.basename("")} -d ."
        redef fun add_to_jar do return true
 end
 
diff --git a/tests/sav/test_ffi_java_annot_files.res b/tests/sav/test_ffi_java_annot_files.res
new file mode 100644 (file)
index 0000000..cbbeae1
--- /dev/null
@@ -0,0 +1,4 @@
+-1
+1
+-1
+1
diff --git a/tests/test_ffi_java_annot_files.nit b/tests/test_ffi_java_annot_files.nit
new file mode 100644 (file)
index 0000000..c57135a
--- /dev/null
@@ -0,0 +1,35 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# 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.
+
+module test_ffi_java_annot_files is
+       extra_java_files("test_ffi_java_annot_files_a.java")
+end
+
+import java
+
+fun foo in "Java" `{
+       test_ffi_java_annot_files_a zero = new test_ffi_java_annot_files_a(0);
+       test_ffi_java_annot_files_a one = new test_ffi_java_annot_files_a(1);
+       test_ffi_java_annot_files_a ten = new test_ffi_java_annot_files_a(10);
+       test_ffi_java_annot_files_a neg = new test_ffi_java_annot_files_a(-1);
+
+       System.out.println(zero.compareTo(one));
+       System.out.println(one.compareTo(zero));
+       System.out.println(zero.compareTo(ten));
+       System.out.println(zero.compareTo(neg));
+`}
+
+foo
diff --git a/tests/test_ffi_java_annot_files_a.java b/tests/test_ffi_java_annot_files_a.java
new file mode 100644 (file)
index 0000000..2a7fdf5
--- /dev/null
@@ -0,0 +1,30 @@
+// This file is part of NIT ( http://www.nitlanguage.org ).
+//
+// Copyright 2014 Alexis Laferriere <alexis.laf@xymus.net>
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// 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.
+
+import java.lang.Comparable;
+
+public class test_ffi_java_annot_files_a implements Comparable<test_ffi_java_annot_files_a> {
+       Integer val;
+
+       test_ffi_java_annot_files_a(int val) {
+               this.val = new Integer(val);
+       }
+
+       @Override
+       public int compareTo(test_ffi_java_annot_files_a other) {
+               return val.compareTo(other.val);
+       }
+}