class Spoom::Model
def [](full_name)
Raises an error if the symbol is not found
Get a symbol by it's full name
def [](full_name) symbol = @symbols[full_name] raise Error, "Symbol not found: #{full_name}" unless symbol symbol end
def compute_symbols_hierarchy!
def compute_symbols_hierarchy! @symbols.dup.each do |_full_name, symbol| symbol.definitions.each do |definition| next unless definition.is_a?(Namespace) @symbols_hierarchy.add_element(symbol) if definition.is_a?(Class) superclass_name = definition.superclass_name if superclass_name superclass = resolve_symbol(superclass_name, context: symbol) @symbols_hierarchy.add_direct_edge(symbol, superclass) end end definition.mixins.each do |mixin| next if mixin.is_a?(Extend) target = resolve_symbol(mixin.name, context: symbol) @symbols_hierarchy.add_direct_edge(symbol, target) end end end end
def finalize!
def finalize! compute_symbols_hierarchy! end
def initialize
def initialize @symbols = {} #: Hash[String, Symbol] @symbols_hierarchy = Poset.new #: Poset[Symbol] end
def register_symbol(full_name)
If the symbol already exists, it will be returned.
Register a new symbol by it's full name
def register_symbol(full_name) @symbols[full_name] ||= Symbol.new(full_name) end
def resolve_symbol(full_name, context:)
def resolve_symbol(full_name, context:) if full_name.start_with?("::") full_name = full_name.delete_prefix("::") return @symbols[full_name] ||= UnresolvedSymbol.new(full_name) end target = @symbols[full_name] #: Symbol? return target if target parts = context.full_name.split("::") until parts.empty? target = @symbols["#{parts.join("::")}::#{full_name}"] return target if target parts.pop end @symbols[full_name] = UnresolvedSymbol.new(full_name) end
def subtypes(symbol)
def subtypes(symbol) poe = @symbols_hierarchy[symbol] poe.descendants end
def supertypes(symbol)
def supertypes(symbol) poe = @symbols_hierarchy[symbol] poe.ancestors end