class Index
Represents a list of definitions organised for quick lookup and lexical enumeration.
Definitions
def self.for(*paths, languages: Languages.all)
Create and populate an index from the given paths.
Signature
-
parameter
paths
Array(String)
The paths to index (files, directories, or glob patterns).
-
parameter
languages
Languages
The languages to support in this index.
-
returns
Index
A new index populated with definitions from the given paths.
Implementation
def self.for(*paths, languages: Languages.all)
# Resolve all paths to actual files:
resolved_paths = paths.flat_map do |path|
if File.directory?(path)
Dir.glob(File.join(path, "**/*"))
elsif File.file?(path)
[path]
else
# Handle glob patterns or non-existent paths:
Dir.glob(path)
end
end
resolved_paths.sort!
resolved_paths.uniq!
# Create and populate the index:
index = new(languages)
index.update(resolved_paths)
return index
end
def initialize(languages = Languages.all)
Initialize an empty index.
Signature
-
parameter
languages
Languages
The languages to support in this index.
Implementation
def initialize(languages = Languages.all)
# Initialize with supported languages:
@languages = languages
# Initialize storage for sources and definitions:
@sources = {}
@definitions = {}
# Create a prefix tree for efficient lookups:
@trie = Trie.new
end
def inspect
Generate a string representation of this index.
Signature
-
returns
String
A formatted string showing the number of definitions.
Implementation
def inspect
"#<#{self.class} #{@definitions.size} definition(s)>"
end
alias to_s inspect
Generate a string representation of the index.
attr :languages
All supported languages for this index.
Signature
-
attribute
Languages
The languages this index can parse.
attr :sources
All source files that have been parsed.
Signature
-
attribute
Hash(String, Source)
A mapping of file paths to source objects.
attr :definitions
All definitions which have been parsed.
Signature
-
attribute
Hash(String, Definition)
A mapping of qualified names to definitions.
attr :trie
A (prefix) trie of lexically scoped definitions.
Signature
-
attribute
Trie
The trie structure for efficient lookups.
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 to parse and index.
Implementation
def update(paths)
paths.each do |path|
if source = @languages.source_for(path)
# Store the source file:
@sources[path] = source
# Extract and index all definitions:
source.definitions do |symbol|
# $stderr.puts "Adding #{symbol.qualified_name} to #{symbol.lexical_path.join(' -> ')}"
# Add to definitions lookup:
@definitions[symbol.qualified_name] = symbol
# Add to trie for hierarchical lookup:
@trie.insert(symbol.full_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.
-
returns
Definition | Nil
The best matching definition, or nil if not found.
Implementation
def lookup(reference, relative_to: nil)
if reference.absolute? || relative_to.nil?
# Start from root scope:
lexical_path = []
else
# Start from the given definition's scope:
lexical_path = relative_to.full_path.dup
end
path = reference.path
while true
# Get the current scope node:
node = @trie.lookup(lexical_path)
if node.children[path.first]
if target = node.lookup(path)
# Return the best matching definition:
return reference.best(target.values)
else
return nil
end
end
# Move up one scope level:
break if lexical_path.empty?
lexical_path.pop
end
end