1 # This file is part of NIT ( http://www.nitlanguage.org ).
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 # Extract data mentities of Model that will be documented.
17 # ExtractionPhase populates the DocModel that is the base for all other phases.
18 # No DocPages are created at this level.
20 # TODO build a model instead?
25 redef class ToolContext
27 # Do not generate documentation for attributes.
28 var opt_no_attributes
= new OptionBool("ignore the attributes", "--no-attributes")
30 # Do not generate documentation for private properties.
31 var opt_private
= new OptionBool("also generate private API", "--private")
35 option_context
.add_option
(opt_no_attributes
, opt_private
)
38 # Minimum visibility displayed.
41 var min_visibility
: MVisibility is lazy
do
42 if opt_private
.value
then return none_visibility
43 return protected_visibility
47 # ExtractionPhase populates the DocModel.
51 private var new_model
: Model is noinit
53 # Populates the given DocModel.
58 # Should we exclude this `mproject` from the documentation?
59 fun ignore_mentity
(mentity
: MEntity): Bool do
60 if mentity
isa MModule then
61 return mentity
.is_fictive
or mentity
.is_test_suite
62 else if mentity
isa MClass then
63 return mentity
.visibility
< ctx
.min_visibility
64 else if mentity
isa MClassDef then
65 return ignore_mentity
(mentity
.mclass
)
66 else if mentity
isa MProperty then
67 return ignore_mentity
(mentity
.intro_mclassdef
) or
68 mentity
.visibility
< ctx
.min_visibility
or
69 (ctx
.opt_no_attributes
.value
and mentity
isa MAttribute) or
70 mentity
isa MInnerClass
71 else if mentity
isa MPropDef then
72 return ignore_mentity
(mentity
.mclassdef
) or
73 ignore_mentity
(mentity
.mproperty
)
79 # TODO Should I rebuild a new Model from filtered data?
82 # MProjects that will be documented.
83 var mprojects
= new HashSet[MProject]
85 # MGroups that will be documented.
86 var mgroups
= new HashSet[MGroup]
88 # MModules that will be documented.
89 var mmodules
= new HashSet[MModule]
91 # MClasses that will be documented.
92 var mclasses
= new HashSet[MClass]
94 # MClassDefs that will be documented.
95 var mclassdefs
= new HashSet[MClassDef]
97 # MProperties that will be documented.
98 var mproperties
= new HashSet[MProperty]
100 # MPropdefs that will be documented.
101 var mpropdefs
= new HashSet[MPropDef]
103 # Populate `self` from internal `model`.
104 fun populate
(v
: ExtractionPhase) do
105 populate_mprojects
(v
)
107 populate_mproperties
(v
)
110 # Populates the `mprojects` set.
111 private fun populate_mprojects
(v
: ExtractionPhase) do
112 for mproject
in model
.mprojects
do
113 if v
.ignore_mentity
(mproject
) then continue
114 self.mprojects
.add mproject
115 for mgroup
in mproject
.mgroups
do
116 if v
.ignore_mentity
(mgroup
) then continue
117 self.mgroups
.add mgroup
118 for mmodule
in mgroup
.mmodules
do
119 if v
.ignore_mentity
(mmodule
) then continue
120 self.mmodules
.add mmodule
126 # Populates the `mclasses` set.
127 private fun populate_mclasses
(v
: ExtractionPhase) do
128 for mclass
in model
.mclasses
do
129 if v
.ignore_mentity
(mclass
) then continue
130 self.mclasses
.add mclass
131 for mclassdef
in mclass
.mclassdefs
do
132 if v
.ignore_mentity
(mclassdef
) then continue
133 self.mclassdefs
.add mclassdef
138 # Populates the `mproperties` set.
139 private fun populate_mproperties
(v
: ExtractionPhase) do
140 for mproperty
in model
.mproperties
do
141 if v
.ignore_mentity
(mproperty
) then continue
142 self.mproperties
.add mproperty
143 for mpropdef
in mproperty
.mpropdefs
do
144 if v
.ignore_mentity
(mpropdef
) then continue
145 self.mpropdefs
.add mpropdef
150 # Lists all MEntities in the model.
152 # FIXME invalidate cache if `self` is modified.
153 var mentities
: Collection[MEntity] is lazy
do
154 var res
= new HashSet[MEntity]
155 res
.add_all mprojects
159 res
.add_all mclassdefs
160 res
.add_all mproperties
161 res
.add_all mpropdefs
165 # Searches MEntities that match `name`.
166 fun mentities_by_name
(name
: String): Array[MEntity] do
167 var res
= new Array[MEntity]
168 for mentity
in mentities
do
169 if mentity
.name
!= name
then continue
175 # Looks up a MEntity by its `namespace`.
177 # Usefull when `mentities_by_name` by return conflicts.
179 # Path can be the shortest possible to disambiguise like `Class::property`.
180 # In case of larger conflicts, a more complex namespace can be given like
181 # `project::module::Class::prop`.
182 fun mentities_by_namespace
(namespace
: String): Array[MEntity] do
183 var res
= new Array[MEntity]
184 for mentity
in mentities
do
185 mentity
.mentities_by_namespace
(namespace
, res
)
192 # Looks up a MEntity by its `namespace` from `self`.
193 private fun mentities_by_namespace
(namespace
: String, res
: Array[MEntity]) do end
195 private fun lookup_in
(mentities
: Collection[MEntity], namespace
: String, res
: Array[MEntity]) do
196 var parts
= namespace
.split_once_on
("::")
197 var name
= parts
.shift
198 for mentity
in mentities
do
199 if mentity
.name
!= name
then continue
200 if parts
.is_empty
then
203 mentity
.mentities_by_namespace
(parts
.first
, res
)
210 redef fun mentities_by_namespace
(namespace
, res
) do lookup_in
(mgroups
, namespace
, res
)
214 redef fun mentities_by_namespace
(namespace
, res
) do lookup_in
(mmodules
, namespace
, res
)
218 redef fun mentities_by_namespace
(namespace
, res
) do lookup_in
(mclassdefs
, namespace
, res
)
221 redef class MClassDef
222 redef fun mentities_by_namespace
(namespace
, res
) do lookup_in
(mpropdefs
, namespace
, res
)