nitpackage: make package expension optional
[nit.git] / src / nitpackage.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Helpful features about packages
16 module nitpackage
17
18 import frontend
19
20 redef class ToolContext
21 # --expand
22 var opt_expand = new OptionBool("Move singleton packages to their own directory", "--expand")
23
24 # README handling phase
25 var readme_phase: Phase = new ReadmePhase(self, null)
26
27 redef init do
28 super
29 option_context.add_option(opt_expand)
30 end
31 end
32
33 private class ReadmePhase
34 super Phase
35
36 redef fun process_mainmodule(mainmodule, mmodules) do
37 var mpackages = extract_mpackages(mmodules)
38
39 for mpackage in mpackages do
40
41 # Fictive and buggy packages are ignored
42 if not mpackage.has_source then
43 toolcontext.warning(mpackage.location, "no-source",
44 "Warning: `{mpackage}` has no source file")
45 continue
46 end
47
48 # Expand packages
49 if toolcontext.opt_expand.value and not mpackage.is_expanded then
50 var path = mpackage.expand
51 toolcontext.info("{mpackage} moved to {path}", 0)
52 end
53 if not mpackage.is_expanded then
54 toolcontext.warning(mpackage.location, "no-dir",
55 "Warning: `{mpackage}` has no package directory")
56 continue
57 end
58 end
59 end
60
61 # Extract the list of packages from the mmodules passed as arguments
62 fun extract_mpackages(mmodules: Collection[MModule]): Collection[MPackage] do
63 var mpackages = new ArraySet[MPackage]
64 for mmodule in mmodules do
65 var mpackage = mmodule.mpackage
66 if mpackage == null then continue
67 mpackages.add mpackage
68 end
69 return mpackages.to_a
70 end
71 end
72
73 redef class MPackage
74
75 # Expand `self` in its own directory
76 private fun expand: String do
77 assert not is_expanded
78
79 var ori_path = package_path.as(not null)
80 var new_path = ori_path.dirname / name
81
82 new_path.mkdir
83 sys.system "mv {ori_path} {new_path / name}.nit"
84
85 var ini_file = "{new_path}.ini"
86 if ini_file.file_exists then
87 sys.system "mv {new_path}.ini {new_path}/package.ini"
88 end
89
90 return new_path
91 end
92 end
93
94 # build toolcontext
95 var toolcontext = new ToolContext
96 var tpl = new Template
97 tpl.add "Usage: nitpackage [OPTION]... <file.nit>...\n"
98 tpl.add "Helpful features about packages."
99 toolcontext.tooldescription = tpl.write_to_string
100
101 # process options
102 toolcontext.process_options(args)
103 var arguments = toolcontext.option_context.rest
104
105 # build model
106 var model = new Model
107 var mbuilder = new ModelBuilder(model, toolcontext)
108 var mmodules = mbuilder.parse_full(arguments)
109
110 # process
111 if mmodules.is_empty then return
112 mbuilder.run_phases
113 toolcontext.run_global_phases(mmodules)