--- /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.
+
+# Vector Space Model
+#
+# Vector Space Model (VSM) is an algebraic model for representing text documents
+# (and any objects, in general) as vectors of identifiers, such as, for example,
+# index terms.
+#
+# It is used in information filtering, information retrieval, indexing and
+# relevancy rankings.
+module vsm
+
+import counter
+
+# A n-dimensions vector
+#
+# *n-dimensions* vectors are used to represent a text document or an object.
+class Vector
+ super HashMap[nullable Object, Float]
+
+ # Cosine similarity of `self` and `other`.
+ #
+ # Gives the proximity in the range `[0.0 .. 1.0]` where 0.0 means that the
+ # two vectors are orthogonal and 1.0 means that they are identical.
+ #
+ # ~~~
+ # var v1 = new Vector
+ # v1["x"] = 1.0
+ # v1["y"] = 2.0
+ # v1["z"] = 3.0
+ #
+ # var v2 = new Vector
+ # v2["x"] = 1.0
+ # v2["y"] = 2.0
+ # v2["z"] = 3.0
+ #
+ # var v3 = new Vector
+ # v3["a"] = 1.0
+ # v3["b"] = 2.0
+ # v3["c"] = 3.0
+ #
+ # print v1.cosine_similarity(v2)
+ # assert v1.cosine_similarity(v2) == 1.0
+ # print v1.cosine_similarity(v3)
+ # assert v1.cosine_similarity(v3) == 0.0
+ # ~~~
+ fun cosine_similarity(other: SELF): Float do
+ # Collect terms
+ var terms = new HashSet[nullable Object]
+ for k in self.keys do terms.add k
+ for k in other.keys do terms.add k
+
+ # Get dot product of two vectors
+ var dot = 0.0
+ for term in terms do
+ dot += self.get_or_default(term, 0.0) * other.get_or_default(term, 0.0)
+ end
+ var cos = dot.to_f / (self.norm * other.norm)
+ if cos.is_nan then return 0.0
+ return cos
+ end
+
+ # The norm of the vector.
+ #
+ # `||x|| = (x1 ** 2 ... + xn ** 2).sqrt`
+ #
+ # ~~~
+ # var v = new Vector
+ # v["x"] = 1.0
+ # v["y"] = 1.0
+ # v["z"] = 1.0
+ # v["t"] = 1.0
+ # assert v.norm.is_approx(2.0, 0.001)
+ #
+ # v["x"] = 1.0
+ # v["y"] = 2.0
+ # v["z"] = 3.0
+ # v["t"] = 0.0
+ # assert v.norm.is_approx(3.742, 0.001)
+ # ~~~
+ fun norm: Float do
+ var sum = 0.0
+ for v in self.values do sum += v.pow(2.0)
+ return sum.to_f.sqrt
+ end
+
+ redef fun to_s do
+ return "[{join(", ", ":")}]"
+ end
+end
+
+# A Document index based on VSM
+#
+# Using VSMIndex you can index documents associated with their vector.
+# Documents can then be matched to query vectors.
+class VSMIndex
+
+ # Documents index
+ #
+ # TODO use a more efficient representation.
+ var documents = new HashSet[Document]
+
+ # Count for all terms in all indexed documents
+ #
+ # Used to compute the `inverse_doc_frequency`.
+ var terms_doc_count = new Vector
+
+ # Inverse document frequency
+ #
+ # The inverse document frequency is a measure of how much information a term
+ # provides, that is, whether the term is common or rare across all documents.
+ var inverse_doc_frequency = new Vector
+
+ # Used to sort matches
+ #
+ # See `IndexMatch`.
+ var sorter = new IndexMatchSorter
+
+ # Match `query` vector to all index document vectors
+ #
+ # Returns an `IndexMatch` for each indexed document.
+ # Results are ordered by descending similarity.
+ fun match_vector(query: Vector): Array[IndexMatch] do
+ var matches = new Array[IndexMatch]
+ for doc in documents do
+ var sim = query.cosine_similarity(doc.tfidf)
+ if sim == 0.0 then continue
+ matches.add new IndexMatch(doc, sim)
+ end
+ sorter.sort(matches)
+ return matches
+ end
+
+ # Index a document
+ #
+ # With each new document, the `inverse_doc_frequency` must be updated.
+ # By default, the method `update_index` is called after each call to
+ # `index_document`.
+ #
+ # When processing batch documents, use `auto_update = false` to disable
+ # the auto update of the index.
+ fun index_document(doc: Document, auto_update: nullable Bool) do
+ for term, count in doc.terms_count do
+ if not terms_doc_count.has_key(term) then
+ terms_doc_count[term] = 1.0
+ else
+ terms_doc_count[term] += 1.0
+ end
+ end
+ documents.add doc
+ if auto_update == null or auto_update then update_index
+ end
+
+ # Update the index
+ #
+ # Recompute the `inverse_doc_frequency` values.
+ # Must be called manually after indexing new document with the option
+ # `auto_update = false`.
+ fun update_index do
+ for doc in documents do
+ for term, ccount in doc.terms_count do
+ inverse_doc_frequency[term] = (documents.length.to_f / terms_doc_count[term]).log
+ end
+ end
+ for doc in documents do
+ for term, freq in doc.terms_frequency do
+ doc.tfidf[term] = freq * inverse_doc_frequency[term]
+ end
+ end
+ end
+end
+
+# A VSM index to store strings
+class StringIndex
+ super VSMIndex
+
+ # Index a new Document from `title`, `uri` and string `string`.
+ #
+ # Return the Document created.
+ #
+ # See `index_document`.
+ fun index_string(title, uri, string: String, auto_update: nullable Bool): Document do
+ var vector = parse_string(string)
+ var doc = new Document(title, uri, vector)
+ index_document(doc, auto_update)
+ return doc
+ end
+
+ # Match the `query` string against all indexed documents
+ #
+ # See `match_vector`.
+ fun match_string(query: String): Array[IndexMatch] do
+ var vector = parse_string(query)
+ return match_vector(vector)
+ end
+
+ # Parse the `string` as a Vector
+ #
+ # Returns a vector containing the terms of `string`.
+ fun parse_string(string: String): Vector do
+ var reader = new StringReader(string)
+ var vector = new Vector
+ loop
+ var token = reader.read_word
+ if token == "" then break
+
+ if not vector.has_key(token) then
+ vector[token] = 1.0
+ else
+ vector[token] += 1.0
+ end
+ end
+ return vector
+ end
+end
+
+# A VSMIndex to index files
+class FileIndex
+ super StringIndex
+
+ # Index a file from its `path`.
+ #
+ # Return the created document or null if `path` is not accepted by `accept_file`.
+ #
+ # See `index_document`.
+ fun index_file(path: String, auto_update: nullable Bool): nullable Document do
+ if not accept_file(path) then return null
+ var vector = parse_file(path)
+ var doc = new Document(path, path, vector)
+ index_document(doc, auto_update)
+ return doc
+ end
+
+ # Index multiple files
+ #
+ # The recursive method `index_dir` will be called for each directory found
+ # in `paths`.
+ #
+ # See `index_file`
+ fun index_files(paths: Collection[String], auto_update: nullable Bool) do
+ for path in paths do
+ if path.to_path.is_dir then
+ index_dir(path, false)
+ else
+ index_file(path, false)
+ end
+ end
+ if auto_update != null and auto_update then update_index
+ end
+
+ # Index all files in `dir` recursively
+ #
+ # See `index_file`.
+ fun index_dir(dir: String, auto_update: nullable Bool) do
+ if not dir.to_path.is_dir then return
+ for file in dir.files do
+ var path = dir / file
+ if path.to_path.is_dir then
+ index_dir(path, false)
+ else
+ index_file(path, false)
+ end
+ end
+ if auto_update != null and auto_update then update_index
+ end
+
+ # Is `path` accepted depending on `whitelist_exts` and `blacklist_exts`?
+ fun accept_file(path: String): Bool do
+ var ext = path.file_extension
+ if ext != null then
+ ext = ext.to_lower
+ if blacklist_exts.has(ext) then return false
+ if whitelist_exts.not_empty and not whitelist_exts.has(ext) then return false
+ end
+ return whitelist_exts.is_empty
+ end
+
+ # Parse the `file` content as a Vector
+ #
+ # See `parse_string`.
+ fun parse_file(file: String): Vector do
+ return parse_string(file.to_path.read_all)
+ end
+
+ # File extensions white list
+ #
+ # If not empty, only files with these extensions will be indexed.
+ #
+ # If an extension is in both `whitelist_exts` and `blacklist_exts`, the
+ # blacklist will prevail and the file will be ignored.
+ var whitelist_exts = new Array[String] is writable
+
+ # File extensions black list
+ #
+ # Files with these extensions will not be indexed.
+ var blacklist_exts = new Array[String] is writable
+end
+
+# A Document to add in a VSMIndex
+class Document
+
+ # Document title
+ var title: String
+
+ # Document URI
+ var uri: String
+
+ # Count of all terms found in the document
+ #
+ # Used to compute the document `terms_frequency`.
+ var terms_count: Vector
+
+ # Frequency of each term found in the document
+ #
+ # Used to match the document against the `VSMIndex::inverse_doc_frequency`.
+ var terms_frequency: Vector is lazy do
+ var all_terms = 0.0
+ for t, c in terms_count do all_terms += c
+
+ var vector = new Vector
+ for t, c in terms_count do
+ vector[t] = c / all_terms
+ end
+ return vector
+ end
+
+ # Term frequency–Inverse document frequency for each term
+ #
+ # A high weight in tf–idf is reached by a high term frequency
+ # (in the given document) and a low document frequency of the term in the
+ # whole collection of documents
+ var tfidf = new Vector
+
+ redef fun to_s do return "{title}"
+end
+
+# A match to a `request` in an `Index`
+class IndexMatch
+ super Comparable
+
+ # Document matching the `request_vector`
+ var document: Document
+
+ # Similarity between the `request` and the `doc`.
+ #
+ # Result is in the range 0.0 .. 1.1 where 0.0 means no similarity and 1.0
+ # means perfect similarity.
+ var similarity: Float
+
+ redef fun to_s do return "{document} ({similarity})"
+end
+
+# Sort matches by similarity
+class IndexMatchSorter
+ super DefaultComparator
+
+ redef type COMPARED: IndexMatch
+
+ redef fun compare(a, b) do
+ return b.similarity <=> a.similarity
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
-# Collect things from a `Model`.
+# Collect things from a `ModelView`
+#
+# This module introduce several usefull methods to list and count things from a
+# ModelView.
+#
+# First setup you view from a Model:
+#
+# ~~~nitih
+# var view = new ModelView(model)
+# ~~~
+#
+# Then ask question using the view:
+#
+# ~~~nitish
+# print number of parents for `{my_class}`
+# print my_class.collect_parents(view).count
+# ~~~
#
# **Warning**
#
# `model_collect` offers a flattened view of the model without considering any
# main module.
# For this reason, `model_collect` lists all the definitions reachable from all
-# modules
+# modules.
#
# This is usefull for tools that need a global view of a model like `nitdoc`,
-# `nitx` or `nituml`.
+# `nitx`, `nitmetrics` or `nituml`.
# It should not be used for compiling stuffs like computing VFT, where the listed
# entities could not be reachable depending on the modules really imported.
module model_collect
redef class MEntity
- # FIXME used to bypass RTA limitation on type resolution.
+ # FIXME used to bypass RTA limitation on type resolution
type MENTITY: SELF
- # Collect modifier keywords like `redef`, `private` etc.
- fun collect_modifiers: Array[String] do
- return new Array[String]
- end
+ # Collect modifier keywords like `redef`, `private` etc
+ fun collect_modifiers: Array[String] do return new Array[String]
- # Collect `self` linearization anchored on `mainmodule`.
+ # Collect `self` linearization anchored on `mainmodule`
fun collect_linearization(mainmodule: MModule): nullable Array[MEntity] do
return null
end
- # Collect `self` ancestors (direct and indirect).
+ # Collect `self` ancestors (direct and indirect)
#
# The concept of ancestor is abstract at this stage.
fun collect_ancestors(view: ModelView): Set[MENTITY] do
while todo.not_empty do
var mentity = todo.pop
if mentity == self or done.has(mentity) then continue
- print "{mentity} == {self}"
done.add mentity
todo.add_all mentity.collect_parents(view)
end
return done
end
- # Collect `self` parents (direct ancestors).
+ # Collect `self` parents (direct ancestors)
#
# The concept of parent is abstract at this stage.
fun collect_parents(view: ModelView): Set[MENTITY] is abstract
- # Collect `self` children (direct descendants).
+ # Collect `self` children (direct descendants)
#
# The concept of child is abstract at this stage.
fun collect_children(view: ModelView): Set[MENTITY] is abstract
- # Collect `self` descendants (direct and direct).
+ # Collect `self` descendants (direct and direct)
#
# The concept of descendant is abstract at this stage.
fun collect_descendants(view: ModelView): Set[MENTITY] do
return done
end
- # Build a poset representing `self` in it's own hierarchy.
+ # Build a poset representing `self` in it's own hierarchy
#
# The notion of hierarchy depends on the type of MEntity.
#
# Here a recap:
- # * MPackage: package dependencies
- # * MGroup: group dependencies
- # * MModule: modules imports
- # * MClass: class inheritance (all classdefs flattened)
- # * MClassDef: classdef inheritance
- # * MProperty: property definitions graph (all propdefs flattened)
- # * MPropDef: property definitions graph
+ # * `MPackage`: package dependencies
+ # * `MGroup`: group dependencies
+ # * `MModule`: modules imports
+ # * `MClass`: class inheritance (all classdefs flattened)
+ # * `MClassDef`: classdef inheritance
+ # * `MProperty`: property definitions graph (all propdefs flattened)
+ # * `MPropDef`: property definitions graph
fun hierarchy_poset(view: ModelView): POSet[MENTITY] do
var done = new HashSet[MENTITY]
var mentities = new Array[MENTITY]
end
end
-redef class MPackage
- redef fun collect_modifiers do
- var res = super
- res.add "package"
+redef class Model
+
+ # Collect all MPackages in `self`
+ fun collect_mpackages(view: ModelView): HashSet[MPackage] do
+ var res = new HashSet[MPackage]
+ for mpackage in mpackages do
+ if not view.accept_mentity(mpackage) then continue
+ res.add(mpackage)
+ end
+ return res
+ end
+
+ # Collect all MModules in `self`
+ fun collect_mmodules(view: ModelView): HashSet[MModule] do
+ var res = new HashSet[MModule]
+ for mpackage in collect_mpackages(view) do
+ res.add_all mpackage.collect_all_mmodules(view)
+ end
+ return res
+ end
+
+ # Collect all MClasses introduced in `self`
+ fun collect_intro_mclasses(view: ModelView): HashSet[MClass] do
+ var res = new HashSet[MClass]
+ for mpackage in collect_mpackages(view) do
+ res.add_all mpackage.collect_intro_mclasses(view)
+ end
+ return res
+ end
+
+ # Collect all MProperties introduced in `self`
+ fun collect_intro_mproperties(view: ModelView): HashSet[MProperty] do
+ var res = new HashSet[MProperty]
+ for mpackage in collect_mpackages(view) do
+ res.add_all mpackage.collect_intro_mproperties(view)
+ end
return res
end
+end
+
+redef class MPackage
+
+ redef fun collect_modifiers do return super + ["package"]
- # `MPackage` parents are its direct dependencies.
+ # Collect all packages directly imported by `self`
redef fun collect_parents(view) do
var res = new HashSet[MENTITY]
for mgroup in mgroups do
return res
end
- # `MPackage` children are packages that directly depends on `self`.
+ # Collect all packages that directly depends on `self`
redef fun collect_children(view) do
var res = new HashSet[MENTITY]
for mpackage in view.mpackages do
return res
end
- # `MModules` contained in `self`.
+ # Collect all groups contained in `self`
+ fun collect_all_mgroups(view: ModelView): HashSet[MGroup] do
+ var res = new HashSet[MGroup]
+ for mgroup in mgroups do
+ if not view.accept_mentity(mgroup) then continue
+ res.add(mgroup)
+ end
+ return res
+ end
+
+ # Collect only groups contained in `self.root`
+ fun collect_mgroups(view: ModelView): HashSet[MGroup] do
+ var res = new HashSet[MGroup]
+ var root = self.root
+ if root == null then return res
+ res.add_all root.collect_mgroups(view)
+ return res
+ end
+
+ # Collect all modules contained in `self`
+ fun collect_all_mmodules(view: ModelView): HashSet[MModule] do
+ var res = new HashSet[MModule]
+ for mgroup in collect_mgroups(view) do
+ res.add_all mgroup.collect_mmodules(view)
+ end
+ return res
+ end
+
+ # Collect only modules contained in `self.root`
fun collect_mmodules(view: ModelView): HashSet[MModule] do
var res = new HashSet[MModule]
+ var root = self.root
+ if root == null then return res
+ res.add_all root.collect_mmodules(view)
+ return res
+ end
+
+ # Collect all classes introduced in `self`
+ fun collect_intro_mclasses(view: ModelView): HashSet[MClass] do
+ var res = new HashSet[MClass]
for mgroup in mgroups do
- for mmodule in mgroup.mmodules do
- if not view.accept_mentity(mmodule) then continue
- res.add(mmodule)
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_intro_mclasses(view)
end
end
return res
end
-end
-redef class MGroup
- redef fun collect_modifiers do
- var res = super
- res.add "group"
+ # Collect all classes redefined or refined in `self`
+ fun collect_redef_mclasses(view: ModelView): Set[MClass] do
+ var res = new HashSet[MClass]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_redef_mclasses(view)
+ end
+ end
return res
end
- # `MGroup` parents are its direct dependencies.
+ # Collect all properties introduced in `self`
+ fun collect_intro_mproperties(view: ModelView): HashSet[MProperty] do
+ var res = new HashSet[MProperty]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_intro_mproperties(view)
+ end
+ end
+ return res
+ end
+
+ # Collect all properties redefined in `self`
+ fun collect_redef_mproperties(view: ModelView): HashSet[MProperty] do
+ var res = new HashSet[MProperty]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_redef_mproperties(view)
+ end
+ end
+ return res
+ end
+
+ # Collect all attributes introduced in `self`
+ fun collect_intro_attributes(view: ModelView): Set[MAttribute] do
+ var res = new HashSet[MAttribute]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_intro_attributes(view)
+ end
+ end
+ return res
+ end
+
+ # Collect all inits introduced in `self`
+ fun collect_intro_inits(view: ModelView): Set[MMethod] do
+ var res = new HashSet[MMethod]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_intro_inits(view)
+ end
+ end
+ return res
+ end
+
+ # Collect all methods introduced in `self` excluding inits
+ #
+ # See `collect_intro_inits`.
+ fun collect_intro_methods(view: ModelView): Set[MMethod] do
+ var res = new HashSet[MMethod]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_intro_methods(view)
+ end
+ end
+ return res
+ end
+
+ # Collect all virtual types introduced in `self`
+ fun collect_intro_vts(view: ModelView): Set[MVirtualTypeProp] do
+ var res = new HashSet[MVirtualTypeProp]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_intro_vts(view)
+ end
+ end
+ return res
+ end
+end
+
+redef class MGroup
+
+ redef fun collect_modifiers do return super + ["group"]
+
+ # Collect all groups directly import by `self`
redef fun collect_parents(view) do
var res = new HashSet[MENTITY]
for mmodule in mmodules do
return res
end
- # `MGroup` children are mgroups that directly depends on `self`.
+ # Collect all group that directly import `self`
redef fun collect_children(view) do
var res = new HashSet[MENTITY]
for mgroup in view.mgroups do
end
return res
end
-end
-redef class MModule
+ # Collect all groups contained in `self`
+ fun collect_mgroups(view: ModelView): HashSet[MENTITY] do
+ var res = new HashSet[MENTITY]
+ for mgroup in in_nesting.direct_smallers do
+ if not view.accept_mentity(mgroup) then continue
+ res.add(mgroup)
+ end
+ return res
+ end
- redef fun collect_modifiers do
- var res = super
- res.add "module"
+ # Collect all modules contained in `self`
+ fun collect_mmodules(view: ModelView): HashSet[MModule] do
+ var res = new HashSet[MModule]
+ for mmodule in mmodules do
+ if not view.accept_mentity(mmodule) then continue
+ res.add(mmodule)
+ end
return res
end
+end
+
+redef class MModule
- # `MModule` ancestors are all its transitive imports.
+ redef fun collect_modifiers do return super + ["module"]
+
+ # Collect all module ancestors of `self` (direct and transitive imports)
redef fun collect_ancestors(view) do
var res = new HashSet[MENTITY]
for mentity in in_importation.greaters do
return res
end
- # `MModule` parents are all its direct imports.
+ # Collect all modules directly imported by `self`
redef fun collect_parents(view) do
var res = new HashSet[MENTITY]
for mentity in in_importation.direct_greaters do
return res
end
- # `MModule` children are modules that directly import `self`.
+ # Collect all modules that directly import `self`
redef fun collect_children(view) do
var res = new HashSet[MENTITY]
for mentity in in_importation.direct_smallers do
return res
end
- # `MModule` children are modules that transitively import `self`.
+ # Collect all module descendants of `self` (direct and transitive imports)
redef fun collect_descendants(view) do
var res = new HashSet[MENTITY]
for mentity in in_importation.smallers do
return res
end
- # Collect mclassdefs introduced in `self` with `visibility >= to min_visibility`.
+ # Collect all class definitions introduced in `self`
fun collect_intro_mclassdefs(view: ModelView): Set[MClassDef] do
var res = new HashSet[MClassDef]
for mclassdef in mclassdefs do
return res
end
- # Collect mclassdefs redefined in `self` with `visibility >= to min_visibility`.
+ # Collect all class definitions refined in `self`
fun collect_redef_mclassdefs(view: ModelView): Set[MClassDef] do
var res = new HashSet[MClassDef]
for mclassdef in mclassdefs do
return res
end
- # Collect mclasses introduced in `self` with `visibility >= to min_visibility`.
+ # Collect all class definitions introduced and refined in `self`
+ fun collect_local_mclassdefs(view: ModelView): Set[MClassDef] do
+ var res = new HashSet[MClassDef]
+ res.add_all collect_intro_mclassdefs(view)
+ res.add_all collect_redef_mclassdefs(view)
+ return res
+ end
+
+ # Collect all classes introduced in `self`
fun collect_intro_mclasses(view: ModelView): Set[MClass] do
var res = new HashSet[MClass]
for mclass in intro_mclasses do
return res
end
- # Collect mclasses redefined in `self` with `visibility >= to min_visibility`.
+ # Collect all classes refined in `self`
fun collect_redef_mclasses(view: ModelView): Set[MClass] do
var mclasses = new HashSet[MClass]
for mclassdef in mclassdefs do
- if not view.accept_mentity(mclassdef) then continue
+ if not view.accept_mentity(mclassdef.mclass) then continue
if not mclassdef.is_intro then mclasses.add(mclassdef.mclass)
end
return mclasses
end
+
+ # Collect all classes introduced and refined in `self`
+ fun collect_local_mclasses(view: ModelView): Set[MClass] do
+ var res = new HashSet[MClass]
+ res.add_all collect_intro_mclasses(view)
+ res.add_all collect_redef_mclasses(view)
+ return res
+ end
+
+ # Collect all classes imported from `self` parents
+ fun collect_imported_mclasses(view: ModelView): Set[MClass] do
+ var res = new HashSet[MClass]
+ for parent in collect_parents(view) do
+ res.add_all parent.collect_intro_mclasses(view)
+ res.add_all parent.collect_redef_mclasses(view)
+ res.add_all parent.collect_imported_mclasses(view)
+ end
+ return res
+ end
+
+ # Collect all properties introduced in `self`
+ fun collect_intro_mproperties(view: ModelView): Set[MProperty] do
+ var res = new HashSet[MProperty]
+ for mclass in collect_intro_mclasses(view) do
+ res.add_all mclass.collect_intro_mproperties(view)
+ end
+ return res
+ end
+
+ # Collect properties redefined in `self`
+ fun collect_redef_mproperties(view: ModelView): Set[MProperty] do
+ var res = new HashSet[MProperty]
+ for mclassdef in mclassdefs do
+ for mpropdef in mclassdef.collect_redef_mpropdefs(view) do
+ res.add mpropdef.mproperty
+ end
+ end
+ return res
+ end
+
+ # Collect attributes introduced in `self`
+ fun collect_intro_attributes(view: ModelView): Set[MAttribute] do
+ var res = new HashSet[MAttribute]
+ for mproperty in collect_intro_mproperties(view) do
+ if mproperty isa MAttribute then res.add(mproperty)
+ end
+ return res
+ end
+
+ # Collect all inits introduced in `self`
+ fun collect_intro_inits(view: ModelView): Set[MMethod] do
+ var res = new HashSet[MMethod]
+ for mproperty in collect_intro_mproperties(view) do
+ if mproperty isa MMethod and mproperty.is_init then res.add(mproperty)
+ end
+ return res
+ end
+
+ # Collect methods introduced in `self` (without inits)
+ fun collect_intro_methods(view: ModelView): Set[MMethod] do
+ var res = new HashSet[MMethod]
+ for mproperty in collect_intro_mproperties(view) do
+ if mproperty isa MMethod and not mproperty.is_init then res.add(mproperty)
+ end
+ return res
+ end
+
+ # Collect virtual types introduced in `self`
+ fun collect_intro_vts(view: ModelView): Set[MVirtualTypeProp] do
+ var res = new HashSet[MVirtualTypeProp]
+ for mproperty in collect_intro_mproperties(view) do
+ if mproperty isa MVirtualTypeProp then res.add(mproperty)
+ end
+ return res
+ end
end
redef class MClass
return mclassdefs
end
- # `MClass` parents are the direct parents of `self`.
+ # Collect all direct parents of `self`
#
# This method uses a flattened hierarchy containing all the mclassdefs.
redef fun collect_parents(view) do
return res
end
- # Collect all ancestors of `self` with `visibility >= to min_visibility`.
+ # Collect all ancestors of `self`
redef fun collect_ancestors(view) do
var res = new HashSet[MENTITY]
for mclassdef in mclassdefs do
return res
end
- # `MClass` parents are the direct parents of `self`.
+ # Collect all direct children of `self`
#
# This method uses a flattened hierarchy containing all the mclassdefs.
redef fun collect_children(view) do
return res
end
- # Collect all mproperties introduced in 'self' with `visibility >= min_visibility`.
+ # Collect all class definitions of `self`
+ fun collect_mclassdefs(view: ModelView): Set[MClassDef] do
+ var res = new HashSet[MClassDef]
+ for mclassdef in mclassdefs do
+ if not view.accept_mentity(mclassdef) then continue
+ res.add mclassdef
+ end
+ return res
+ end
+
+ # Collect all property definitions that are introductions in `self`
+ fun collect_intro_mpropdefs(view: ModelView): Set[MPropDef] do
+ var set = new HashSet[MPropDef]
+ for mclassdef in mclassdefs do
+ for mpropdef in mclassdef.mpropdefs do
+ if not mpropdef.is_intro then continue
+ if not view.accept_mentity(mpropdef) then continue
+ set.add(mpropdef)
+ end
+ end
+ return set
+ end
+
+ # Collect all properties introduced in `self`
fun collect_intro_mproperties(view: ModelView): Set[MProperty] do
var set = new HashSet[MProperty]
for mclassdef in mclassdefs do
return set
end
- # Collect all mproperties redefined in 'self' with `visibility >= min_visibility`.
+ # Collect all propierty definitions that are redefinition in `self`
+ fun collect_redef_mpropdefs(view: ModelView): Set[MPropDef] do
+ var set = new HashSet[MPropDef]
+ for mclassdef in mclassdefs do
+ for mpropdef in mclassdef.mpropdefs do
+ if mpropdef.is_intro then continue
+ if not view.accept_mentity(mpropdef) then continue
+ set.add(mpropdef)
+ end
+ end
+ return set
+ end
+
+ # Collect all properties redefined in `self`
fun collect_redef_mproperties(view: ModelView): Set[MProperty] do
var set = new HashSet[MProperty]
for mclassdef in mclassdefs do
return set
end
- # Collect mproperties introduced and redefined in 'self' with `visibility >= min_visibility`.
+ # Collect all properties introduced and redefined in `self`
fun collect_local_mproperties(view: ModelView): Set[MProperty] do
var set = new HashSet[MProperty]
set.add_all collect_intro_mproperties(view)
return set
end
- # Collect all mproperties inehrited by 'self' with `visibility >= min_visibility`.
+ # Collect all properties inehrited by `self`
fun collect_inherited_mproperties(view: ModelView): Set[MProperty] do
var set = new HashSet[MProperty]
for parent in collect_parents(view) do
return set
end
- # Collect all mproperties accessible by 'self' with `visibility >= min_visibility`.
+ # Collect all properties accessible by `self`
#
- # This include introduced, redefined, inherited mproperties.
+ # This include introduced, redefined, inherited properties.
fun collect_accessible_mproperties(view: ModelView): Set[MProperty] do
var set = new HashSet[MProperty]
set.add_all(collect_intro_mproperties(view))
return set
end
- # Collect mmethods introduced in 'self' with `visibility >= min_visibility`.
+ # Collect all methods introduced in `self`
fun collect_intro_mmethods(view: ModelView): Set[MMethod] do
var res = new HashSet[MMethod]
for mproperty in collect_intro_mproperties(view) do
return res
end
- # Collect mmethods redefined in 'self' with `visibility >= min_visibility`.
+ # Collect all methods redefined in `self`
fun collect_redef_mmethods(view: ModelView): Set[MMethod] do
var res = new HashSet[MMethod]
for mproperty in collect_redef_mproperties(view) do
return res
end
- # Collect mmethods introduced and redefined in 'self' with `visibility >= min_visibility`.
+ # Collect all methods introduced and redefined in `self`
fun collect_local_mmethods(view: ModelView): Set[MMethod] do
var set = new HashSet[MMethod]
set.add_all collect_intro_mmethods(view)
return set
end
- # Collect mmethods inherited by 'self' if accepted by `view`.
+ # Collect all methods inherited by `self`
fun collect_inherited_mmethods(view: ModelView): Set[MMethod] do
var res = new HashSet[MMethod]
for mproperty in collect_inherited_mproperties(view) do
return res
end
- # Collect all mmethods accessible by 'self' with `visibility >= min_visibility`.
+ # Collect all methods accessible by `self`
#
- # This include introduced, redefined, inherited mmethods.
+ # This include introduced, redefined, inherited methods.
fun collect_accessible_mmethods(view: ModelView): Set[MMethod] do
var set = new HashSet[MMethod]
set.add_all(collect_intro_mmethods(view))
return set
end
- # Collect mattributes introduced in 'self' with `visibility >= min_visibility`.
+ # Collect all attributes introduced in `self`
fun collect_intro_mattributes(view: ModelView): Set[MAttribute] do
var res = new HashSet[MAttribute]
for mproperty in collect_intro_mproperties(view) do
return res
end
- # Collect mattributes redefined in 'self' with `visibility >= min_visibility`.
+ # Collect all attributes redefined in `self`
fun collect_redef_mattributes(view: ModelView): Set[MAttribute] do
var res = new HashSet[MAttribute]
for mproperty in collect_redef_mproperties(view) do
return res
end
- # Collect mattributes introduced and redefined in 'self' with `visibility >= min_visibility`.
+ # Collect all attributes introduced and redefined in `self`
fun collect_local_mattributes(view: ModelView): Set[MAttribute] do
var set = new HashSet[MAttribute]
set.add_all collect_intro_mattributes(view)
return set
end
- # Collect mattributes inherited by 'self' with `visibility >= min_visibility`.
+ # Collect all attributes inherited by `self`
fun collect_inherited_mattributes(view: ModelView): Set[MAttribute] do
var res = new HashSet[MAttribute]
for mproperty in collect_inherited_mproperties(view) do
return res
end
- # Collect all mattributes accessible by 'self' with `visibility >= min_visibility`.
+ # Collect all attributes accessible by `self`
#
# This include introduced, redefined, inherited mattributes.
fun collect_accessible_mattributes(view: ModelView): Set[MAttribute] do
return set
end
- # Collect init mmethods introduced in 'self' if accepted by `view`.
+ # Collect all init methods introduced in `self`
fun collect_intro_inits(view: ModelView): Set[MMethod] do
var res = new HashSet[MMethod]
for mproperty in collect_intro_mmethods(view) do
return res
end
- # Collect init mmethods redefined in 'self' if accepted by `view`.
+ # Collect all init methods redefined in `self`
fun collect_redef_inits(view: ModelView): Set[MMethod] do
var res = new HashSet[MMethod]
for mproperty in collect_redef_mmethods(view) do
return res
end
- # Collect init mmethods introduced and redefined in 'self' if accepted by `view`.
+ # Collect all init methods introduced and redefined in `self`
fun collect_local_inits(view: ModelView): Set[MMethod] do
var set = new HashSet[MMethod]
set.add_all collect_intro_inits(view)
return set
end
- # Collect init mmethods inherited by 'self' if accepted by `view`.
+ # Collect all init methods inherited by `self`
fun collect_inherited_inits(view: ModelView): Set[MMethod] do
var res = new HashSet[MMethod]
for mproperty in collect_inherited_mmethods(view) do
return res
end
- # Collect all init mmethods accessible by 'self' if accepted by `view`.
+ # Collect all init methods accessible by `self`
#
# This include introduced, redefined, inherited inits.
fun collect_accessible_inits(view: ModelView): Set[MMethod] do
return set
end
- # Collect all virtual types accessible by 'self' if accepted by `view`.
+ # Collect all virtual types introduced in `self`
+ fun collect_intro_vts(view: ModelView): Set[MVirtualTypeProp] do
+ var res = new HashSet[MVirtualTypeProp]
+ for mproperty in collect_intro_mproperties(view) do
+ if mproperty isa MVirtualTypeProp then res.add(mproperty)
+ end
+ return res
+ end
+
+ # Collect all virtual types redefined in `self`
+ fun collect_redef_vts(view: ModelView): Set[MVirtualTypeProp] do
+ var res = new HashSet[MVirtualTypeProp]
+ for mproperty in collect_intro_mproperties(view) do
+ if mproperty isa MVirtualTypeProp then res.add(mproperty)
+ end
+ return res
+ end
+
+ # Collect all virtual types introduced or redefined in `self`
+ fun collect_local_vts(view: ModelView): Set[MVirtualTypeProp] do
+ var set = new HashSet[MVirtualTypeProp]
+ set.add_all collect_intro_vts(view)
+ set.add_all collect_redef_vts(view)
+ return set
+ end
+
+ # Collect all virtual types inherited by `self`
+ fun collect_inherited_vts(view: ModelView): Set[MVirtualTypeProp] do
+ var res = new HashSet[MVirtualTypeProp]
+ for mproperty in collect_inherited_mproperties(view) do
+ if mproperty isa MVirtualTypeProp then res.add(mproperty)
+ end
+ return res
+ end
+
+ # Collect all virtual types accessible by `self`
#
# This include introduced, redefined, inherited virtual types.
fun collect_accessible_vts(view: ModelView): Set[MVirtualTypeProp] do
redef class MClassDef
+ redef fun collect_modifiers do
+ var res = super
+ 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
+
redef fun collect_linearization(mainmodule) do
var mclassdefs = new Array[MClassDef]
for mclassdef in in_hierarchy.as(not null).greaters do
return mclassdefs
end
- # `MClassDef` ancestors are its direct and transitive super classes.
redef fun collect_ancestors(view) do
var res = new HashSet[MENTITY]
var hierarchy = self.in_hierarchy
return res
end
- # `MClassDef` parents are its direct super classes.
redef fun collect_parents(view) do
var res = new HashSet[MENTITY]
var hierarchy = self.in_hierarchy
return res
end
- # `MClassDef` children are its direct subclasses.
redef fun collect_children(view) do
var res = new HashSet[MENTITY]
var hierarchy = self.in_hierarchy
return res
end
- # Collect mpropdefs in 'self' with `visibility >= min_visibility`.
+ # Collect all property definitions in `self`
fun collect_mpropdefs(view: ModelView): Set[MPropDef] do
var res = new HashSet[MPropDef]
for mpropdef in mpropdefs do
return res
end
- # Collect mpropdefs introduced in 'self' with `visibility >= min_visibility`.
+ # Collect all attribute definitions in `self`
+ fun collect_mattributedefs(view: ModelView): Set[MAttributeDef] do
+ var res = new HashSet[MAttributeDef]
+ for mpropdef in collect_mpropdefs(view) do
+ if not mpropdef isa MAttributeDef then continue
+ res.add mpropdef
+ end
+ return res
+ end
+
+ # Collect all methods definitions in `self`
+ fun collect_mmethoddefs(view: ModelView): Set[MMethodDef] do
+ var res = new HashSet[MMethodDef]
+ for mpropdef in collect_mpropdefs(view) do
+ if not mpropdef isa MMethodDef then continue
+ res.add mpropdef
+ end
+ return res
+ end
+
+ # Collect all virtual types definitions in `self`
+ fun collect_mtypedefs(view: ModelView): Set[MVirtualTypeDef] do
+ var res = new HashSet[MVirtualTypeDef]
+ for mpropdef in collect_mpropdefs(view) do
+ if not mpropdef isa MVirtualTypeDef then continue
+ res.add mpropdef
+ end
+ return res
+ end
+
+ # Collect all property definitions that are introduction in `self`
fun collect_intro_mpropdefs(view: ModelView): Set[MPropDef] do
var res = new HashSet[MPropDef]
for mpropdef in mpropdefs do
return res
end
- # Collect mpropdefs redefined in 'self' with `visibility >= min_visibility`.
+ # Collect all property definitions that are redefinition in `self`
fun collect_redef_mpropdefs(view: ModelView): Set[MPropDef] do
var res = new HashSet[MPropDef]
for mpropdef in mpropdefs do
end
return res
end
-
- redef fun collect_modifiers do
- var res = super
- 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
return mpropdefs
end
- # Collect mpropdefs in 'self' with `visibility >= min_visibility`.
+ # Collect all property definitions of `self`
fun collect_mpropdefs(view: ModelView): Set[MPropDef] do
var res = new HashSet[MPropDef]
for mpropdef in mpropdefs do
return res
end
- # `MProperty` parents are all direct super definition of `self`.
- #
- # This method uses a flattened hierarchy containing all the mpropdefs.
+ # Collect all direct super definitions of `self`
redef fun collect_parents(view) do
var res = new HashSet[MENTITY]
for mpropdef in mpropdefs do
return res
end
- # `MProperty` parents are all direct sub definition of `self`.
- #
- # This method uses a flattened hierarchy containing all the mpropdefs.
+ # Collection all definitions that have `self` as a direct super definition
redef fun collect_children(view) do
var res = new HashSet[MENTITY]
for mpropdef in mpropdefs do
end
redef class MPropDef
+
redef fun collect_modifiers do
var res = super
if not is_intro then
return mpropdefs
end
- # `MPropDef` parents include only the next definition of `self`.
+ # Collect only the next definition of `self`
redef fun collect_parents(view) do
var res = new HashSet[MENTITY]
var mpropdef = self
return res
end
- # `MPropdef` children are definitions that directly depends on `self`.
+ # Collect all children definitions that directly depend on `self`
redef fun collect_children(view) do
var res = new HashSet[MENTITY]
for mpropdef in mproperty.collect_mpropdefs(view) do