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
 #
 # ~~~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
 # ~~~
 #      index.index(mentity)
 # end
 # ~~~
@@ -55,8 +54,7 @@
 #
 # ~~~nitish
 # var index = new ModelIndex
 #
 # ~~~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)
 #      # We don't really care about definitions
 #      if mentity isa MClassDef or mentity isa MPropDef then continue
 #      index.index(mentity)
 # ~~~
 module model_index
 
 # ~~~
 module model_index
 
-import model::model_views
+import model::model_collect
 import trees::trie
 
 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]
 
        # 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
                        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
        # 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
 
                        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
                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
                end
-               return new Array[MEntity]
+               return res
        end
 
        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
                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
                end
                return null
        end
@@ -175,7 +179,7 @@ redef class ModelView
 
        # Search mentities based on a `query` string
        #
 
        # 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
        #
        # 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.
        # 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
                # 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
                        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
                # 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
                        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
                # 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
                        match.score += malus
                        sim_matches.add match
                end
@@ -228,8 +232,7 @@ end
 # ~~~nitish
 # # Build index
 # var index = new ModelIndex
 # ~~~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
 #      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.
        # 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
                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
                                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`
        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`
        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.
        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
                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
                        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.
        #
        # 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
                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
                        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
        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
                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))
                        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
        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
                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
                        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
        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
                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
                        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
        # 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
                        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))
                        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))