nitc :: ModelIndex
It provides methods to find mentities based on a prefix or string similarity.
var index = new ModelIndex
for mentity in model.collect_mentities do
if mentity isa MClassDef or mentity isa MPropDef then continue
index.index(mentity)
end
for e in index.find("Foo").uniq.sort(new ScoreComparator).limit(10) do
print " * {e.score}: {e.mentity.name} ({e.mentity.full_name})"
end
nitc :: ModelIndex :: _full_name_distances
Distance tree for mentitiesfull_name
nitc :: ModelIndex :: _full_name_prefixes
Prefix tree for mentitiesfull_name
nitc :: ModelIndex :: _full_names
Map of all mentities indexed by theirfull_name
nitc :: ModelIndex :: _mentities
List of all indexed mentities.nitc :: ModelIndex :: _name_distances
Distance tree for mentitiesname
nitc :: ModelIndex :: _name_prefixes
Prefix tree for mentitiesname
nitc :: ModelIndex :: defaultinit
nitc :: ModelIndex :: find
Find all mentities that matchesname
nitc :: ModelIndex :: find_by_full_name
Find mentities by full name trying firt by prefix then by similaritynitc :: ModelIndex :: find_by_full_name_prefix
Find all mentities whereMEntity::full_name
matches the prefix
nitc :: ModelIndex :: find_by_full_name_similarity
Rank all mentities by the distance betweenMEntity::full_name
and full_name
nitc :: ModelIndex :: find_by_name
Find mentities by name trying first by prefix then by similaritynitc :: ModelIndex :: find_by_name_prefix
Find all mentities whereMEntity::name
matches the prefix
nitc :: ModelIndex :: find_by_name_similarity
Rank all mentities by the distance betweenMEntity::name
and name
nitc :: ModelIndex :: find_by_similarity
Rank all mentities by the distance betweenname
and both the mentity name and full name
nitc :: ModelIndex :: full_name_distances
Distance tree for mentitiesfull_name
nitc :: ModelIndex :: full_name_distances=
Distance tree for mentitiesfull_name
nitc :: ModelIndex :: full_name_prefixes
Prefix tree for mentitiesfull_name
nitc :: ModelIndex :: full_name_prefixes=
Prefix tree for mentitiesfull_name
nitc :: ModelIndex :: full_names
Map of all mentities indexed by theirfull_name
nitc :: ModelIndex :: full_names=
Map of all mentities indexed by theirfull_name
nitc :: ModelIndex :: index
Indexmentity
so it can be retrieved by a find query
nitc :: ModelIndex :: index_by_full_name
Indexmentity
by its MEntity::full_name
nitc :: ModelIndex :: index_by_name
Indexmentity
by it's MEntity::name
nitc :: ModelIndex :: mentities=
List of all indexed mentities.nitc :: ModelIndex :: name_distances=
Distance tree for mentitiesname
nitc :: ModelIndex :: name_prefixes
Prefix tree for mentitiesname
nitc :: ModelIndex :: name_prefixes=
Prefix tree for mentitiesname
nitc :: ModelIndex :: score_results_incremental
Translate Trie results toSearchResult
nitc $ ModelIndex :: SELF
Type of this instance, automatically specialized in every classnitc :: ModelIndex :: _full_name_distances
Distance tree for mentitiesfull_name
nitc :: ModelIndex :: _full_name_prefixes
Prefix tree for mentitiesfull_name
nitc :: ModelIndex :: _full_names
Map of all mentities indexed by theirfull_name
nitc :: ModelIndex :: _mentities
List of all indexed mentities.nitc :: ModelIndex :: _name_distances
Distance tree for mentitiesname
nitc :: ModelIndex :: _name_prefixes
Prefix tree for mentitiesname
core :: Object :: class_factory
Implementation used byget_class
to create the specific class.
core :: Object :: defaultinit
nitc :: ModelIndex :: defaultinit
nitc :: ModelIndex :: find
Find all mentities that matchesname
nitc :: ModelIndex :: find_by_full_name
Find mentities by full name trying firt by prefix then by similaritynitc :: ModelIndex :: find_by_full_name_prefix
Find all mentities whereMEntity::full_name
matches the prefix
nitc :: ModelIndex :: find_by_full_name_similarity
Rank all mentities by the distance betweenMEntity::full_name
and full_name
nitc :: ModelIndex :: find_by_name
Find mentities by name trying first by prefix then by similaritynitc :: ModelIndex :: find_by_name_prefix
Find all mentities whereMEntity::name
matches the prefix
nitc :: ModelIndex :: find_by_name_similarity
Rank all mentities by the distance betweenMEntity::name
and name
nitc :: ModelIndex :: find_by_similarity
Rank all mentities by the distance betweenname
and both the mentity name and full name
nitc :: ModelIndex :: full_name_distances
Distance tree for mentitiesfull_name
nitc :: ModelIndex :: full_name_distances=
Distance tree for mentitiesfull_name
nitc :: ModelIndex :: full_name_prefixes
Prefix tree for mentitiesfull_name
nitc :: ModelIndex :: full_name_prefixes=
Prefix tree for mentitiesfull_name
nitc :: ModelIndex :: full_names
Map of all mentities indexed by theirfull_name
nitc :: ModelIndex :: full_names=
Map of all mentities indexed by theirfull_name
nitc :: ModelIndex :: index
Indexmentity
so it can be retrieved by a find query
nitc :: ModelIndex :: index_by_full_name
Indexmentity
by its MEntity::full_name
nitc :: ModelIndex :: index_by_name
Indexmentity
by it's MEntity::name
core :: Object :: is_same_instance
Return true ifself
and other
are the same instance (i.e. same identity).
core :: Object :: is_same_serialized
Isself
the same as other
in a serialization context?
core :: Object :: is_same_type
Return true ifself
and other
have the same dynamic type.
nitc :: ModelIndex :: mentities=
List of all indexed mentities.nitc :: ModelIndex :: name_distances=
Distance tree for mentitiesname
nitc :: ModelIndex :: name_prefixes
Prefix tree for mentitiesname
nitc :: ModelIndex :: name_prefixes=
Prefix tree for mentitiesname
core :: Object :: native_class_name
The class name of the object in CString format.core :: Object :: output_class_name
Display class name on stdout (debug only).nitc :: ModelIndex :: score_results_incremental
Translate Trie results toSearchResult
# ModelIndex indexes mentities by their name and full name
#
# It provides methods to find mentities based on a prefix or string similarity.
#
# ~~~nitish
# # Build index
# var index = new ModelIndex
# for mentity in model.collect_mentities do
# if mentity isa MClassDef or mentity isa MPropDef then continue
# index.index(mentity)
# end
#
# for e in index.find("Foo").uniq.sort(new ScoreComparator).limit(10) do
# print " * {e.score}: {e.mentity.name} ({e.mentity.full_name})"
# end
# ~~~
class ModelIndex
# List of all indexed mentities.
#
# Faster than traversing the tries.
var mentities = new Array[MEntity]
# Map of all mentities indexed by their `name`
var names = new HashMap[String, Array[MEntity]]
# Prefix tree for mentities `name`
#
# Because multiple mentities can share the same `name`, we use a Trie of
# arrays of mentities.
#
# As for now, we do not index class and property definitions.
# TODO add an option.
var name_prefixes = new Trie[Array[MEntity]]
# Distance tree for mentities `name`
var name_distances = new BKTree
# Map of all mentities indexed by their `full_name`
var full_names = new HashMap[String, MEntity]
# Prefix tree for mentities `full_name`
#
# Even if two mentities cannot share the same `full_name`, we use a Trie of
# arrays of mentities to be consistent with `name_prefixes`.
var full_name_prefixes = new Trie[Array[MEntity]]
# Distance tree for mentities `full_name`
var full_name_distances = new BKTree
# Index `mentity` by it's `MEntity::name`
#
# See `name_prefixes`.
private fun index_by_name(mentity: MEntity) do
var name = mentity.name
# Index name
if not names.has_key(name) then
names[name] = new Array[MEntity]
end
names[name].add mentity
# Index prefix
if not name_prefixes.has_key(name) then
name_prefixes[name] = new Array[MEntity]
end
name_prefixes[name].add mentity
# Index distance
name_distances.add(name)
end
# Index `mentity` by its `MEntity::full_name`
private fun index_by_full_name(mentity: MEntity) do
var name = mentity.full_name
# Index full name
full_names[name] = mentity
# Index prefix
if not full_name_prefixes.has_key(name) then
full_name_prefixes[name] = new Array[MEntity]
end
full_name_prefixes[name].add mentity
# Index distance
full_name_distances.add(name)
end
# Index `mentity` so it can be retrieved by a find query
#
# MEntities are indexed by both name and full_name.
fun index(mentity: MEntity) do
mentities.add mentity
index_by_name mentity
index_by_full_name mentity
end
# Translate Trie results to `SearchResult`
#
# This method is used internally to translate each mentity returned by a prefix
# match in a Trie into a SearchResult that can be ranked by score.
#
# 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]], 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
end
return results
end
# Find all mentities where `MEntity::name` matches the `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, 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, filter: nullable ModelFilter): IndexMatches do
var results = new IndexMatches
for match in name_distances.search(name) do
var dist = match.distance
var mname = match.key
if not names.has_key(mname) then continue
for mentity in names[mname] do
if mentity isa MClassDef or mentity isa MPropDef then continue
if filter != null and not filter.accept_mentity(mentity) then continue
results.add new IndexMatch(mentity, dist)
end
end
return results
end
# Rank all mentities by the distance between `MEntity::full_name` and `full_name`
#
# 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, filter: nullable ModelFilter): IndexMatches do
var results = new IndexMatches
for match in full_name_distances.search(name) do
var dist = match.distance
var mname = match.key
if not full_names.has_key(mname) then continue
var mentity = full_names[mname]
if mentity isa MClassDef or mentity isa MPropDef then continue
if filter != null and not filter.accept_mentity(mentity) then continue
results.add new IndexMatch(mentity, dist)
end
return results
end
# Rank all mentities by the distance between `name` and both the mentity name and full name
fun find_by_similarity(name: String, filter: nullable ModelFilter): IndexMatches do
var results = new IndexMatches
results.add_all find_by_full_name_similarity(name, filter)
results.add_all find_by_name_similarity(name, filter)
return results
end
# Find mentities by name trying first by prefix then by similarity
fun find_by_name(name: String, filter: nullable ModelFilter): IndexMatches do
var results = find_by_name_prefix(name, filter)
results.add_all find_by_name_similarity(name, filter)
return results
end
# Find mentities by full name trying firt by prefix then by similarity
fun find_by_full_name(name: String, filter: nullable ModelFilter): IndexMatches do
var results = find_by_full_name_prefix(name)
results.add_all find_by_full_name_similarity(name, filter)
return results
end
# Find all mentities that matches `name`
#
# 1. try by name prefix
# 2. add full name prefix matches
# 3. try similarity by name
# 4. try similarity by full_name
fun find(name: String, filter: nullable ModelFilter): IndexMatches do
var results = find_by_name_prefix(name, filter)
results.add_all find_by_full_name_prefix(name, filter)
results.add_all find_by_similarity(name, filter)
return results
end
end
src/model/model_index.nit:227,1--427,3