Module: Rigor::Reflection
- Defined in:
- lib/rigor/reflection.rb
Overview
Read-side facade over Rigor’s three reflection sources:
-
**‘Rigor::Environment::ClassRegistry`** — Ruby `Class` / `Module` objects (Integer, Float, Set, Pathname, …) registered at boot. Static; never changes during a `rigor check` run.
-
**‘Rigor::Environment::RbsLoader`** — RBS-side declarations (instance / singleton methods, class hierarchy, constants). Loaded on demand from the project’s ‘sig/` directory + the bundled stdlib RBS.
-
**‘Rigor::Scope` discovered facts** — source-side discoveries produced by `Rigor::Inference::ScopeIndexer` (user-defined classes / modules, in-source constants, discovered method nodes, class ivar / cvar declarations).
This module is the **stable read shape** that v0.1.0’s plugin API will be designed against. ADR-2 (‘docs/adr/2-extension-api.md`) calls out a unified reflection layer as a prerequisite for the extension protocols, and `docs/design/20260505-v0.1.0-readiness.md` nominates this module as the highest-leverage cold-start slice.
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` / `:unknown` ordering between two class names.
-
Reflection.nominal_for_name — ‘Rigor::Type::Nominal` for the class name, joining registry + RBS lookups.
-
Reflection.singleton_for_name — ‘Rigor::Type::Singleton` for 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::Method` for the method, or `nil` when the method is not declared in RBS. Source-side discovered methods are exposed through Reflection.discovered_method? below until the unified `MethodDefinition` carrier 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 adds 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]` for `Array`), 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 ‘def` for 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::Method` for 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::Nominal` for 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?.
-
.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::Singleton` for 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::Method` for the singleton (class-side) method, or nil.
Class Method Details
.class_known?(class_name, scope: Scope.empty) ⇒ Boolean
63 64 65 66 67 |
# File 'lib/rigor/reflection.rb', line 63 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`.
91 92 93 |
# File 'lib/rigor/reflection.rb', line 91 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`), or `[]` when the class is non-generic / not in RBS. Used by the dispatcher when binding generic method types to a concrete receiver.
168 169 170 171 172 173 |
# File 'lib/rigor/reflection.rb', line 168 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.
111 112 113 114 115 116 117 |
# File 'lib/rigor/reflection.rb', line 111 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).
191 192 193 |
# File 'lib/rigor/reflection.rb', line 191 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.
199 200 201 |
# File 'lib/rigor/reflection.rb', line 199 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).
145 146 147 148 149 150 151 152 |
# File 'lib/rigor/reflection.rb', line 145 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 StandardError 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.
124 125 126 127 128 129 |
# File 'lib/rigor/reflection.rb', line 124 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.
97 98 99 |
# File 'lib/rigor/reflection.rb', line 97 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).
82 83 84 85 86 87 |
# File 'lib/rigor/reflection.rb', line 82 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 |
.singleton_definition(class_name, scope: nil, environment: nil) ⇒ Object
Returns the full RBS singleton-side class definition.
155 156 157 158 159 160 161 162 |
# File 'lib/rigor/reflection.rb', line 155 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 StandardError 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.
103 104 105 |
# File 'lib/rigor/reflection.rb', line 103 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.
133 134 135 136 137 138 |
# File 'lib/rigor/reflection.rb', line 133 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 |