Module: Rigor::Reflection
- Defined in:
- lib/rigor/reflection.rb,
sig/rigor/reflection.rbs
Overview
Read-side facade over Rigor's three reflection sources:
Rigor::Environment::ClassRegistry— RubyClass/Moduleobjects (Integer, Float, Set, Pathname, …) registered at boot. Static; never changes during arigor checkrun.Rigor::Environment::RbsLoader— RBS-side declarations (instance / singleton methods, class hierarchy, constants). Loaded on demand from the project'ssig/directory + the bundled stdlib RBS.Rigor::Scopediscovered facts — source-side discoveries produced byRigor::Inference::ScopeIndexer(user-defined classes / modules, in-source constants, discovered method nodes, class ivar / cvar declarations).
This module is the stable read shape the plugin API is designed against (ADR-2,
docs/adr/2-extension-api.md).
The facade is read-only and additive. Existing call sites that read directly from
Rigor::Scope or Rigor::Environment::RbsLoader continue to work unchanged; they
migrate to the facade at their own pace. The facade performs no caching beyond what the
underlying sources already provide.
Public surface (v0.0.7 first pass)
- Reflection.class_known? — does any source recognise this class / module name?
- Reflection.class_ordering —
:equal/:subclass/:superclass/:disjoint/:unknownordering between two class names. - Reflection.nominal_for_name —
Rigor::Type::Nominalfor the class name, joining registry + RBS lookups. - Reflection.singleton_for_name —
Rigor::Type::Singletonfor the class name's class object. - Reflection.constant_type_for — type of a constant (joins in-source constants and RBS-side constants).
- Reflection.instance_method_definition / Reflection.singleton_method_definition — RBS-side
RBS::Definition::Methodfor the method, ornilwhen the method is not declared in RBS. Source-side discovered methods are exposed through Reflection.discovered_method? below until the unifiedMethodDefinitioncarrier ships. - Reflection.discovered_class? / Reflection.discovered_method? — has the ScopeIndexer pass recorded the class / method as user-defined in the analyzed sources?
The provenance side of the API (which source family contributed each fact) is explicitly out of scope for the v0.0.7 first pass; v0.1.0's plugin API added it as a separate concern.
Class Method Summary collapse
- .class_known?(class_name, scope: Scope.empty) ⇒ Boolean
-
.class_ordering(lhs, rhs, scope: Scope.empty) ⇒ Symbol
One of
:equal,:subclass,:superclass,:disjoint,:unknown. -
.class_type_param_names(class_name, scope: nil, environment: nil) ⇒ Object
Returns the RBS-declared type parameter names for the class (e.g.
[:A]forArray[A]), or[]when the class is non-generic / not in RBS. -
.constant_type_for(constant_name, scope: Scope.empty) ⇒ Object
Returns the type of the named constant.
-
.discovered_class?(class_name, scope: Scope.empty) ⇒ Boolean
True when the analyzed source contains a class / module declaration for the given name.
-
.discovered_method?(class_name, method_name, kind: :instance, scope: Scope.empty) ⇒ Boolean
True when the ScopeIndexer recorded a
deffor the given method on the given class with the matching kind. -
.instance_definition(class_name, scope: nil, environment: nil) ⇒ Object
Returns the full RBS instance-side class definition (
RBS::Definition), used by callers that walk the method table or member list. -
.instance_method_definition(class_name, method_name, scope: nil, environment: nil) ⇒ Object
Returns the RBS
RBS::Definition::Methodfor the instance method, or nil when the class or method is not in RBS. -
.nominal_for_name(class_name, scope: Scope.empty) ⇒ Object
Returns the
Rigor::Type::Nominalfor the class name, or nil when no source knows the class. -
.rbs_class_known?(class_name, scope: nil, environment: nil) ⇒ Boolean
RBS-only variant of Reflection.class_known?.
-
.resolve_constant_type(name, scope: Scope.empty) ⇒ Object
Resolves a constant reference to its type through Ruby's lexical constant lookup: the most-qualified candidate first (the enclosing class path joined to
name), then progressively less-qualified, then the barename. -
.singleton_definition(class_name, scope: nil, environment: nil) ⇒ Object
Returns the full RBS singleton-side class definition.
-
.singleton_for_name(class_name, scope: Scope.empty) ⇒ Object
Returns the
Rigor::Type::Singletonfor the class name's class object, or nil when no source knows the class. -
.singleton_method_definition(class_name, method_name, scope: nil, environment: nil) ⇒ Object
Returns the RBS
RBS::Definition::Methodfor the singleton (class-side) method, or nil.
Instance Method Summary collapse
- #self?.class_known? ⇒ Boolean
- #self?.class_ordering ⇒ Symbol
- #self?.class_type_param_names ⇒ Array[Symbol]
- #self?.constant_type_for ⇒ Type::t?
- #self?.discovered_class? ⇒ Boolean
- #self?.discovered_method? ⇒ Boolean
- #self?.instance_definition ⇒ Object
- #self?.instance_method_definition ⇒ Object
- #self?.nominal_for_name ⇒ Type::Nominal?
- #self?.rbs_class_known? ⇒ Boolean
- #self?.resolve_constant_type ⇒ Type::t?
- #self?.singleton_definition ⇒ Object
- #self?.singleton_for_name ⇒ Type::Singleton?
- #self?.singleton_method_definition ⇒ Object
Class Method Details
.class_known?(class_name, scope: Scope.empty) ⇒ Boolean
52 53 54 55 56 |
# File 'lib/rigor/reflection.rb', line 52 def class_known?(class_name, scope: Scope.empty) return true if scope.discovered_classes.key?(class_name.to_s) scope.environment.class_known?(class_name) end |
.class_ordering(lhs, rhs, scope: Scope.empty) ⇒ Symbol
Returns one of :equal, :subclass, :superclass,
:disjoint, :unknown.
77 78 79 |
# File 'lib/rigor/reflection.rb', line 77 def class_ordering(lhs, rhs, scope: Scope.empty) scope.environment.class_ordering(lhs, rhs) end |
.class_type_param_names(class_name, scope: nil, environment: nil) ⇒ Object
Returns the RBS-declared type parameter names for the class (e.g. [:A] for
Array[A]), or [] when the class is non-generic / not in RBS. Used by the dispatcher
when binding generic method types to a concrete receiver.
214 215 216 217 218 219 |
# File 'lib/rigor/reflection.rb', line 214 def class_type_param_names(class_name, scope: nil, environment: nil) loader = rbs_loader_for(scope, environment) return [] if loader.nil? loader.class_type_param_names(class_name.to_s) end |
.constant_type_for(constant_name, scope: Scope.empty) ⇒ Object
Returns the type of the named constant. Joins in-source constants (recorded by
ScopeIndexer) and RBS-side constants. In-source wins on collision because the user's
source is the authoritative declaration.
This is the flat lookup keyed on the literal constant_name. Callers that need Ruby's
lexical constant resolution (walking the enclosing class path, and folding in registry
classes / source-discovered classes as Singleton / class types) use
resolve_constant_type instead.
101 102 103 104 105 106 107 |
# File 'lib/rigor/reflection.rb', line 101 def constant_type_for(constant_name, scope: Scope.empty) key = constant_name.to_s in_source = scope.in_source_constants[key] return in_source if in_source scope.environment.constant_for_name(constant_name) end |
.discovered_class?(class_name, scope: Scope.empty) ⇒ Boolean
Returns true when the analyzed source contains a class / module declaration for the given name. Does NOT consult the RBS loader (use class_known? for the union).
235 236 237 |
# File 'lib/rigor/reflection.rb', line 235 def discovered_class?(class_name, scope: Scope.empty) scope.discovered_classes.key?(class_name.to_s) end |
.discovered_method?(class_name, method_name, kind: :instance, scope: Scope.empty) ⇒ Boolean
Returns true when the ScopeIndexer recorded a def for the given method on
the given class with the matching kind.
242 243 244 |
# File 'lib/rigor/reflection.rb', line 242 def discovered_method?(class_name, method_name, kind: :instance, scope: Scope.empty) scope.discovered_method?(class_name, method_name, kind) end |
.instance_definition(class_name, scope: nil, environment: nil) ⇒ Object
Returns the full RBS instance-side class definition (RBS::Definition), used by
callers that walk the method table or member list. Returns nil when the class is not
in RBS or when the loader cannot build a definition (e.g. constant aliases, malformed
signatures).
192 193 194 195 196 197 198 199 |
# File 'lib/rigor/reflection.rb', line 192 def instance_definition(class_name, scope: nil, environment: nil) loader = rbs_loader_for(scope, environment) return nil if loader.nil? loader.instance_definition(class_name.to_s) rescue ::RBS::BaseError nil end |
.instance_method_definition(class_name, method_name, scope: nil, environment: nil) ⇒ Object
Returns the RBS RBS::Definition::Method for the instance method, or nil when the
class or method is not in RBS. The source-side discovered-method facts are reachable
through discovered_method?; a future slice will unify the two under a
MethodDefinition carrier.
172 173 174 175 176 177 |
# File 'lib/rigor/reflection.rb', line 172 def instance_method_definition(class_name, method_name, scope: nil, environment: nil) loader = rbs_loader_for(scope, environment) return nil if loader.nil? loader.instance_method(class_name: class_name.to_s, method_name: method_name.to_sym) end |
.nominal_for_name(class_name, scope: Scope.empty) ⇒ Object
Returns the Rigor::Type::Nominal for the class name, or nil when no source knows the
class.
83 84 85 |
# File 'lib/rigor/reflection.rb', line 83 def nominal_for_name(class_name, scope: Scope.empty) scope.environment.nominal_for_name(class_name) end |
.rbs_class_known?(class_name, scope: nil, environment: nil) ⇒ Boolean
RBS-only variant of class_known?. Use when the caller needs to know specifically
whether RBS has a definition for the class, independent of any source-discovered class Foo; end declarations. The diagnostic-rule code paths that walk RBS method tables to
decide whether to flag a missing method use this variant; otherwise the
source-discovered class would suppress the rule even when no RBS sig actually proves
the method exists.
The kwarg accepts either scope: or environment:. The latter is for call sites that
don't carry a Scope (most are bottom-half dispatcher code paths called with only an
environment).
68 69 70 71 72 73 |
# File 'lib/rigor/reflection.rb', line 68 def rbs_class_known?(class_name, scope: nil, environment: nil) loader = rbs_loader_for(scope, environment) return false if loader.nil? loader.class_known?(class_name) end |
.resolve_constant_type(name, scope: Scope.empty) ⇒ Object
Resolves a constant reference to its type through Ruby's lexical constant lookup: the
most-qualified candidate first (the enclosing class path joined to name), then
progressively less-qualified, then the bare name. Each candidate consults, in order,
the class registry (yielding a Singleton[C]), source-discovered classes, in-source
value constants, and finally RBS-side constants — in-source value constants winning over
RBS because the user's source is authoritative for its own constants. Returns the matched
Rigor::Type, or nil when no source knows the constant.
This is the shared owner of the lexical-constant resolution: Inference::ExpressionTyper
reads it to type a constant read, and Inference::Narrowing reads it to recognise a
value-pinned Constant[Regexp] match-predicate operand.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/rigor/reflection.rb', line 120 def resolve_constant_type(name, scope: Scope.empty) env = scope.environment discovered = scope.discovered_classes in_source = scope.in_source_constants lexical_constant_candidates(name, scope: scope).each do |candidate| singleton = env.singleton_for_name(candidate) return singleton if singleton in_source_class = discovered[candidate] return in_source_class if in_source_class # In-source value-bearing constants take precedence over RBS constant decls because # user code is the authoritative source for its own constants. in_source_value = in_source[candidate] return in_source_value if in_source_value value = env.constant_for_name(candidate) return value if value end nil end |
.singleton_definition(class_name, scope: nil, environment: nil) ⇒ Object
Returns the full RBS singleton-side class definition.
202 203 204 205 206 207 208 209 |
# File 'lib/rigor/reflection.rb', line 202 def singleton_definition(class_name, scope: nil, environment: nil) loader = rbs_loader_for(scope, environment) return nil if loader.nil? loader.singleton_definition(class_name.to_s) rescue ::RBS::BaseError nil end |
.singleton_for_name(class_name, scope: Scope.empty) ⇒ Object
Returns the Rigor::Type::Singleton for the class name's class object, or nil when no
source knows the class.
89 90 91 |
# File 'lib/rigor/reflection.rb', line 89 def singleton_for_name(class_name, scope: Scope.empty) scope.environment.singleton_for_name(class_name) end |
.singleton_method_definition(class_name, method_name, scope: nil, environment: nil) ⇒ Object
Returns the RBS RBS::Definition::Method for the singleton (class-side) method, or
nil.
181 182 183 184 185 186 |
# File 'lib/rigor/reflection.rb', line 181 def singleton_method_definition(class_name, method_name, scope: nil, environment: nil) loader = rbs_loader_for(scope, environment) return nil if loader.nil? loader.singleton_method(class_name: class_name.to_s, method_name: method_name.to_sym) end |
Instance Method Details
#self?.class_known? ⇒ Boolean
3 |
# File 'sig/rigor/reflection.rbs', line 3
def self?.class_known?: (String | Symbol class_name, ?scope: Scope) -> bool
|
#self?.class_ordering ⇒ Symbol
5 |
# File 'sig/rigor/reflection.rbs', line 5
def self?.class_ordering: (String | Symbol lhs, String | Symbol rhs, ?scope: Scope) -> Symbol
|
#self?.class_type_param_names ⇒ Array[Symbol]
14 |
# File 'sig/rigor/reflection.rbs', line 14
def self?.class_type_param_names: (String | Symbol class_name, ?scope: Scope) -> Array[Symbol]
|
#self?.constant_type_for ⇒ Type::t?
8 |
# File 'sig/rigor/reflection.rbs', line 8
def self?.constant_type_for: (String | Symbol constant_name, ?scope: Scope) -> Type::t?
|
#self?.discovered_class? ⇒ Boolean
15 |
# File 'sig/rigor/reflection.rbs', line 15
def self?.discovered_class?: (String | Symbol class_name, ?scope: Scope) -> bool
|
#self?.discovered_method? ⇒ Boolean
16 |
# File 'sig/rigor/reflection.rbs', line 16
def self?.discovered_method?: (String | Symbol class_name, String | Symbol method_name, ?kind: Symbol, ?scope: Scope) -> bool
|
#self?.instance_definition ⇒ Object
12 |
# File 'sig/rigor/reflection.rbs', line 12
def self?.instance_definition: (String | Symbol class_name, ?scope: Scope) -> untyped
|
#self?.instance_method_definition ⇒ Object
10 |
# File 'sig/rigor/reflection.rbs', line 10
def self?.instance_method_definition: (String | Symbol class_name, String | Symbol method_name, ?scope: Scope) -> untyped
|
#self?.nominal_for_name ⇒ Type::Nominal?
6 |
# File 'sig/rigor/reflection.rbs', line 6
def self?.nominal_for_name: (String | Symbol class_name, ?scope: Scope) -> Type::Nominal?
|
#self?.rbs_class_known? ⇒ Boolean
4 |
# File 'sig/rigor/reflection.rbs', line 4
def self?.rbs_class_known?: (String | Symbol class_name, ?scope: Scope) -> bool
|
#self?.resolve_constant_type ⇒ Type::t?
9 |
# File 'sig/rigor/reflection.rbs', line 9
def self?.resolve_constant_type: (String | Symbol name, ?scope: Scope) -> Type::t?
|
#self?.singleton_definition ⇒ Object
13 |
# File 'sig/rigor/reflection.rbs', line 13
def self?.singleton_definition: (String | Symbol class_name, ?scope: Scope) -> untyped
|
#self?.singleton_for_name ⇒ Type::Singleton?
7 |
# File 'sig/rigor/reflection.rbs', line 7
def self?.singleton_for_name: (String | Symbol class_name, ?scope: Scope) -> Type::Singleton?
|
#self?.singleton_method_definition ⇒ Object
11 |
# File 'sig/rigor/reflection.rbs', line 11
def self?.singleton_method_definition: (String | Symbol class_name, String | Symbol method_name, ?scope: Scope) -> untyped
|