From: Jean Privat Date: Tue, 17 Jun 2014 20:03:06 +0000 (-0400) Subject: Merge: Include extra Java files in a project X-Git-Tag: v0.6.6~27 X-Git-Url: http://nitlanguage.org?hp=bd435f33db2427534763b99ffe0eb567e18e1520 Merge: Include extra Java files in a project Will be used to declare implement new Activities and sub classes like Listeners. Pull-Request: #496 Reviewed-by: Jean Privat Reviewed-by: Frédéric Vachon Reviewed-by: Alexandre Terrasa --- diff --git a/src/common_ffi/common_ffi.nit b/src/common_ffi/common_ffi.nit index 6fcef86..c22180c 100644 --- a/src/common_ffi/common_ffi.nit +++ b/src/common_ffi/common_ffi.nit @@ -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 index 0000000..632a322 --- /dev/null +++ b/src/common_ffi/extra_java_files.nit @@ -0,0 +1,110 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2014 Alexis Laferrière +# +# 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 diff --git a/src/common_ffi/java.nit b/src/common_ffi/java.nit index 330336f..68ba1e9 100644 --- a/src/common_ffi/java.nit +++ b/src/common_ffi/java.nit @@ -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 index 0000000..cbbeae1 --- /dev/null +++ b/tests/sav/test_ffi_java_annot_files.res @@ -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 index 0000000..c57135a --- /dev/null +++ b/tests/test_ffi_java_annot_files.nit @@ -0,0 +1,35 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2014 Alexis Laferrière +# +# 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 index 0000000..2a7fdf5 --- /dev/null +++ b/tests/test_ffi_java_annot_files_a.java @@ -0,0 +1,30 @@ +// This file is part of NIT ( http://www.nitlanguage.org ). +// +// Copyright 2014 Alexis Laferriere +// +// 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 { + 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); + } +}