class Index
A list of definitions organised for quick lookup and lexical enumeration.
Definitions
def initialize(languages = Languages.all)
Initialize an empty index.
Implementation
def initialize(languages = Languages.all)
@languages = languages
@sources = {}
@definitions = {}
# This is essentially a prefix tree:
@trie = Trie.new
end
attr :languages
All supported languages for this index.
Signature
-
attribute
Languages
attr :sources
All source files that have been parsed.
Signature
-
attribute
Array(Source)
attr :definitions
All definitions which have been parsed.
Signature
-
attribute
Hash(String, Definition)
attr :trie
A (prefix) trie of lexically scoped definitions.
Signature
-
attribute
Trie
def update(paths)
Updates the index by parsing the specified files. All extracted definitions are merged into the existing index.
Signature
-
parameter
paths
Array(String)
The source file paths.
Implementation
def update(paths)
paths.each do |path|
if source = @languages.source_for(path)
@sources[path] = source
source.definitions do |symbol|
# $stderr.puts "Adding #{symbol.qualified_name} to #{symbol.lexical_path.join(' -> ')}"
@definitions[symbol.qualified_name] = symbol
@trie.insert(symbol.path, symbol)
end
end
end
end
def lookup(reference, relative_to: nil)
Lookup the specified reference and return matching definitions.
Signature
-
parameter
reference
Language::Reference
The reference to match.
-
parameter
relative_to
Definition
Lookup the reference relative to the scope of this definition.
Implementation
def lookup(reference, relative_to: nil)
if reference.absolute? || relative_to.nil?
lexical_path = []
else
lexical_path = relative_to.path.dup
end
path = reference.path
while true
node = @trie.lookup(lexical_path)
if node.children[path.first]
if target = node.lookup(path)
return reference.best(target.values)
else
return nil
end
end
break if lexical_path.empty?
lexical_path.pop
end
end