model_index: use filter
[nit.git] / src / model / model_index.nit
index f8cfb24..805d019 100644 (file)
@@ -29,8 +29,7 @@
 #
 # ~~~nitish
 # var index = new ModelIndex
-# var view = new ModelView(model, mainmodule)
-# for mentity in view.mentities do
+# for mentity in model.collect_mentities do
 #      index.index(mentity)
 # end
 # ~~~
@@ -55,8 +54,7 @@
 #
 # ~~~nitish
 # var index = new ModelIndex
-# var view = new ModelView(model, mainmodule)
-# for mentity in view.mentities do
+# for mentity in model.collect_mentities do
 #      # We don't really care about definitions
 #      if mentity isa MClassDef or mentity isa MPropDef then continue
 #      index.index(mentity)
 # ~~~
 module model_index
 
-import model::model_views
+import model::model_collect
 import trees::trie
 
-redef class ModelView
+redef class Model
 
        # Keep a direct link to mentities by full name to speed up `mentity_from_uri`
        var mentities_by_full_name: HashMap[String, MEntity] is lazy do
                var mentities_by_full_name = new HashMap[String, MEntity]
-               for mentity in mentities do
+               for mentity in collect_mentities do
                        mentities_by_full_name[mentity.full_name] = mentity
                end
                return mentities_by_full_name
@@ -144,23 +142,29 @@ redef class ModelView
        # ModelIndex used to perform searches
        var index: ModelIndex is lazy do
                var index = new ModelIndex
-               for mentity in mentities do
+               for mentity in collect_mentities do
                        if mentity isa MClassDef or mentity isa MPropDef then continue
                        index.index mentity
                end
                return index
        end
 
-       redef fun mentities_by_name(name) do
+       redef fun mentities_by_name(name, filter) do
+               var res = new Array[MEntity]
                if index.name_prefixes.has_key(name) then
-                       return index.name_prefixes[name]
+                       for mentity in index.name_prefixes[name] do
+                               if filter == null or filter.accept_mentity(mentity) then
+                                       res.add mentity
+                               end
+                       end
                end
-               return new Array[MEntity]
+               return res
        end
 
-       redef fun mentity_by_full_name(full_name) do
+       redef fun mentity_by_full_name(full_name, filter) do
                if mentities_by_full_name.has_key(full_name) then
-                       return mentities_by_full_name[full_name]
+                       var mentity = mentities_by_full_name[full_name]
+                       if filter == null or filter.accept_mentity(mentity) then return mentity
                end
                return null
        end
@@ -175,7 +179,7 @@ redef class ModelView
 
        # Search mentities based on a `query` string
        #
-       # Lookup the view index for anything matching `query` and return `limit` results.
+       # Lookup the index for anything matching `query` and return `limit` results.
        #
        # The algorithm used is the following:
        # 1- lookup by name prefix
@@ -183,9 +187,9 @@ redef class ModelView
        # 3- loopup by levenshtein distance
        #
        # At each step if the `limit` is reached, the algorithm stops and returns the results.
-       fun find(query: String, limit: nullable Int): Array[MEntity] do
+       fun find(query: String, limit: nullable Int, filter: nullable ModelFilter): Array[MEntity] do
                # Find, lookup by name prefix
-               var matches = index.find_by_name_prefix(query).uniq.
+               var matches = index.find_by_name_prefix(query, filter).uniq.
                        sort(lname_sorter, name_sorter, kind_sorter)
                if limit != null and matches.length >= limit then
                        return matches.limit(limit).rerank.sort(vis_sorter, score_sorter).mentities
@@ -195,7 +199,7 @@ redef class ModelView
                # If limit not reached, lookup by full_name prefix
                var malus = matches.length
                var full_matches = new IndexMatches
-               for match in index.find_by_full_name_prefix(query).
+               for match in index.find_by_full_name_prefix(query, filter).
                        sort(kind_sorter, lfname_sorter, fname_sorter) do
                        match.score += malus
                        full_matches.add match
@@ -210,7 +214,7 @@ redef class ModelView
                # If limit not reached, lookup by similarity
                malus = matches.length
                var sim_matches = new IndexMatches
-               for match in index.find_by_similarity(query).sort(score_sorter, kind_sorter, lname_sorter, name_sorter) do
+               for match in index.find_by_similarity(query, filter).sort(score_sorter, kind_sorter, lname_sorter, name_sorter) do
                        match.score += malus
                        sim_matches.add match
                end
@@ -228,8 +232,7 @@ end
 # ~~~nitish
 # # Build index
 # var index = new ModelIndex
-# var view = new ModelView(model, mainmodule)
-# for mentity in view.mentities do
+# for mentity in model.collect_mentities do
 #      if mentity isa MClassDef or mentity isa MPropDef then continue
 #      index.index(mentity)
 # end
@@ -297,11 +300,12 @@ class ModelIndex
        # Results from the Trie are returned in a breadth first manner so we get the
        # matches ordered by prefix.
        # We preserve that order by giving an incremental score to the `array` items.
