Merge: Kill `model_utils`
[nit.git] / src / doc / doc_phases / doc_poset.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 # Importation and inheritance POSet for pages.
16 module doc_poset
17
18 import doc_pages
19 import model::model_collect
20
21 # This phase computes importation and inheritance POSet for pages.
22 class POSetPhase
23 super DocPhase
24
25 # Populates the given DocModel.
26 redef fun apply do
27 for page in doc.pages.values do
28 if page isa MEntityPage then page.build_poset(self, doc)
29 end
30 end
31 end
32
33 redef class MEntityPage
34
35 # The poset associated with this page.
36 #
37 # FIXME should be defined in subclasses
38 # as the POSet can contains other types than `SELF`
39 var poset = new POSet[MENTITY]
40
41 # Build the POSet for this page.
42 private fun build_poset(v: POSetPhase, doc: DocModel) do end
43 end
44
45 redef class MModulePage
46
47 # Imported modules that should appear in the documentation.
48 var imports = new HashSet[MModule]
49
50 # Clients modules that should appear in the documentation.
51 var clients = new HashSet[MModule]
52
53 redef fun build_poset(v, doc) do
54 # collect importation
55 for dep in mentity.in_importation.greaters do
56 if dep == mentity then continue
57 if not doc.mmodules.has(dep) then continue
58 imports.add dep
59 end
60 # FIXME avoid diff
61 #if imports.length > 10 then
62 if mentity.in_importation.greaters.length > 10 then
63 imports.clear
64 for dep in mentity.in_importation.direct_greaters do
65 if dep == mentity then continue
66 if not doc.mmodules.has(dep) then continue
67 imports.add dep
68 end
69 end
70 # collect clients
71 for dep in mentity.in_importation.smallers do
72 if dep == mentity then continue
73 if not doc.mmodules.has(dep) then continue
74 clients.add dep
75 end
76 if clients.length > 10 then
77 clients.clear
78 for dep in mentity.in_importation.direct_smallers do
79 if dep == mentity then continue
80 if not doc.mmodules.has(dep) then continue
81 clients.add dep
82 end
83 end
84 # make poset
85 var mmodules = new HashSet[MModule]
86 var mgroup = mentity.mgroup
87 if mgroup != null and mgroup.default_mmodule == mentity then
88 mmodules.add_all mgroup.mmodules
89 end
90 mmodules.add_all imports
91 if clients.length < 10 then mmodules.add_all clients
92 mmodules.add mentity
93 build_importation_poset(doc, mmodules)
94 end
95
96 # Build the POSet of importation from a list of `mmodules`.
97 private fun build_importation_poset(doc: DocModel, mmodules: Set[MModule]): POSet[MModule] do
98 for mmodule in mmodules do
99 if not doc.mmodules.has(mmodule) then continue
100 poset.add_node mmodule
101 for omodule in mmodules do
102 if not doc.mmodules.has(omodule) then continue
103 poset.add_node mmodule
104 if mmodule.in_importation < omodule then
105 poset.add_edge(mmodule, omodule)
106 end
107 end
108 end
109 return poset
110 end
111 end
112
113 redef class MClassPage
114
115 # Direct parents classes to document.
116 var parents = new HashSet[MClass]
117
118 # Transitive ancestors classes to document.
119 #
120 # Does not contain the direct ancestors.
121 # See `parents` for that.
122 var ancestors = new HashSet[MClass]
123
124 # Direct children classes to document.
125 var children = new HashSet[MClass]
126
127 # All descendants classes to document.
128 #
129 # Does not contain the direct children.
130 # See `children` for that.
131 var descendants = new HashSet[MClass]
132
133 redef fun build_poset(v, doc) do
134 poset.add_node mentity
135
136 var h = mentity.in_hierarchy(doc.mainmodule)
137 # parents
138 for mclass in h.direct_greaters do
139 if doc.mclasses.has(mclass) then parents.add mclass
140 end
141 # ancestors
142 for mclass in h.greaters do
143 if mclass == mentity then continue
144 if not doc.mclasses.has(mclass) then continue
145 if parents.has(mclass) then continue
146 ancestors.add mclass
147 end
148 # children
149 for mclass in h.direct_smallers do
150 if doc.mclasses.has(mclass) then children.add mclass
151 end
152 # descendants
153 for mclass in h.smallers do
154 if mclass == mentity then continue
155 if not doc.mclasses.has(mclass) then continue
156 if children.has(mclass) then continue
157 descendants.add mclass
158 end
159 # poset
160 var mclasses = new HashSet[MClass]
161 mclasses.add_all ancestors
162 mclasses.add_all parents
163 mclasses.add_all children
164 mclasses.add_all descendants
165 mclasses.add mentity
166 build_inheritance_poset(v, doc, mclasses)
167 end
168
169 private fun build_inheritance_poset(v: POSetPhase, doc: DocModel, mclasses: Set[MClass]): POSet[MClass] do
170 for mclass in mclasses do
171 poset.add_node mclass
172 for oclass in mclasses do
173 if mclass == oclass then continue
174 poset.add_node oclass
175 if mclass.in_hierarchy(doc.mainmodule) < oclass then
176 poset.add_edge(mclass, oclass)
177 end
178 end
179 end
180 return poset
181 end
182 end