Java FFI: extra_java_file annotation use full Java class name
[nit.git] / src / ffi / extra_java_files.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Intro the annotation `extra_java_files` to compile extra java files
18 #
19 # It is mainly used to declare public Java classes.
20 module extra_java_files
21
22 import literal
23 import java
24 private import annotation
25
26 redef class ToolContext
27 var extra_java_files_phase: Phase = new JavaExtraFilesPhase(self, [literal_phase])
28 end
29
30 redef class MModule
31 # Extra Java files to compile with the module
32 private var extra_java_files: nullable Array[ExtraJavaFile] = null
33 end
34
35 private class JavaExtraFilesPhase
36 super Phase
37
38 redef fun process_annotated_node(nmoduledecl, nat)
39 do
40 # Skip if we are not interested
41 var annot_name = "extra_java_files"
42 if nat.name != annot_name then return
43
44 # Do some validity checks and print errors if the annotation is used incorrectly
45 var modelbuilder = toolcontext.modelbuilder
46
47 if not nmoduledecl isa AModuledecl then
48 modelbuilder.error(nat, "Syntax Error: only the declaration of modules may use `{annot_name}`.")
49 return
50 end
51
52 var args = nat.n_args
53 if args.is_empty then
54 modelbuilder.error(nat, "Syntax Error: `{annot_name}` expects at least one argument.")
55 return
56 end
57
58 # retrieve module
59 var nmodule = nmoduledecl.parent.as(AModule)
60 var mmodule = nmodule.mmodule.as(not null)
61 var java_files = mmodule.extra_java_files
62 if java_files == null then
63 java_files = new Array[ExtraJavaFile]
64 mmodule.extra_java_files = java_files
65 end
66
67 var format_error = "Syntax Error: `{annot_name}` expects its arguments to be paths to java files."
68 for arg in args do
69 var name = arg.as_string
70 if name == null or name.is_empty then
71 modelbuilder.error(arg, format_error)
72 return
73 end
74
75 var path = name.split(".").last + ".java"
76
77 # Append specified path to directory of the Nit source file
78 var source_file = nat.location.file
79 if source_file != null then path = "{source_file.filename.dirname}/{path}"
80
81 if not path.file_exists then
82 modelbuilder.error(nat, "FFI with Java Error: file `{path}` not found.")
83 continue
84 end
85
86 var file = new ExtraJavaFile(name, path)
87 mmodule.ffi_files.add file
88 java_files.add file
89 end
90 end
91 end
92
93 redef class JavaLanguage
94 redef fun compile_to_files(mmodule, compdir)
95 do
96 super
97
98 # Also copy over the extra Java files
99 var extra_java_files = mmodule.extra_java_files
100 if extra_java_files != null then for file in extra_java_files do
101
102 var dir = compdir / file.filename.dirname
103 dir.mkdir
104
105 file.src_path.file_copy_to(compdir/file.filename)
106 end
107 end
108 end
109
110 # User supplied Java file to include with the app for use from the FFI
111 class ExtraJavaFile
112 super JavaFile
113
114 autoinit full_name, src_path
115
116 redef var full_name
117
118 # Path to the original user file
119 var src_path: String
120
121 redef fun filename do return full_name.replace(".", "/") + ".java"
122 end