-       private fun score_results_incremental(array: Array[Array[MEntity]]): IndexMatches do
+       private fun score_results_incremental(array: Array[Array[MEntity]], filter: nullable ModelFilter): IndexMatches do
                var results = new IndexMatches
                var score = 1
                for mentities in array do
                        for mentity in mentities do
+                               if filter != null and not filter.accept_mentity(mentity) then continue
                                results.add new IndexMatch(mentity, score)
                        end
                        score += 1
@@ -310,22 +314,23 @@ class ModelIndex
        end
 
        # Find all mentities where `MEntity::name` matches the `prefix`
-       fun find_by_name_prefix(prefix: String): IndexMatches do
-               return score_results_incremental(name_prefixes.find_by_prefix(prefix))
+       fun find_by_name_prefix(prefix: String, filter: nullable ModelFilter): IndexMatches do
+               return score_results_incremental(name_prefixes.find_by_prefix(prefix), filter)
        end
 
        # Find all mentities where `MEntity::full_name` matches the `prefix`
-       fun find_by_full_name_prefix(prefix: String): IndexMatches do
-               return score_results_incremental(full_name_prefixes.find_by_prefix(prefix))
+       fun find_by_full_name_prefix(prefix: String, filter: nullable ModelFilter): IndexMatches do
+               return score_results_incremental(full_name_prefixes.find_by_prefix(prefix), filter)
        end
 
        # Rank all mentities by the distance between `MEntity::name` and `name`
        #
        # Use the Levenshtein algorithm on all the indexed mentities `name`.
        # Warning: may not scale to large indexes.
-       fun find_by_name_similarity(name: String): IndexMatches do
+       fun find_by_name_similarity(name: String, filter: nullable ModelFilter): IndexMatches do
                var results = new IndexMatches
                for mentity in mentities do
+                       if filter != null and not filter.accept_mentity(mentity) then continue
                        if mentity isa MClassDef or mentity isa MPropDef then continue
                        results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.name))
                end
@@ -336,9 +341,10 @@ class ModelIndex
        #
        # Use the Levenshtein algorithm on all the indexed mentities `full_name`.
        # Warning: may not scale to large indexes.
-       fun find_by_full_name_similarity(name: String): IndexMatches do
+       fun find_by_full_name_similarity(name: String, filter: nullable ModelFilter): IndexMatches do
                var results = new IndexMatches
                for mentity in mentities do
+                       if filter != null and not filter.accept_mentity(mentity) then continue
                        if mentity isa MClassDef or mentity isa MPropDef then continue
                        results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.full_name))
                end
@@ -346,9 +352,10 @@ class ModelIndex
        end
 
        # Rank all mentities by the distance between `name` and both the mentity name and full name
-       fun find_by_similarity(name: String): IndexMatches do
+       fun find_by_similarity(name: String, filter: nullable ModelFilter): IndexMatches do
                var results = new IndexMatches
                for mentity in mentities do
+                       if filter != null and not filter.accept_mentity(mentity) then continue
                        if mentity isa MClassDef or mentity isa MPropDef then continue
                        results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.name))
                        results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.full_name))
@@ -357,9 +364,10 @@ class ModelIndex
        end
 
        # Find mentities by name trying first by prefix then by similarity
-       fun find_by_name(name: String): IndexMatches do
+       fun find_by_name(name: String, filter: nullable ModelFilter): IndexMatches do
                var results = find_by_name_prefix(name)
                for mentity in mentities do
+                       if filter != null and not filter.accept_mentity(mentity) then continue
                        if mentity isa MClassDef or mentity isa MPropDef then continue
                        results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.name))
                end
@@ -367,9 +375,10 @@ class ModelIndex
        end
 
        # Find mentities by full name trying firt by prefix then by similarity
-       fun find_by_full_name(name: String): IndexMatches do
+       fun find_by_full_name(name: String, filter: nullable ModelFilter): IndexMatches do
                var results = find_by_full_name_prefix(name)
                for mentity in mentities do
+                       if filter != null and not filter.accept_mentity(mentity) then continue
                        if mentity isa MClassDef or mentity isa MPropDef then continue
                        results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.full_name))
                end
@@ -382,14 +391,15 @@ class ModelIndex
        # 2. add full name prefix matches
        # 3. try similarity by name
        # 4. try similarity by full_name
-       fun find(name: String): IndexMatches do
-               var results = find_by_name_prefix(name)
+       fun find(name: String, filter: nullable ModelFilter): IndexMatches do
+               var results = find_by_name_prefix(name, filter)
 
-               for result in find_by_full_name_prefix(name) do
+               for result in find_by_full_name_prefix(name, filter) do
                        results.add result
                end
 
                for mentity in mentities do
+                       if filter != null and not filter.accept_mentity(mentity) then continue
                        if mentity isa MClassDef or mentity isa MPropDef then continue
                        results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.name))
                        results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.full_name))