When running `source misc/nit_env.sh install` I noticed that it resulted in the following error:
`grep: User/user .profile: No such file or directory`
The `nit_env.sh` script created a `.profile` file in the home directory despite an existing `.bash_profile`. The `nit` command won't work since the shell will read the `.bash_profile` instead of the `profile`.
This PR checks for the existance and writes to a `.profile` or `.bashrc` or `.bash_profile`, if it finds none of those it creates a `.profile` and writes to that one.
If the PR is accepted the documentation will have to be updated.
Pull-Request: #1913
Reviewed-by: Jean Privat <jean@pryen.org>
import toolcontext
import model_ext
+import model::model_views
# The model of a Nitdoc documentation.
#
# The model is populated through `DocPhase` to be constructed.
# It is a placeholder to share data between each phase.
class DocModel
+ super ModelView
# `DocPage` composing the documentation associated to their ids.
#
# See `add_page`.
var pages: Map[String, DocPage] = new HashMap[String, DocPage]
- # Nit `Model` from which we extract the documentation.
- var model: Model is writable
-
# The entry point of the `model`.
var mainmodule: MModule is writable
# Depth of `self` in the composite tree.
fun depth: Int do
+ var parent = self.parent
if parent == null then return 0
return parent.depth + 1
end
# Avoid id conflict with group
redef fun nitdoc_id do
+ var mgroup = self.mgroup
if mgroup == null then return super
return "{mgroup.full_name}::{full_name}".to_cmangle
end
for mclass in mmodule.intro_mclasses do
if doc.mclasses.has(mclass) then intros.add mclass
end
- for mclass in mmodule.collect_redef_mclasses(v.ctx.min_visibility) do
+ for mclass in mmodule.collect_redef_mclasses(v.doc) do
if doc.mclasses.has(mclass) then redefs.add mclass
end
end
import semantize
import doc_commands
-import doc_extract
import doc_poset
import doc::console_templates
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Extract data mentities of Model that will be documented.
-#
-# ExtractionPhase populates the DocModel that is the base for all other phases.
-# No DocPages are created at this level.
-#
-# TODO build a model instead?
-module doc_extract
-
-import doc_base
-
-redef class ToolContext
-
- # Do not generate documentation for attributes.
- var opt_no_attributes = new OptionBool("Ignore the attributes", "--no-attributes")
-
- # Do not generate documentation for private properties.
- var opt_private = new OptionBool("Also generate private API", "--private")
-
- redef init do
- super
- option_context.add_option(opt_no_attributes, opt_private)
- end
-
- # Minimum visibility displayed.
- #
- # See `opt_private`.
- var min_visibility: MVisibility is lazy do
- if opt_private.value then return none_visibility
- return protected_visibility
- end
-end
-
-# ExtractionPhase populates the DocModel.
-class ExtractionPhase
- super DocPhase
-
- private var new_model: Model is noinit
-
- # Populates the given DocModel.
- redef fun apply do
- doc.populate(self)
- end
-
- # Should we exclude this `mpackage` from the documentation?
- fun ignore_mentity(mentity: MEntity): Bool do
- if mentity isa MModule then
- return mentity.is_fictive or mentity.is_test_suite
- else if mentity isa MClass then
- return mentity.visibility < ctx.min_visibility
- else if mentity isa MClassDef then
- return ignore_mentity(mentity.mclass)
- else if mentity isa MProperty then
- return ignore_mentity(mentity.intro_mclassdef) or
- mentity.visibility < ctx.min_visibility or
- (ctx.opt_no_attributes.value and mentity isa MAttribute) or
- mentity isa MInnerClass
- else if mentity isa MPropDef then
- return ignore_mentity(mentity.mclassdef) or
- ignore_mentity(mentity.mproperty)
- end
- return false
- end
-end
-
-# TODO Should I rebuild a new Model from filtered data?
-redef class DocModel
-
- # MPackages that will be documented.
- var mpackages = new HashSet[MPackage]
-
- # MGroups that will be documented.
- var mgroups = new HashSet[MGroup]
-
- # MModules that will be documented.
- var mmodules = new HashSet[MModule]
-
- # MClasses that will be documented.
- var mclasses = new HashSet[MClass]
-
- # MClassDefs that will be documented.
- var mclassdefs = new HashSet[MClassDef]
-
- # MProperties that will be documented.
- var mproperties = new HashSet[MProperty]
-
- # MPropdefs that will be documented.
- var mpropdefs = new HashSet[MPropDef]
-
- # Populate `self` from internal `model`.
- fun populate(v: ExtractionPhase) do
- populate_mpackages(v)
- populate_mclasses(v)
- populate_mproperties(v)
- end
-
- # Populates the `mpackages` set.
- private fun populate_mpackages(v: ExtractionPhase) do
- for mpackage in model.mpackages do
- if v.ignore_mentity(mpackage) then continue
- self.mpackages.add mpackage
- for mgroup in mpackage.mgroups do
- if v.ignore_mentity(mgroup) then continue
- self.mgroups.add mgroup
- for mmodule in mgroup.mmodules do
- if v.ignore_mentity(mmodule) then continue
- self.mmodules.add mmodule
- end
- end
- end
- end
-
- # Populates the `mclasses` set.
- private fun populate_mclasses(v: ExtractionPhase) do
- for mclass in model.mclasses do
- if v.ignore_mentity(mclass) then continue
- self.mclasses.add mclass
- for mclassdef in mclass.mclassdefs do
- if v.ignore_mentity(mclassdef) then continue
- self.mclassdefs.add mclassdef
- end
- end
- end
-
- # Populates the `mproperties` set.
- private fun populate_mproperties(v: ExtractionPhase) do
- for mproperty in model.mproperties do
- if v.ignore_mentity(mproperty) then continue
- self.mproperties.add mproperty
- for mpropdef in mproperty.mpropdefs do
- if v.ignore_mentity(mpropdef) then continue
- self.mpropdefs.add mpropdef
- end
- end
- end
-
- # Lists all MEntities in the model.
- #
- # FIXME invalidate cache if `self` is modified.
- var mentities: Collection[MEntity] is lazy do
- var res = new HashSet[MEntity]
- res.add_all mpackages
- res.add_all mgroups
- res.add_all mmodules
- res.add_all mclasses
- res.add_all mclassdefs
- res.add_all mproperties
- res.add_all mpropdefs
- return res
- end
-
- # Searches MEntities that match `name`.
- fun mentities_by_name(name: String): Array[MEntity] do
- var res = new Array[MEntity]
- for mentity in mentities do
- if mentity.name != name then continue
- res.add mentity
- end
- return res
- end
-
- # Looks up a MEntity by its `namespace`.
- #
- # Usefull when `mentities_by_name` by return conflicts.
- #
- # Path can be the shortest possible to disambiguise like `Class::property`.
- # In case of larger conflicts, a more complex namespace can be given like
- # `package::module::Class::prop`.
- fun mentities_by_namespace(namespace: String): Array[MEntity] do
- var res = new Array[MEntity]
- for mentity in mentities do
- mentity.mentities_by_namespace(namespace, res)
- end
- return res
- end
-end
-
-redef class MEntity
- # Looks up a MEntity by its `namespace` from `self`.
- private fun mentities_by_namespace(namespace: String, res: Array[MEntity]) do end
-
- private fun lookup_in(mentities: Collection[MEntity], namespace: String, res: Array[MEntity]) do
- var parts = namespace.split_once_on("::")
- var name = parts.shift
- for mentity in mentities do
- if mentity.name != name then continue
- if parts.is_empty then
- res.add mentity
- else
- mentity.mentities_by_namespace(parts.first, res)
- end
- end
- end
-end
-
-redef class MPackage
- redef fun mentities_by_namespace(namespace, res) do lookup_in(mgroups, namespace, res)
-end
-
-redef class MGroup
- redef fun mentities_by_namespace(namespace, res) do lookup_in(mmodules, namespace, res)
-end
-
-redef class MModule
- redef fun mentities_by_namespace(namespace, res) do lookup_in(mclassdefs, namespace, res)
-end
-
-redef class MClassDef
- redef fun mentities_by_namespace(namespace, res) do lookup_in(mpropdefs, namespace, res)
-end
# TODO filter here?
super
var mclasses = new HashSet[MClass]
- mclasses.add_all mentity.collect_intro_mclasses(v.ctx.min_visibility)
- mclasses.add_all mentity.collect_redef_mclasses(v.ctx.min_visibility)
+ mclasses.add_all mentity.collect_intro_mclasses(v.doc)
+ mclasses.add_all mentity.collect_redef_mclasses(v.doc)
if mclasses.is_empty then return
var list = new UnorderedList
list.css_classes.add "list-unstyled list-labeled"
private fun mclass_inherited_mprops(v: RenderHTMLPhase, doc: DocModel): Set[MProperty] do
var res = new HashSet[MProperty]
- var local = mentity.collect_local_mproperties(v.ctx.min_visibility)
- for mprop in mentity.collect_inherited_mproperties(v.ctx.min_visibility) do
+ var local = mentity.collect_local_mproperties(v.doc)
+ for mprop in mentity.collect_inherited_mproperties(v.doc) do
if local.has(mprop) then continue
#if mprop isa MMethod and mprop.is_init then continue
if mprop.intro.mclassdef.mclass.name == "Object" and
# Manage indexing of Nit model for Nitdoc QuickSearch.
module doc_indexing
-import doc_extract
+import doc_base
import html_templates::html_model # FIXME maybe this phase should depend on `html_render`
private import json::static
var section = new TabbedGroup("{mentity.nitdoc_id}.intros_redefs")
section.toc_title = "Intros / Redefs"
var group = new PanelGroup("list.group", "List")
- var intros = mmodule.collect_intro_mclassdefs(v.ctx.min_visibility).to_a
+ var intros = mmodule.collect_intro_mclassdefs(v.doc).to_a
doc.mainmodule.linearize_mclassdefs(intros)
group.add_child new MEntitiesListArticle("{mentity.nitdoc_id}.intros", "Introduces", intros)
- var redefs = mmodule.collect_redef_mclassdefs(v.ctx.min_visibility).to_a
+ var redefs = mmodule.collect_redef_mclassdefs(v.doc).to_a
doc.mainmodule.linearize_mclassdefs(redefs)
group.add_child new MEntitiesListArticle("{mentity.nitdoc_id}.redefs", "Redefines", redefs)
section.add_child group
var section = new TabbedGroup("{mentity.nitdoc_id}.intros_redefs")
section.toc_title = "Intros / Redefs"
var group = new PanelGroup("list.group", "List")
- var intros = mclassdef.collect_intro_mpropdefs(v.ctx.min_visibility).to_a
+ var intros = mclassdef.collect_intro_mpropdefs(v.doc).to_a
# FIXME avoid diff changes
# v.ctx.mainmodule.linearize_mpropdefs(intros)
group.add_child new MEntitiesListArticle("{mentity.nitdoc_id}.intros", "Introduces", intros)
- var redefs = mclassdef.collect_redef_mpropdefs(v.ctx.min_visibility).to_a
+ var redefs = mclassdef.collect_redef_mpropdefs(v.doc).to_a
# FIXME avoid diff changes
# v.ctx.mainmodule.linearize_mpropdefs(redefs)
group.add_child new MEntitiesListArticle("{mentity.nitdoc_id}.redefs", "Redefines", redefs)
# Create DocPage instances for each documentated Mentity.
module doc_pages
-import doc_extract
+import doc_base
# ExtractionPhase populates the DocModel with DocPage.
class MakePagePhase
if mentity isa MModule then
v.add_article new MEntitiesListArticle("Classes", null, mentity.mclassdefs)
else if mentity isa MClass then
- var mprops = mentity.collect_intro_mproperties(public_visibility)
+ var mprops = mentity.collect_intro_mproperties(mentity.public_view)
v.add_article new MEntitiesListArticle("Methods", null, mprops.to_a)
else if mentity isa MClassDef then
v.add_article new MEntitiesListArticle("Methods", null, mentity.mpropdefs)
end
end
+redef class Model
+
+ # Get a custom view for vimautocomplete.
+ private fun vim_view: ModelView do
+ var view = new ModelView(self)
+ view.min_visibility = protected_visibility
+ return view
+ end
+end
+
redef class MEntity
private fun field_separator: String do return "#====#"
private fun line_separator: String do return "#nnnn#"
stream.write line_separator*2
stream.write "## Properties"
stream.write line_separator
- var props = mclass.collect_accessible_mproperties(protected_visibility).to_a
+ var props = mclass.collect_accessible_mproperties(model.protected_view).to_a
alpha_comparator.sort props
for prop in props do
if mclass.name == "Object" or prop.intro.mclassdef.mclass.name != "Object" then
# Can it be instantiated?
if mclass.kind != interface_kind and mclass.kind != abstract_kind then
- for prop in mclass.collect_accessible_mproperties(public_visibility) do
+ for prop in mclass.collect_accessible_mproperties(model.public_view) do
if prop isa MMethod and prop.is_init then
mclass_intro.target_constructor = prop.intro
mclass_intro.write_doc(mainmodule, constructors_stream)
redef fun write_extra_doc(mainmodule, stream)
do
# Introduced classes
- var class_intros = collect_intro_mclasses(protected_visibility).to_a
+ var class_intros = collect_intro_mclasses(model.protected_view).to_a
if class_intros.not_empty then
alpha_comparator.sort class_intros
stream.write line_separator*2
# Introduced properties
var prop_intros = new Array[MPropDef]
for c in mclassdefs do
- prop_intros.add_all c.collect_intro_mpropdefs(protected_visibility)
+ prop_intros.add_all c.collect_intro_mpropdefs(model.protected_view)
end
if prop_intros.not_empty then
if self isa MMethod then
var intro = intro
assert intro isa MMethodDef
- stream.write intro.msignature.to_s
+ var msignature = intro.msignature
+ if msignature != null then
+ stream.write msignature.to_s
+ end
end
var mdoc = intro.mdoc
var out = "{toolcontext.opt_dir.value or else "metrics"}/mclasses"
out.mkdir
+ var model = toolcontext.modelbuilder.model
+ var model_view = model.private_view
print toolcontext.format_h1("\n# MClasses metrics")
var metrics = new MetricSet
- var min_vis = private_visibility
metrics.register(new CNOA(mainmodule))
metrics.register(new CNOP(mainmodule))
metrics.register(new CNOC(mainmodule))
metrics.register(new CNOD(mainmodule))
metrics.register(new CDIT(mainmodule))
- metrics.register(new CNBP(mainmodule, min_vis))
- metrics.register(new CNBA(mainmodule, min_vis))
- metrics.register(new CNBIP(mainmodule, min_vis))
- metrics.register(new CNBRP(mainmodule, min_vis))
- metrics.register(new CNBHP(mainmodule, min_vis))
+ metrics.register(new CNBP(mainmodule, model_view))
+ metrics.register(new CNBA(mainmodule, model_view))
+ metrics.register(new CNBIP(mainmodule, model_view))
+ metrics.register(new CNBRP(mainmodule, model_view))
+ metrics.register(new CNBHP(mainmodule, model_view))
#TODO metrics.register(new CNBI) # nb init
#TODO metrics.register(new CNBM) # nb methods
#TODO metrics.register(new CNBV) # nb vtypes
- var model = toolcontext.modelbuilder.model
var mclasses = new HashSet[MClass]
for mpackage in model.mpackages do
redef fun desc do return "number of accessible properties (inherited + local)"
var mainmodule: MModule
- var min_visibility: MVisibility
+ var model_view: ModelView
- init(mainmodule: MModule, min_visibility: MVisibility) do
+ init(mainmodule: MModule, model_view: ModelView) do
self.mainmodule = mainmodule
- self.min_visibility = min_visibility
+ self.model_view = model_view
end
redef fun collect(mclasses) do
for mclass in mclasses do
- values[mclass] = mclass.collect_accessible_mproperties(min_visibility).length
+ values[mclass] = mclass.collect_accessible_mproperties(model_view).length
end
end
end
redef fun desc do return "number of accessible attributes (inherited + local)"
var mainmodule: MModule
- var min_visibility: MVisibility
+ var model_view: ModelView
- init(mainmodule: MModule, min_visibility: MVisibility) do
+ init(mainmodule: MModule, model_view: ModelView) do
self.mainmodule = mainmodule
- self.min_visibility = min_visibility
+ self.model_view = model_view
end
redef fun collect(mclasses) do
for mclass in mclasses do
- values[mclass] = mclass.collect_accessible_mattributes(min_visibility).length
+ values[mclass] = mclass.collect_accessible_mattributes(model_view).length
end
end
end
redef fun desc do return "number of introduced properties"
var mainmodule: MModule
- var min_visibility: MVisibility
+ var model_view: ModelView
- init(mainmodule: MModule, min_visibility: MVisibility) do
+ init(mainmodule: MModule, model_view: ModelView) do
self.mainmodule = mainmodule
- self.min_visibility = min_visibility
+ self.model_view = model_view
end
redef fun collect(mclasses) do
for mclass in mclasses do
- values[mclass] = mclass.collect_intro_mproperties(min_visibility).length
+ values[mclass] = mclass.collect_intro_mproperties(model_view).length
end
end
end
redef fun desc do return "number of redefined properties"
var mainmodule: MModule
- var min_visibility: MVisibility
+ var model_view: ModelView
- init(mainmodule: MModule, min_visibility: MVisibility) do
+ init(mainmodule: MModule, model_view: ModelView) do
self.mainmodule = mainmodule
- self.min_visibility = min_visibility
+ self.model_view = model_view
end
redef fun collect(mclasses) do
for mclass in mclasses do
- values[mclass] = mclass.collect_redef_mproperties(min_visibility).length
+ values[mclass] = mclass.collect_redef_mproperties(model_view).length
end
end
end
redef fun desc do return "number of inherited properties"
var mainmodule: MModule
- var min_visibility: MVisibility
+ var model_view: ModelView
- init(mainmodule: MModule, min_visibility: MVisibility) do
+ init(mainmodule: MModule, model_view: ModelView) do
self.mainmodule = mainmodule
- self.min_visibility = min_visibility
+ self.model_view = model_view
end
redef fun collect(mclasses) do
for mclass in mclasses do
- values[mclass] = mclass.collect_inherited_mproperties(min_visibility).length
+ values[mclass] = mclass.collect_inherited_mproperties(model_view).length
end
end
end
redef fun desc do return "number of local properties (intro + redef)"
var mainmodule: MModule
- var min_visibility: MVisibility
+ var model_view: ModelView
- init(mainmodule: MModule, min_visibility: MVisibility) do
+ init(mainmodule: MModule, model_view: ModelView) do
self.mainmodule = mainmodule
- self.min_visibility = min_visibility
+ self.model_view = model_view
end
redef fun collect(mclasses) do
for mclass in mclasses do
- values[mclass] = mclass.collect_local_mproperties(min_visibility).length
+ values[mclass] = mclass.collect_local_mproperties(model_view).length
end
end
end
print toolcontext.format_h1("\n# Mendel metrics")
- var vis = protected_visibility
var model = toolcontext.modelbuilder.model
+ var model_view = model.protected_view
var mclasses = new HashSet[MClass]
- for mclass in model.mclasses do
- if mclass.visibility < vis then continue
+ for mclass in model_view.mclasses do
if mclass.is_interface then continue
mclasses.add(mclass)
end
- var cnblp = new CNBLP(mainmodule, vis)
+ var cnblp = new CNBLP(mainmodule, model_view)
var cnvi = new CNVI(mainmodule)
var cnvs = new CNVS(mainmodule)
csvh.format = new CsvFormat('"', ';', "\n")
csvh.header = ["povr", "ovr", "pext", "ext", "pspe", "spe", "prep", "rep", "eq"]
for mclass in mclasses do
- var povr = mclass.is_pure_overrider(vis).object_id
- var ovr = mclass.is_overrider(vis).object_id
- var pext = mclass.is_pure_extender(vis).object_id
- var ext = mclass.is_extender(vis).object_id
- var pspe = mclass.is_pure_specializer(vis).object_id
- var spe = mclass.is_pure_specializer(vis).object_id
- var prep = mclass.is_pure_replacer(vis).object_id
- var rep = mclass.is_replacer(vis).object_id
- var eq = mclass.is_equal(vis).object_id
+ var povr = mclass.is_pure_overrider(model_view).object_id
+ var ovr = mclass.is_overrider(model_view).object_id
+ var pext = mclass.is_pure_extender(model_view).object_id
+ var ext = mclass.is_extender(model_view).object_id
+ var pspe = mclass.is_pure_specializer(model_view).object_id
+ var spe = mclass.is_pure_specializer(model_view).object_id
+ var prep = mclass.is_pure_replacer(model_view).object_id
+ var rep = mclass.is_replacer(model_view).object_id
+ var eq = mclass.is_equal(model_view).object_id
csvh.add_record(povr, ovr, pext, ext, pspe, spe, prep, rep, eq)
end
csvh.save("{out}/inheritance_behaviour.csv")
# Mainmodule used to compute class hierarchy.
var mainmodule: MModule
+ private var protected_view: ModelView = mainmodule.model.protected_view is lateinit
redef fun collect(mclasses) do
for mclass in mclasses do
- var totc = mclass.collect_accessible_mproperties(protected_visibility).length
+ var totc = mclass.collect_accessible_mproperties(protected_view).length
var ditc = mclass.in_hierarchy(mainmodule).depth
values[mclass] = totc.to_f / (ditc + 1).to_f
end
redef fun collect(mmodules) do
for mmodule in mmodules do
- var totc = mmodule.collect_intro_mclassdefs(protected_visibility).length
- totc += mmodule.collect_redef_mclassdefs(protected_visibility).length
+ var totc = mmodule.collect_intro_mclassdefs(mmodule.protected_view).length
+ totc += mmodule.collect_redef_mclassdefs(mmodule.protected_view).length
var ditc = mmodule.in_importation.depth
values[mmodule] = totc.to_f / (ditc + 1).to_f
end
# Mainmodule used to compute class hierarchy.
var mainmodule: MModule
+ private var protected_view: ModelView = mainmodule.model.protected_view is lateinit
redef fun collect(mclasses) do
var cbms = new CBMS(mainmodule)
cbms.clear
cbms.collect(new HashSet[MClass].from(parents))
# compute class novelty index
- var locc = mclass.collect_accessible_mproperties(protected_visibility).length
+ var locc = mclass.collect_accessible_mproperties(protected_view).length
values[mclass] = locc.to_f / cbms.avg
else
values[mclass] = 0.0
mbms.clear
mbms.collect(new HashSet[MModule].from(parents))
# compute module novelty index
- var locc = mmodule.collect_intro_mclassdefs(protected_visibility).length
- locc += mmodule.collect_redef_mclassdefs(protected_visibility).length
+ var locc = mmodule.collect_intro_mclassdefs(mmodule.protected_view).length
+ locc += mmodule.collect_redef_mclassdefs(mmodule.protected_view).length
values[mmodule] = locc.to_f / mbms.avg
else
values[mmodule] = 0.0
# Mainmodule used to compute class hierarchy.
var mainmodule: MModule
+ private var protected_view: ModelView = mainmodule.model.protected_view is lateinit
redef fun collect(mclasses) do
var cnvi = new CNVI(mainmodule)
cnvi.collect(mclasses)
for mclass in mclasses do
- var locc = mclass.collect_local_mproperties(protected_visibility).length
+ var locc = mclass.collect_local_mproperties(protected_view).length
values[mclass] = cnvi.values[mclass] * locc.to_f
end
end
var mnvi = new MNVI
mnvi.collect(mmodules)
for mmodule in mmodules do
- var locc = mmodule.collect_intro_mclassdefs(protected_visibility).length
- locc += mmodule.collect_redef_mclassdefs(protected_visibility).length
+ var locc = mmodule.collect_intro_mclassdefs(mmodule.protected_view).length
+ locc += mmodule.collect_redef_mclassdefs(mmodule.protected_view).length
values[mmodule] = mnvi.values[mmodule] * locc.to_f
end
end
redef class MClass
# the set of redefition that call to super
- fun extended_mproperties(min_visibility: MVisibility): Set[MProperty] do
+ fun extended_mproperties(view: ModelView): Set[MProperty] do
var set = new HashSet[MProperty]
for mclassdef in mclassdefs do
for mpropdef in mclassdef.mpropdefs do
- if mpropdef.mproperty.visibility < min_visibility then continue
+ if not view.accept_mentity(mpropdef) then continue
if not mpropdef.has_supercall then continue
if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
end
end
# the set of redefition that do not call to super
- fun overriden_mproperties(min_visibility: MVisibility): Set[MProperty] do
+ fun overriden_mproperties(view: ModelView): Set[MProperty] do
var set = new HashSet[MProperty]
for mclassdef in mclassdefs do
for mpropdef in mclassdef.mpropdefs do
- if mpropdef.mproperty.visibility < min_visibility then continue
+ if not view.accept_mentity(mpropdef) then continue
if mpropdef.has_supercall then continue
if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
end
end
# pure overriders contain only redefinitions
- private fun is_pure_overrider(min_visibility: MVisibility): Bool do
- var news = collect_intro_mproperties(min_visibility).length
- var locs = collect_local_mproperties(min_visibility).length
+ private fun is_pure_overrider(view: ModelView): Bool do
+ var news = collect_intro_mproperties(view).length
+ var locs = collect_local_mproperties(view).length
if news == 0 and locs > 0 then return true
return false
end
# overriders contain more definitions than introductions
- private fun is_overrider(min_visibility: MVisibility): Bool do
- var rdfs = collect_redef_mproperties(min_visibility).length
- var news = collect_intro_mproperties(min_visibility).length
- var locs = collect_local_mproperties(min_visibility).length
+ private fun is_overrider(view: ModelView): Bool do
+ var rdfs = collect_redef_mproperties(view).length
+ var news = collect_intro_mproperties(view).length
+ var locs = collect_local_mproperties(view).length
if rdfs >= news and locs > 0 then return true
return false
end
# pure extenders contain only introductions
- private fun is_pure_extender(min_visibility: MVisibility): Bool do
- var rdfs = collect_redef_mproperties(min_visibility).length
- var locs = collect_local_mproperties(min_visibility).length
+ private fun is_pure_extender(view: ModelView): Bool do
+ var rdfs = collect_redef_mproperties(view).length
+ var locs = collect_local_mproperties(view).length
if rdfs == 0 and locs > 0 then return true
return false
end
# extenders contain more introduction than redefinitions
- private fun is_extender(min_visibility: MVisibility): Bool do
- var rdfs = collect_redef_mproperties(min_visibility).length
- var news = collect_intro_mproperties(min_visibility).length
- var locs = collect_local_mproperties(min_visibility).length
+ private fun is_extender(view: ModelView): Bool do
+ var rdfs = collect_redef_mproperties(view).length
+ var news = collect_intro_mproperties(view).length
+ var locs = collect_local_mproperties(view).length
if news > rdfs and locs > 0 then return true
return false
end
# pure specializers always call to super in its redefinitions
- private fun is_pure_specializer(min_visibility: MVisibility): Bool do
- var ovrs = overriden_mproperties(min_visibility).length
- var rdfs = collect_redef_mproperties(min_visibility).length
+ private fun is_pure_specializer(view: ModelView): Bool do
+ var ovrs = overriden_mproperties(view).length
+ var rdfs = collect_redef_mproperties(view).length
if ovrs == 0 and rdfs > 0 then return true
return false
end
# specializers have more redefinitions that call super than not calling it
- private fun is_specializer(min_visibility: MVisibility): Bool do
- var spcs = extended_mproperties(min_visibility).length
- var ovrs = overriden_mproperties(min_visibility).length
- var rdfs = collect_redef_mproperties(min_visibility).length
+ private fun is_specializer(view: ModelView): Bool do
+ var spcs = extended_mproperties(view).length
+ var ovrs = overriden_mproperties(view).length
+ var rdfs = collect_redef_mproperties(view).length
if spcs > ovrs and rdfs > 0 then return true
return false
end
# pure replacers never call to super in its redefinitions
- private fun is_pure_replacer(min_visibility: MVisibility): Bool do
- var spcs = extended_mproperties(min_visibility).length
- var rdfs = collect_redef_mproperties(min_visibility).length
+ private fun is_pure_replacer(view: ModelView): Bool do
+ var spcs = extended_mproperties(view).length
+ var rdfs = collect_redef_mproperties(view).length
if spcs == 0 and rdfs > 0 then return true
return false
end
# replacers have less redefinitions that call super than not calling it
- private fun is_replacer(min_visibility: MVisibility): Bool do
- var spcs = extended_mproperties(min_visibility).length
- var ovrs = overriden_mproperties(min_visibility).length
- var rdfs = collect_redef_mproperties(min_visibility).length
+ private fun is_replacer(view: ModelView): Bool do
+ var spcs = extended_mproperties(view).length
+ var ovrs = overriden_mproperties(view).length
+ var rdfs = collect_redef_mproperties(view).length
if ovrs > spcs and rdfs > 0 then return true
return false
end
# equals contain as redifinition than introduction
- private fun is_equal(min_visibility: MVisibility): Bool do
- var spcs = extended_mproperties(min_visibility).length
- var ovrs = overriden_mproperties(min_visibility).length
- var rdfs = collect_redef_mproperties(min_visibility).length
+ private fun is_equal(view: ModelView): Bool do
+ var spcs = extended_mproperties(view).length
+ var ovrs = overriden_mproperties(view).length
+ var rdfs = collect_redef_mproperties(view).length
if spcs == ovrs and rdfs > 0 then return true
return false
end
print toolcontext.format_h1("\n# Nullable metrics")
+ var model = toolcontext.modelbuilder.model
+ var model_view = model.private_view
+
var metrics = new MetricSet
- var min_vis = private_visibility
- metrics.register(new CNBA(mainmodule, min_vis))
- metrics.register(new CNBNA(mainmodule, min_vis))
+ metrics.register(new CNBA(mainmodule, model_view))
+ metrics.register(new CNBNA(mainmodule, model_view))
- var model = toolcontext.modelbuilder.model
var mclasses = new HashSet[MClass]
for mpackage in model.mpackages do
redef fun desc do return "number of accessible nullable attributes (inherited + local)"
var mainmodule: MModule
- var min_visibility: MVisibility
+ var model_view: ModelView
- init(mainmodule: MModule, min_visibility: MVisibility) do
+ init(mainmodule: MModule, model_view: ModelView) do
self.mainmodule = mainmodule
- self.min_visibility = min_visibility
+ self.model_view = model_view
end
redef fun collect(mclasses) do
for mclass in mclasses do
- var all = mclass.collect_accessible_mattributes(min_visibility)
+ var all = mclass.collect_accessible_mattributes(model_view)
for mattr in all do
if mattr.is_nullable then values.inc(mclass)
end
# A model knows modules, classes and properties and can retrieve them.
class Model
super MEntity
+
+ redef fun model do return self
end
# A named and possibly documented entity in the model.
# entities could not be reachable depending on the modules really imported.
module model_collect
-import model
-
-redef class MEntity
-
- # Collect mentities with a fully qualified `namespace`.
- fun collect_by_namespace(namespace: String): Array[MEntity] is abstract
-
- private fun lookup_in(mentities: Collection[MEntity], namespace: String, res: Array[MEntity]) do
- var parts = namespace.split_once_on("::")
- var name = parts.shift
- for mentity in mentities do
- if mentity.name != name then continue
- if parts.is_empty then
- res.add mentity
- else
- res.add_all mentity.collect_by_namespace(parts.first)
- end
- end
- end
-end
-
-redef class Model
- redef fun collect_by_namespace(namespace) do
- var res = new Array[MEntity]
- var parts = namespace.split_once_on("::")
- var name = parts.shift
- for mentity in mpackages do
- if mentity.name != name then continue
- if parts.is_empty then
- res.add mentity
- else
- res.add_all mentity.collect_by_namespace(parts.first)
- end
- end
- return res
- end
-end
-
-redef class MPackage
- redef fun collect_by_namespace(namespace) do
- var res = new Array[MEntity]
- var root = self.root
- if root == null then return res
- lookup_in([root], namespace, res)
- return res
- end
-end
-
-redef class MGroup
- redef fun collect_by_namespace(namespace) do
- var res = new Array[MEntity]
- lookup_in(in_nesting.direct_smallers, namespace, res)
- lookup_in(mmodules, namespace, res)
- return res
- end
-end
+import model_views
redef class MModule
- redef fun collect_by_namespace(namespace) do
- var res = new Array[MEntity]
- lookup_in(mclassdefs, namespace, res)
- return res
- end
-
# Collect mclassdefs introduced in `self` with `visibility >= to min_visibility`.
- fun collect_intro_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
+ fun collect_intro_mclassdefs(view: ModelView): Set[MClassDef] do
var res = new HashSet[MClassDef]
for mclassdef in mclassdefs do
if not mclassdef.is_intro then continue
- if mclassdef.mclass.visibility < min_visibility then continue
+ if not view.accept_mentity(mclassdef) then continue
res.add mclassdef
end
return res
end
# Collect mclassdefs redefined in `self` with `visibility >= to min_visibility`.
- fun collect_redef_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
+ fun collect_redef_mclassdefs(view: ModelView): Set[MClassDef] do
var res = new HashSet[MClassDef]
for mclassdef in mclassdefs do
if mclassdef.is_intro then continue
- if mclassdef.mclass.visibility < min_visibility then continue
+ if not view.accept_mentity(mclassdef) then continue
res.add mclassdef
end
return res
end
# Collect mclasses introduced in `self` with `visibility >= to min_visibility`.
- fun collect_intro_mclasses(min_visibility: MVisibility): Set[MClass] do
+ fun collect_intro_mclasses(view: ModelView): Set[MClass] do
var res = new HashSet[MClass]
for mclass in intro_mclasses do
- if mclass.visibility < min_visibility then continue
+ if not view.accept_mentity(mclass) then continue
res.add mclass
end
return res
end
# Collect mclasses redefined in `self` with `visibility >= to min_visibility`.
- fun collect_redef_mclasses(min_visibility: MVisibility): Set[MClass] do
+ fun collect_redef_mclasses(view: ModelView): Set[MClass] do
var mclasses = new HashSet[MClass]
- for c in mclassdefs do
- if c.mclass.visibility < min_visibility then continue
- if not c.is_intro then mclasses.add(c.mclass)
+ for mclassdef in mclassdefs do
+ if not view.accept_mentity(mclassdef) then continue
+ if not mclassdef.is_intro then mclasses.add(mclassdef.mclass)
end
return mclasses
end
redef class MClass
# Collect direct parents of `self` with `visibility >= to min_visibility`.
- fun collect_parents(min_visibility: MVisibility): Set[MClass] do
+ fun collect_parents(view: ModelView): Set[MClass] do
var res = new HashSet[MClass]
for mclassdef in mclassdefs do
for mclasstype in mclassdef.supertypes do
var mclass = mclasstype.mclass
- if mclass.visibility < min_visibility then continue
+ if not view.accept_mentity(mclass) then continue
res.add(mclass)
end
end
end
# Collect all ancestors of `self` with `visibility >= to min_visibility`.
- fun collect_ancestors(min_visibility: MVisibility): Set[MClass] do
+ fun collect_ancestors(view: ModelView): Set[MClass] do
var res = new HashSet[MClass]
for mclassdef in self.mclassdefs do
for super_mclassdef in mclassdef.in_hierarchy.greaters do
if super_mclassdef == mclassdef then continue # skip self
var mclass = super_mclassdef.mclass
- if mclass.visibility < min_visibility then continue
+ if not view.accept_mentity(mclass) then continue
res.add(mclass)
end
end
end
# Collect direct children of `self` with `visibility >= to min_visibility`.
- fun collect_children(min_visibility: MVisibility): Set[MClass] do
+ fun collect_children(view: ModelView): Set[MClass] do
var res = new HashSet[MClass]
for mclassdef in self.mclassdefs do
for sub_mclassdef in mclassdef.in_hierarchy.direct_smallers do
if sub_mclassdef == mclassdef then continue # skip self
var mclass = sub_mclassdef.mclass
- if mclass.visibility < min_visibility then continue
+ if not view.accept_mentity(mclass) then continue
res.add(mclass)
end
end
end
# Collect all descendants of `self` with `visibility >= to min_visibility`.
- fun descendants(min_visibility: MVisibility): Set[MClass] do
+ fun collect_descendants(view: ModelView): Set[MClass] do
var res = new HashSet[MClass]
for mclassdef in self.mclassdefs do
for sub_mclassdef in mclassdef.in_hierarchy.smallers do
if sub_mclassdef == mclassdef then continue # skip self
var mclass = sub_mclassdef.mclass
- if mclass.visibility < min_visibility then continue
+ if not view.accept_mentity(mclass) then continue
res.add(mclass)
end
end
end
# Collect all mproperties introduced in 'self' with `visibility >= min_visibility`.
- fun collect_intro_mproperties(min_visibility: MVisibility): Set[MProperty] do
+ fun collect_intro_mproperties(view: ModelView): Set[MProperty] do
var set = new HashSet[MProperty]
for mclassdef in mclassdefs do
for mprop in mclassdef.intro_mproperties do
- if mprop.visibility < min_visibility then continue
+ if not view.accept_mentity(mprop) then continue
set.add(mprop)
end
end
end
# Collect all mproperties redefined in 'self' with `visibility >= min_visibility`.
- fun collect_redef_mproperties(min_visibility: MVisibility): Set[MProperty] do
+ fun collect_redef_mproperties(view: ModelView): Set[MProperty] do
var set = new HashSet[MProperty]
for mclassdef in mclassdefs do
for mpropdef in mclassdef.mpropdefs do
- if mpropdef.mproperty.visibility < min_visibility then continue
- if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
+ if mpropdef.mproperty.intro_mclassdef.mclass == self then continue
+ if not view.accept_mentity(mpropdef) then continue
+ set.add(mpropdef.mproperty)
end
end
return set
end
# Collect mproperties introduced and redefined in 'self' with `visibility >= min_visibility`.
- fun collect_local_mproperties(min_visibility: MVisibility): Set[MProperty] do
+ fun collect_local_mproperties(view: ModelView): Set[MProperty] do
var set = new HashSet[MProperty]
- set.add_all collect_intro_mproperties(min_visibility)
- set.add_all collect_redef_mproperties(min_visibility)
+ set.add_all collect_intro_mproperties(view)
+ set.add_all collect_redef_mproperties(view)
return set
end
# Collect all mproperties inehrited by 'self' with `visibility >= min_visibility`.
- fun collect_inherited_mproperties(min_visibility: MVisibility): Set[MProperty] do
+ fun collect_inherited_mproperties(view: ModelView): Set[MProperty] do
var set = new HashSet[MProperty]
- for parent in collect_parents(min_visibility) do
- set.add_all(parent.collect_intro_mproperties(min_visibility))
- set.add_all(parent.collect_inherited_mproperties(min_visibility))
+ for parent in collect_parents(view) do
+ set.add_all(parent.collect_intro_mproperties(view))
+ set.add_all(parent.collect_inherited_mproperties(view))
end
return set
end
# Collect all mproperties accessible by 'self' with `visibility >= min_visibility`.
#
# This include introduced, redefined, inherited mproperties.
- fun collect_accessible_mproperties(min_visibility: MVisibility): Set[MProperty] do
+ fun collect_accessible_mproperties(view: ModelView): Set[MProperty] do
var set = new HashSet[MProperty]
- set.add_all(collect_intro_mproperties(min_visibility))
- set.add_all(collect_redef_mproperties(min_visibility))
- set.add_all(collect_inherited_mproperties(min_visibility))
+ set.add_all(collect_intro_mproperties(view))
+ set.add_all(collect_redef_mproperties(view))
+ set.add_all(collect_inherited_mproperties(view))
return set
end
# Collect mmethods introduced in 'self' with `visibility >= min_visibility`.
- fun collect_intro_mmethods(min_visibility: MVisibility): Set[MMethod] do
+ fun collect_intro_mmethods(view: ModelView): Set[MMethod] do
var res = new HashSet[MMethod]
- for mproperty in collect_intro_mproperties(min_visibility) do
+ for mproperty in collect_intro_mproperties(view) do
if mproperty isa MMethod then res.add(mproperty)
end
return res
end
# Collect mmethods redefined in 'self' with `visibility >= min_visibility`.
- fun collect_redef_mmethods(min_visibility: MVisibility): Set[MMethod] do
+ fun collect_redef_mmethods(view: ModelView): Set[MMethod] do
var res = new HashSet[MMethod]
- for mproperty in collect_redef_mproperties(min_visibility) do
+ for mproperty in collect_redef_mproperties(view) do
if mproperty isa MMethod then res.add(mproperty)
end
return res
end
# Collect mmethods introduced and redefined in 'self' with `visibility >= min_visibility`.
- fun collect_local_mmethods(min_visibility: MVisibility): Set[MMethod] do
+ fun collect_local_mmethods(view: ModelView): Set[MMethod] do
var set = new HashSet[MMethod]
- set.add_all collect_intro_mmethods(min_visibility)
- set.add_all collect_redef_mmethods(min_visibility)
+ set.add_all collect_intro_mmethods(view)
+ set.add_all collect_redef_mmethods(view)
return set
end
# Collect mattributes introduced in 'self' with `visibility >= min_visibility`.
- fun collect_intro_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+ fun collect_intro_mattributes(view: ModelView): Set[MAttribute] do
var res = new HashSet[MAttribute]
- for mproperty in collect_intro_mproperties(min_visibility) do
+ for mproperty in collect_intro_mproperties(view) do
if mproperty isa MAttribute then res.add(mproperty)
end
return res
end
# Collect mattributes redefined in 'self' with `visibility >= min_visibility`.
- fun collect_redef_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+ fun collect_redef_mattributes(view: ModelView): Set[MAttribute] do
var res = new HashSet[MAttribute]
- for mproperty in collect_redef_mproperties(min_visibility) do
+ for mproperty in collect_redef_mproperties(view) do
if mproperty isa MAttribute then res.add(mproperty)
end
return res
end
# Collect mattributes introduced and redefined in 'self' with `visibility >= min_visibility`.
- fun collect_local_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+ fun collect_local_mattributes(view: ModelView): Set[MAttribute] do
var set = new HashSet[MAttribute]
- set.add_all collect_intro_mattributes(min_visibility)
- set.add_all collect_redef_mattributes(min_visibility)
+ set.add_all collect_intro_mattributes(view)
+ set.add_all collect_redef_mattributes(view)
return set
end
# Collect mattributes inherited by 'self' with `visibility >= min_visibility`.
- fun collect_inherited_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+ fun collect_inherited_mattributes(view: ModelView): Set[MAttribute] do
var res = new HashSet[MAttribute]
- for mproperty in collect_inherited_mproperties(min_visibility) do
+ for mproperty in collect_inherited_mproperties(view) do
if mproperty isa MAttribute then res.add(mproperty)
end
return res
# Collect all mattributes accessible by 'self' with `visibility >= min_visibility`.
#
# This include introduced, redefined, inherited mattributes.
- fun collect_accessible_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+ fun collect_accessible_mattributes(view: ModelView): Set[MAttribute] do
var set = new HashSet[MAttribute]
- set.add_all(collect_intro_mattributes(min_visibility))
- set.add_all(collect_redef_mattributes(min_visibility))
- set.add_all(collect_inherited_mattributes(min_visibility))
+ set.add_all(collect_intro_mattributes(view))
+ set.add_all(collect_redef_mattributes(view))
+ set.add_all(collect_inherited_mattributes(view))
return set
end
end
redef class MClassDef
- redef fun collect_by_namespace(namespace) do
- var res = new Array[MEntity]
- lookup_in(mpropdefs, namespace, res)
- return res
- end
-
# Collect mpropdefs in 'self' with `visibility >= min_visibility`.
- fun collect_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
+ fun collect_mpropdefs(view: ModelView): Set[MPropDef] do
var res = new HashSet[MPropDef]
for mpropdef in mpropdefs do
- if mpropdef.mproperty.visibility < min_visibility then continue
+ if not view.accept_mentity(mpropdef) then continue
res.add mpropdef
end
return res
end
# Collect mpropdefs introduced in 'self' with `visibility >= min_visibility`.
- fun collect_intro_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
+ fun collect_intro_mpropdefs(view: ModelView): Set[MPropDef] do
var res = new HashSet[MPropDef]
for mpropdef in mpropdefs do
if not mpropdef.is_intro then continue
- if mpropdef.mproperty.visibility < min_visibility then continue
+ if not view.accept_mentity(mpropdef) then continue
res.add mpropdef
end
return res
end
# Collect mpropdefs redefined in 'self' with `visibility >= min_visibility`.
- fun collect_redef_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
+ fun collect_redef_mpropdefs(view: ModelView): Set[MPropDef] do
var res = new HashSet[MPropDef]
for mpropdef in mpropdefs do
if mpropdef.is_intro then continue
- if mpropdef.mproperty.visibility < min_visibility then continue
+ if not view.accept_mentity(mpropdef) then continue
res.add mpropdef
end
return res
# Nitdoc generation phase.
var docphase: Phase = new Nitdoc(self, null)
- init do super # to fix ambiguous linearization
+ # Do not generate documentation for attributes.
+ var opt_no_attributes = new OptionBool("Ignore the attributes", "--no-attributes")
+
+ # Do not generate documentation for private properties.
+ var opt_private = new OptionBool("Also generate private API", "--private")
+
+ redef init do
+ super
+ option_context.add_option(opt_no_attributes, opt_private)
+ end
end
# Nitdoc phase explores the model and generate pages for each mentities found
redef fun process_mainmodule(mainmodule, mmodules)
do
var doc = new DocModel(mainmodule.model, mainmodule)
+ if not toolcontext.opt_private.value then doc.min_visibility = protected_visibility
+ if not toolcontext.opt_no_attributes.value then doc.include_attribute = false
var phases = [
- new ExtractionPhase(toolcontext, doc),
new IndexingPhase(toolcontext, doc),
new MakePagePhase(toolcontext, doc),
new POSetPhase(toolcontext, doc),
import uml
redef class ToolContext
+
+ # Phase that generates UML diagrams from model entities.
var umlphase: Phase = new UMLPhase(self, null)
+ # What to generate?
var opt_gen = new OptionEnum(["class", "package"], "Choose which type of uml diagram to generate", 0, "--diagram")
+ # Generate private?
+ var opt_privacy = new OptionBool("Generates private API", "-p", "--private")
+
redef init do
option_context.add_option opt_gen
+ option_context.add_option opt_privacy
super
end
end
super Phase
redef fun process_mainmodule(mainmodule, mmodules)
do
- var d = new UMLModel(mainmodule.model, mainmodule, toolcontext)
+ var view = new ModelView(mainmodule.model)
+ if not toolcontext.opt_privacy.value then
+ view.min_visibility = protected_visibility
+ end
+
+ var d = new UMLModel(view, mainmodule)
if toolcontext.opt_gen.value == 0 then
print d.generate_class_uml.write_to_string
else if toolcontext.opt_gen.value == 1 then
var doc = new DocModel(mainmodule.model, mainmodule)
var phases = [
- new ExtractionPhase(toolcontext, doc),
new MakePagePhase(toolcontext, doc),
new ConcernsPhase(toolcontext, doc),
new StructurePhase(toolcontext, doc),
module uml_base
import toolcontext
-import model
+import model::model_collect
-redef class ToolContext
- # -p
- var opt_privacy = new OptionBool("Generates private API", "-p", "--private")
-
- # Shortcut for the value of `self.opt_privacy`
- fun private_gen: Bool do return opt_privacy.value
+# UML model builder.
+class UMLModel
- redef init do
- option_context.add_option opt_privacy
- super
- end
-end
+ # Model view
+ var view: ModelView
-class UMLModel
- var model: Model
+ # Main module used for linearization.
var mainmodule: MModule
- var ctx: ToolContext
end
fontname = "Bitstream Vera Sans"
fontsize = 8
]\n"""
- tpl.add model.tpl_class(ctx, mainmodule)
+ for mclass in view.mclasses do
+ tpl.add mclass.tpl_class(self)
+ tpl.add "\n"
+ end
tpl.add "\}"
return tpl
end
end
-redef class Model
-
- # Generates a UML Class diagram from the entities of a `Model`
- redef fun tpl_class(ctx, main) do
- var t = new Template
- for i in mclasses do
- if not ctx.private_gen and i.visibility != public_visibility then continue
- t.add i.tpl_class(ctx, main)
- t.add "\n"
- end
- return t
- end
-
-end
-
redef class MEntity
# Generates a dot-compatible `Writable` UML Class diagram from `self`
- fun tpl_class(ctx: ToolContext, main: MModule): Writable is abstract
+ fun tpl_class(model: UMLModel): Writable is abstract
end
redef class MClass
- redef fun tpl_class(ctx, main) do
+ redef fun tpl_class(model) do
var t = new Template
t.add "{name} [\n label = \"\{"
if kind == abstract_kind then
t.add "]"
end
t.add "|"
- var props: Collection[MProperty]
- if ctx.private_gen then
- props = collect_intro_mproperties(none_visibility)
- else
- props = collect_intro_mproperties(public_visibility)
- end
+ var props = collect_intro_mproperties(model.view)
for i in props do
- if i isa MAttribute then
- t.add i.tpl_class(ctx, main)
- t.add "\\l"
- end
+ if not i isa MAttribute then continue
+ t.add i.tpl_class(model)
+ t.add "\\l"
end
t.add "|"
- var meths
- if ctx.private_gen then
- meths = collect_intro_mmethods(none_visibility)
- else
- meths = collect_intro_mmethods(public_visibility)
- end
- for i in meths do
- t.add i.tpl_class(ctx, main)
+ for i in props do
+ if not i isa MMethod then continue
+ t.add i.tpl_class(model)
t.add "\\l"
end
t.add "\}\"\n]\n"
- var g = in_hierarchy(main).direct_greaters
+ var g = in_hierarchy(model.mainmodule).direct_greaters
for i in g do
- if not ctx.private_gen and i.visibility != public_visibility then continue
+ if not model.view.accept_mentity(i) then continue
t.add "{i.name} -> {name} [dir=back"
if i.kind == interface_kind then
t.add " arrowtail=open style=dashed"
end
redef class MMethod
- redef fun tpl_class(ctx, main) do
+ redef fun tpl_class(model) do
var tpl = new Template
tpl.add visibility.tpl_class
tpl.add " "
tpl.add name.escape_to_dot
- tpl.add intro.msignature.tpl_class(ctx, main)
+ tpl.add intro.msignature.tpl_class(model)
return tpl
end
end
redef class MSignature
- redef fun tpl_class(ctx, main) do
+ redef fun tpl_class(model) do
var t = new Template
t.add "("
var params = new Array[MParameter]
if params.length > 0 then
t.add params.first.name
t.add ": "
- t.add params.first.mtype.tpl_class(ctx, main)
+ t.add params.first.mtype.tpl_class(model)
for i in [1 .. params.length [ do
t.add ", "
t.add params[i].name
t.add ": "
- t.add params[i].mtype.tpl_class(ctx, main)
+ t.add params[i].mtype.tpl_class(model)
end
end
t.add ")"
if return_mtype != null then
t.add ": "
- t.add return_mtype.tpl_class(ctx, main)
+ t.add return_mtype.tpl_class(model)
end
return t
end
end
redef class MAttribute
- redef fun tpl_class(ctx, main) do
+ redef fun tpl_class(model) do
var tpl = new Template
tpl.add visibility.tpl_class
tpl.add " "
tpl.add name
tpl.add ": "
- tpl.add intro.static_mtype.tpl_class(ctx, main)
+ tpl.add intro.static_mtype.tpl_class(model)
return tpl
end
end
end
redef class MClassType
- redef fun tpl_class(c, m) do
+ redef fun tpl_class(model) do
return name
end
end
redef class MGenericType
- redef fun tpl_class(c, m) do
+ redef fun tpl_class(model) do
var t = new Template
t.add name.substring(0, name.index_of('['))
t.add "["
- t.add arguments.first.tpl_class(c, m)
+ t.add arguments.first.tpl_class(model)
for i in [1 .. arguments.length[ do
t.add ", "
- t.add arguments[i].tpl_class(c, m)
+ t.add arguments[i].tpl_class(model)
end
t.add "]"
return t
end
redef class MParameterType
- redef fun tpl_class(c, m) do
+ redef fun tpl_class(model) do
return name
end
end
redef class MVirtualType
- redef fun tpl_class(c, m) do
+ redef fun tpl_class(model) do
return name
end
end
redef class MNullableType
- redef fun tpl_class(c, m) do
+ redef fun tpl_class(model) do
var t = new Template
t.add "nullable "
- t.add mtype.tpl_class(c, m)
+ t.add mtype.tpl_class(model)
return t
end
end
fontname = "Bitstream Vera Sans"
fontsize = 8
]\n"""
- tpl.add model.tpl_module(ctx, mainmodule)
+ tpl.add mainmodule.tpl_module(self)
tpl.add "\}"
return tpl
end
end
-redef class Model
- # Returns a UML package diagram of `main`
- redef fun tpl_module(ctx, main) do
- return main.tpl_module(ctx, main)
- end
+redef class MEntity
+ # Builds a dot UML package diagram entity from `self`
+ fun tpl_module(model: UMLModel): Writable is abstract
end
redef class MModule
- redef fun tpl_module(ctx, main) do
+ redef fun tpl_module(model) do
var t = new Template
t.add "subgraph cluster{name} \{\n"
t.add "label = \"{name}\"\n"
for i in mclassdefs do
- if not ctx.private_gen and i.mclass.visibility != public_visibility then continue
- t.add i.tpl_module(ctx, main)
+ if not model.view.accept_mentity(i) then continue
+ t.add i.tpl_module(model)
end
t.add "\}\n"
return t
end
end
-redef class MEntity
- # Builds a dot UML package diagram entity from `self`
- fun tpl_module(ctx: ToolContext, main: MModule): Writable is abstract
-end
-
redef class MClassDef
# Colour for the border of a class when first introduced
# Defaults to a shade of red
var redef_colour = "#B24758"
- redef fun tpl_module(ctx, main) do
+ redef fun tpl_module(model) do
var t = new Template
t.add "{mmodule}{name} [\n\tlabel = \"\{"
if mclass.kind == abstract_kind then
t.add "|"
for i in mpropdefs do
if not i isa MAttributeDef then continue
- if not ctx.private_gen and i.mproperty.visibility != public_visibility then continue
- t.add i.tpl_module(ctx, main)
+ if not model.view.accept_mentity(i) then continue
+ t.add i.tpl_module(model)
t.add "\\l"
end
t.add "|"
for i in mpropdefs do
if not i isa MMethodDef then continue
- if not ctx.private_gen and i.mproperty.visibility != public_visibility then continue
- t.add i.tpl_module(ctx, main)
+ if not model.view.accept_mentity(i) then continue
+ t.add i.tpl_module(model)
t.add "\\l"
end
t.add "\}\""
end
redef class MMethodDef
- redef fun tpl_module(ctx, main) do
+ redef fun tpl_module(model) do
var t = new Template
t.add mproperty.visibility.tpl_class
t.add " "
t.add name.escape_to_dot
- t.add msignature.tpl_class(ctx, main)
+ t.add msignature.tpl_class(model)
return t
end
end
redef class MAttributeDef
- redef fun tpl_module(ctx, main) do
+ redef fun tpl_module(model) do
var t = new Template
t.add mproperty.visibility.tpl_class
t.add " "
t.add name
t.add ": "
- t.add static_mtype.tpl_class(ctx, main)
+ t.add static_mtype.tpl_class(model)
return t
end
end
module model_html
import model
-import model::model_collect
import doc::doc_down
import html::bootstrap
#
# Mainly used for icons.
var css_classes = new Array[String]
-
- # HTML Tree containing all the nested element of `self`.
- #
- # The nested elements depend on the type of `self`:
- # `MPackage`: root mgroup
- # `MGroup`: directly nested mgroups, mmodules
- # `MModule`: mclassdefs
- # `MClassDef`: mpropdefs
- fun html_tree: UnorderedList do
- var list = new UnorderedList
- list.add_li html_tree_li
- return list
- end
-
- # HTML Tree list item used by `html_tree`.
- private fun html_tree_li: ListItem do return new ListItem(html_link)
end
-
redef class MPackage
redef fun html_raw_namespace do return html_name
- redef fun html_tree_li do
- var tpl = new Template
- tpl.add html_link
- var list = new UnorderedList
- var root = self.root
- if root != null then
- list.add_li root.html_tree_li
- end
- tpl.add list
- return new ListItem(tpl)
- end
-
redef var html_modifiers = ["package"]
redef fun html_namespace do return html_link
redef var css_classes = ["public"]
end
redef var css_classes = ["public"]
-
- redef fun html_tree_li do
- var tpl = new Template
- tpl.add html_link
- var list = new UnorderedList
- for mgroup in in_nesting.direct_smallers do
- list.add_li mgroup.html_tree_li
- end
- for mmodule in mmodules do
- list.add_li mmodule.html_tree_li
- end
- tpl.add list
- return new ListItem(tpl)
- end
end
redef class MModule
end
redef var css_classes = ["public"]
-
- redef fun html_tree_li do
- var tpl = new Template
- tpl.add html_link
- var list = new UnorderedList
- for mclassdef in mclassdefs do
- list.add_li mclassdef.html_tree_li
- end
- tpl.add list
- return new ListItem(tpl)
- end
end
redef class MClass
redef class MClassDef
redef fun html_raw_namespace do return "{mmodule.html_raw_namespace}::{html_name}"
- redef fun html_tree_li do
- var tpl = new Template
- tpl.add html_link
- var list = new UnorderedList
- for mpropdef in mpropdefs do
- list.add_li mpropdef.html_tree_li
- end
- tpl.add list
- return new ListItem(tpl)
- end
-
redef fun mdoc_or_fallback do return mdoc or else mclass.mdoc_or_fallback
# Depends if `self` is an intro or not.
redef fun css_classes do
var set = new HashSet[String]
if is_intro then set.add "intro"
- for m in mclass.intro.collect_modifiers do set.add m.to_cmangle
- for m in collect_modifiers do set.add m.to_cmangle
+ for m in mclass.intro.modifiers do set.add m.to_cmangle
+ for m in modifiers do set.add m.to_cmangle
return set.to_a
end
+
+
+ # List of all modifiers like redef, private etc.
+ var modifiers: Array[String] is lazy do
+ var res = new Array[String]
+ if not is_intro then
+ res.add "redef"
+ else
+ res.add mclass.visibility.to_s
+ end
+ res.add mclass.kind.to_s
+ return res
+ end
end
redef class MProperty
redef fun css_classes do
var set = new HashSet[String]
if is_intro then set.add "intro"
- for m in mproperty.intro.collect_modifiers do set.add m.to_cmangle
- for m in collect_modifiers do set.add m.to_cmangle
+ for m in mproperty.intro.modifiers do set.add m.to_cmangle
+ for m in modifiers do set.add m.to_cmangle
return set.to_a
end
+
+ # List of all modifiers like redef, private, abstract, intern, fun etc.
+ var modifiers: Array[String] is lazy do
+ var res = new Array[String]
+ if not is_intro then
+ res.add "redef"
+ else
+ res.add mproperty.visibility.to_s
+ end
+ var mprop = self
+ if mprop isa MVirtualTypeDef then
+ res.add "type"
+ else if mprop isa MMethodDef then
+ if mprop.is_abstract then
+ res.add "abstract"
+ else if mprop.is_intern then
+ res.add "intern"
+ end
+ if mprop.mproperty.is_init then
+ res.add "init"
+ else
+ res.add "fun"
+ end
+ end
+ return res
+ end
end
redef class MAttributeDef
return tpl
end
end
+
+redef class MEntityTree
+ # Render `self` as a hierarchical UnorderedList.
+ fun html_list: UnorderedList do
+ var lst = new_unordered_list
+ for r in roots do
+ var li = new_mentity_item(r)
+ lst.add_li li
+ build_html_list(r, li)
+ end
+ return lst
+ end
+
+ # Build the html list recursively.
+ private fun build_html_list(e: MEntity, li: ListItem) do
+ if not sub.has_key(e) then return
+ var subs = sub[e]
+ var lst = new_unordered_list
+ for e2 in subs do
+ if e2 isa MGroup and e2.is_root then
+ build_html_list(e2, li)
+ else
+ var sli = new_mentity_item(e2)
+ lst.add_li sli
+ build_html_list(e2, sli)
+ end
+ end
+ var text = new Template
+ text.add li.text
+ if not lst.is_empty then text.add lst
+ li.text = text
+ end
+
+ # HTML unordered List used to compose the tree.
+ #
+ # Redefine this method to add custom CSS classes or other html attributes.
+ protected fun new_unordered_list: UnorderedList do return new UnorderedList
+
+ # Return a li element for `mconcern` that can be displayed in a concern list
+ protected fun new_mentity_item(mentity: MEntity): ListItem do
+ var tpl = new Template
+ tpl.add mentity.html_link
+ var comment = mentity.html_synopsis
+ if comment != null then
+ tpl.add ": "
+ tpl.add comment
+ end
+ return new ListItem(tpl)
+ end
+end
module web_actions
import web_views
-import model::model_collect
# Display the tree of all loaded mentities.
class TreeAction
- super NitAction
+ super ModelAction
- # Model to explore and render.
- var model: Model
-
- # View to render.
- var view = new HtmlHomePage(model) is lazy
-
- redef fun answer(request, url) do return render_view(view)
+ redef fun answer(request, url) do
+ var model = init_model_view(request)
+ var view = new HtmlHomePage(model.to_tree)
+ return render_view(view)
+ end
end
# Display the list of mentities matching `namespace`.
class SearchAction
- super NitAction
-
- # Model to explore and render.
- var model: Model
+ super ModelAction
# TODO handle more than full namespaces.
redef fun answer(request, url) do
if namespace == null or namespace.is_empty then
return render_error(400, "Missing :namespace.")
end
- var mentities = model.collect_by_namespace(namespace)
+ var model = init_model_view(request)
+ var mentities = model.mentities_by_namespace(namespace)
if request.is_json_asked then
var json = new JsonArray
for mentity in mentities do
# Display a MEntity source code.
class CodeAction
- super NitAction
-
- # Model to explore and render.
- var model: Model
+ super ModelAction
# Modelbuilder used to access sources.
var modelbuilder: ModelBuilder
if namespace == null or namespace.is_empty then
return render_error(400, "Missing :namespace.")
end
- var mentities = model.collect_by_namespace(namespace)
+ var model = init_model_view(request)
+ var mentities = model.mentities_by_namespace(namespace)
if mentities.is_empty then
return render_error(404, "No mentity matching this namespace.")
end
# Display the doc of a MEntity.
class DocAction
- super NitAction
-
- # Model to explore and render.
- var model: Model
+ super ModelAction
# Modelbuilder used to access sources.
var modelbuilder: ModelBuilder
if namespace == null or namespace.is_empty then
return render_error(400, "Missing :namespace.")
end
- var mentities = model.collect_by_namespace(namespace)
+ var model = init_model_view(request)
+ var mentities = model.mentities_by_namespace(namespace)
if mentities.is_empty then
return render_error(404, "No mentity matching this namespace.")
end
# Return a random list of MEntities.
class RandomAction
- super NitAction
-
- # Model to explore and render.
- var model: Model
+ super ModelAction
# TODO handle more than full namespaces.
redef fun answer(request, url) do
var n = request.int_arg("n") or else 10
var k = request.string_arg("k") or else "modules"
+ var model = init_model_view(request)
var mentities: Array[MEntity]
if k == "modules" then
mentities = model.mmodules.to_a
else if k == "classdefs" then
- mentities = new Array[MClassDef]
- for mclass in model.mclasses do
- mentities.add_all(mclass.mclassdefs)
- end
+ mentities = model.mclassdefs.to_a
else
- mentities = new Array[MPropDef]
- for mprop in model.mproperties do
- mentities.add_all(mprop.mpropdefs)
- end
+ mentities = model.mpropdefs.to_a
end
mentities.shuffle
mentities = mentities.sub(0, n)
# Base classes used by `nitweb`.
module web_base
-import frontend
+import model::model_views
import nitcorn
import json
end
end
+# Specific nitcorn Action that uses a Model
+class ModelAction
+ super NitAction
+
+ # Model to use.
+ var model: Model
+
+ # Init the model view from the `req` uri parameters.
+ fun init_model_view(req: HttpRequest): ModelView do
+ var view = new ModelView(model)
+
+ var show_private = req.bool_arg("private") or else false
+ if not show_private then view.min_visibility = protected_visibility
+
+ view.include_fictive = req.bool_arg("fictive") or else false
+ view.include_empty_doc = req.bool_arg("empty-doc") or else true
+ view.include_test_suite = req.bool_arg("test-suite") or else false
+ view.include_attribute = req.bool_arg("attributes") or else true
+
+ return view
+ end
+end
+
# A NitView is rendered by an action.
interface NitView
# Renders this view and returns something that can be written to a HTTP response.
super NitView
# Loaded model to display.
- var model: Model
+ var tree: MEntityTree
redef fun render(srv) do
var tpl = new Template
tpl.add new Header(1, "Loaded model")
- for mpackage in model.mpackages do
- tpl.add new Header(3, "Packages")
- tpl.add mpackage.html_tree
- end
+ tpl.add tree.html_list
return tpl
end
end
js/
less/
module_base_attr_nullable-.html
-property_base_attr_nullable-__Bar___a3.html
property_base_attr_nullable-__Bar__a3.html
property_base_attr_nullable-__Bar__a3_61d.html
-property_base_attr_nullable-__Foo___a1.html
-property_base_attr_nullable-__Foo___a2.html
property_base_attr_nullable-__Foo__a1.html
property_base_attr_nullable-__Foo__a1_61d.html
property_base_attr_nullable-__Foo__a2.html
property_base_attr_nullable-__Foo__run_other.html
property_base_attr_nullable-__Int___43d.html
property_base_attr_nullable-__Int__output.html
-property_base_attr_nullable-__Integer___val.html
property_base_attr_nullable-__Integer__init.html
property_base_attr_nullable-__Integer__output.html
property_base_attr_nullable-__Integer__val.html
Object -> Task [dir=back arrowtail=open style=dashed];
A [
- label = "{A||+ pubA(a: A)\l+ pubA2(): A\l+ vpubA(): nullable A\l+ vpubA=(vpubA: nullable A)\l+ vpubA2(): A\l+ vpubA2=(vpubA2: A)\l}"
+ label = "{A||+ pubA(a: A)\l# proA(a: A)\l+ pubA2(): A\l# proA2(): A\l+ vpubA(): nullable A\l+ vpubA=(vpubA: nullable A)\l# vproA(): nullable A\l# vproA=(vproA: nullable A)\l+ vpubA2(): A\l+ vpubA2=(vpubA2: A)\l# vproA2(): A\l# vproA2=(vproA2: A)\l}"
]
Object -> A [dir=back arrowtail=open style=dashed];