Java FFI: enable inserting additionnal Java files to a project
[nit.git] / src / common_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
25 redef class ToolContext
26 var extra_java_files_phase: Phase = new JavaExtraFilesPhase(self, [literal_phase])
27 end
28
29 redef class MModule
30 # Extra Java files to compile with the project
31 private var extra_java_files: nullable Array[JavaFile] = null
32 end
33
34 private class JavaExtraFilesPhase
35 super Phase
36
37 redef fun process_annotated_node(nmoduledecl, nat)
38 do
39 # Skip if we are not interested
40 var annot_name = "extra_java_files"
41 if nat.n_atid.n_id.text != annot_name then return
42
43 # Do some validity checks and print errors if the annotation is used incorrectly
44 var modelbuilder = toolcontext.modelbuilder
45
46 if not nmoduledecl isa AModuledecl then
47 modelbuilder.error(nat, "Syntax error: only the declaration of modules may use \"{annot_name}\".")
48 return
49 end
50
51 var args = nat.n_args
52 if args.is_empty then
53 modelbuilder.error(nat, "Syntax error: \"{annot_name}\" expects at least one argument.")
54 return
55 end
56
57 # retrieve module
58 var nmodule = nmoduledecl.parent.as(AModule)
59 var mmodule = nmodule.mmodule.as(not null)
60 var java_files = mmodule.extra_java_files
61 if java_files == null then
62 java_files = new Array[JavaFile]
63 mmodule.extra_java_files = java_files
64 end
65
66 var format_error = "Syntax error: \"{annot_name}\" expects its arguments to be paths to java files."
67 for arg in args do
68 if not arg isa AExprAtArg then
69 modelbuilder.error(nat, format_error)
70 return
71 end
72
73 var expr = arg.n_expr
74 if not expr isa AStringFormExpr then
75 modelbuilder.error(nat, format_error)
76 return
77 end
78
79 var path = expr.value
80 assert path != null
81
82 # Append specified path to directory of the Nit source file
83 var source_file = nat.location.file
84 if source_file != null then path = "{source_file.filename.dirname}/{path}"
85
86 if not path.file_exists then
87 modelbuilder.error(nat, "FFI with Java error: file \"{path}\" not found.")
88 continue
89 end
90
91 var file = new JavaFile(path)
92 mmodule.ffi_files.add file
93 java_files.add file
94 end
95 end
96 end
97
98 redef class JavaLanguage
99 redef fun compile_to_files(mmodule, compdir)
100 do
101 super
102
103 # also copy over the java files
104 var extra_java_files = mmodule.extra_java_files
105 if extra_java_files != null then for file in extra_java_files do
106 var path = file.filename
107 path.file_copy_to("{compdir}/{path.basename("")}")
108 end
109 end
110 end