Class: RBS::Resolver::ConstantResolver

Inherits:
Object
  • Object
show all
Defined in:
lib/rbs/resolver/constant_resolver.rb,
sig/resolver/constant_resolver.rbs

Defined Under Namespace

Classes: Table

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(builder:) ⇒ ConstantResolver

Returns a new instance of ConstantResolver.

Parameters:



88
89
90
91
92
93
# File 'lib/rbs/resolver/constant_resolver.rb', line 88

def initialize(builder:)
  @builder = builder
  @table = Table.new(builder.env)
  @context_constants_cache = {}
  @child_constants_cache = {}
end

Instance Attribute Details

#builderDefinitionBuilder (readonly)

Returns the value of attribute builder.

Returns:



85
86
87
# File 'lib/rbs/resolver/constant_resolver.rb', line 85

def builder
  @builder
end

#child_constants_cacheHash[TypeName, Hash[Symbol, Constant]] (readonly)

Returns the value of attribute child_constants_cache.

Returns:



86
87
88
# File 'lib/rbs/resolver/constant_resolver.rb', line 86

def child_constants_cache
  @child_constants_cache
end

#context_constants_cacheHash[context, Hash[Symbol, Constant]?] (readonly)

Returns the value of attribute context_constants_cache.

Returns:

  • (Hash[context, Hash[Symbol, Constant]?])


86
87
88
# File 'lib/rbs/resolver/constant_resolver.rb', line 86

def context_constants_cache
  @context_constants_cache
end

#tableTable (readonly)

Returns the value of attribute table.

Returns:



85
86
87
# File 'lib/rbs/resolver/constant_resolver.rb', line 85

def table
  @table
end

Instance Method Details

#children(module_name) ⇒ Hash[Symbol, Constant]

Returns the table of all constants accessible with :: (colon2) operator.

  • The constants under the module are included.
  • The constants under the ancestor modules are included.
    • The constants under the ::Object class are not included.
    • The top level constants are not included.

Parameters:

Returns:



77
78
79
80
81
82
83
84
85
# File 'sig/resolver/constant_resolver.rbs', line 77

def children(module_name)
  module_name = builder.env.normalize_module_name(module_name)

  unless child_constants_cache.key?(module_name)
    load_child_constants(module_name)
  end

  child_constants_cache[module_name] or raise
end

#constants(context) ⇒ Hash[Symbol, Constant]?

Returns the available all constants from context.

Returns nil when the context is invalid.

Parameters:

  • (context)

Returns:



58
59
60
61
62
63
64
# File 'sig/resolver/constant_resolver.rbs', line 58

def constants(context)
  unless context_constants_cache.key?(context)
    load_context_constants(context)
  end

  context_constants_cache[context]
end

#constants_from_ancestors(module_name, constants:) ⇒ void

This method returns an undefined value.

Parameters:



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/rbs/resolver/constant_resolver.rb', line 178

def constants_from_ancestors(module_name, constants:)
  entry = builder.env.module_class_entry(module_name, normalized: true) or raise

  if entry.is_a?(Environment::ClassEntry) || entry.is_a?(Environment::ModuleEntry)
    constants.merge!(table.children(BuiltinNames::Object.name) || raise)
    constants.merge!(table.toplevel)
  end

  builder.ancestor_builder.instance_ancestors(entry.name).ancestors.reverse_each do |ancestor|
    if ancestor.is_a?(Definition::Ancestor::Instance)
      case ancestor.source
      when AST::Members::Include, :super, nil
        consts = table.children(ancestor.name) or raise
        if ancestor.name == BuiltinNames::Object.name && entry.is_a?(Environment::ClassEntry)
          # Insert toplevel constants as ::Object's constants
          consts.merge!(table.toplevel)
        end
        constants.merge!(consts)
      end
    end
  end
end

#constants_from_context(context, constants:) ⇒ Boolean

Parameters:

  • (context)
  • constants: (Hash[Symbol, Constant])

Returns:

  • (Boolean)


163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/rbs/resolver/constant_resolver.rb', line 163

def constants_from_context(context, constants:)
  if context
    parent, last = context

    constants_from_context(parent, constants: constants) or return false

    if last
      consts = table.children(builder.env.normalize_module_name(last)) or return false
      constants.merge!(consts)
    end
  end

  true
end

#constants_itself(context, constants:) ⇒ void

This method returns an undefined value.

Parameters:

  • (context)
  • constants: (Hash[Symbol, Constant])


201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/rbs/resolver/constant_resolver.rb', line 201

def constants_itself(context, constants:)
  if context
    _, typename = context

    if typename
      if (ns = typename.namespace).empty?
        constant = table.toplevel[typename.name] or raise
      else
        hash = table.children(ns.to_type_name) or raise
        constant = hash[typename.name]
      end

      constants[typename.name] = constant
    end
  end
end

#load_child_constants(name) ⇒ void

This method returns an undefined value.

Parameters:



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/rbs/resolver/constant_resolver.rb', line 138

def load_child_constants(name)
  # @type var constants: Hash[Symbol, Constant]
  constants = {}

  if table.children(name)
    builder.ancestor_builder.instance_ancestors(name).ancestors.reverse_each do |ancestor|
      if ancestor.is_a?(Definition::Ancestor::Instance)
        if ancestor.name == BuiltinNames::Object.name
          if name != BuiltinNames::Object.name
            next
          end
        end

        case ancestor.source
        when AST::Members::Include, :super, nil
          consts = table.children(ancestor.name) or raise
          constants.merge!(consts)
        end
      end
    end
  end

  child_constants_cache[name] = constants
end

#load_context_constants(context) ⇒ void

This method returns an undefined value.

Parameters:

  • (context)


122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/rbs/resolver/constant_resolver.rb', line 122

def load_context_constants(context)
  # @type var consts: Hash[Symbol, Constant]
  consts = {}

  if last = context&.[](1)
    constants_from_ancestors(last, constants: consts)
  else
    constants_from_ancestors(BuiltinNames::Object.name, constants: consts)
  end

  constants_from_context(context, constants: consts) or return
  constants_itself(context, constants: consts)

  context_constants_cache[context] = consts
end

#resolve(name, context:) ⇒ Constant?

Resolves to Constant with given constant name name and context. Returns nil if the constant cannot be resolved from the context.

Parameters:

  • name (Symbol)
  • context: (context)

Returns:



53
54
55
56
# File 'sig/resolver/constant_resolver.rbs', line 53

def resolve(name, context:)
  cs = constants(context) or raise "Broken context is given"
  cs[name]
end

#resolve_child(module_name, name) ⇒ Constant?

Resolves the module_name and constant name to Constant

A::B
^     <- module_name
   ^  <- constant_name

Parameters:

  • module_name (TypeName)
  • constant_name (Symbol)

Returns:



68
69
70
# File 'sig/resolver/constant_resolver.rbs', line 68

def resolve_child(module_name, name)
  children(module_name)[name]
end