Class: Steep::Services::CompletionProvider::TypeName

Inherits:
Object
  • Object
show all
Defined in:
lib/steep/services/completion_provider/type_name.rb

Defined Under Namespace

Modules: Prefix

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env:, context:, dirs:) ⇒ TypeName

Returns a new instance of TypeName.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/steep/services/completion_provider/type_name.rb', line 55

def initialize(env:, context:, dirs:)
  @env = env
  @context = context

  table = ::RBS::Environment::UseMap::Table.new()
  table.known_types.merge(env.class_decls.keys)
  table.known_types.merge(env.class_alias_decls.keys)
  table.known_types.merge(env.type_alias_decls.keys)
  table.known_types.merge(env.interface_decls.keys)
  table.compute_children

  @map = ::RBS::Environment::UseMap.new(table: table)
  dirs.each do |dir|
    case dir
    when ::RBS::AST::Directives::Use
      dir.clauses.each do |clause|
        @map.build_map(clause)
      end
    end
  end

  @type_name_resolver = ::RBS::Resolver::TypeNameResolver.build(env)
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



53
54
55
# File 'lib/steep/services/completion_provider/type_name.rb', line 53

def context
  @context
end

#envObject (readonly)

Returns the value of attribute env.



53
54
55
# File 'lib/steep/services/completion_provider/type_name.rb', line 53

def env
  @env
end

#mapObject (readonly)

Returns the value of attribute map.



53
54
55
# File 'lib/steep/services/completion_provider/type_name.rb', line 53

def map
  @map
end

#type_name_resolverObject (readonly)

Returns the value of attribute type_name_resolver.



53
54
55
# File 'lib/steep/services/completion_provider/type_name.rb', line 53

def type_name_resolver
  @type_name_resolver
end

Instance Method Details

#each_outer_module(context = self.context, &block) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/steep/services/completion_provider/type_name.rb', line 79

def each_outer_module(context = self.context, &block)
  if block
    if (parent, con = context)
      namespace = each_outer_module(parent, &block)
      case con
      when false
        namespace
      when ::RBS::TypeName
        ns = con.with_prefix(namespace).to_namespace
        yield(ns)
        ns
      end
    else
      yield(::RBS::Namespace.root)
      ::RBS::Namespace.root
    end
  else
    enum_for :each_outer_module
  end
end

#each_type_name(&block) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/steep/services/completion_provider/type_name.rb', line 100

def each_type_name(&block)
  if block
    env = self.env

    table = {} #: Hash[::RBS::Namespace, Array[::RBS::TypeName]]
    env.class_decls.each_key do |type_name|
      yield(type_name)
      (table[type_name.namespace] ||= []) << type_name
    end
    env.type_alias_decls.each_key do |type_name|
      yield(type_name)
      (table[type_name.namespace] ||= []) << type_name
    end
    env.interface_decls.each_key do |type_name|
      yield(type_name)
      (table[type_name.namespace] ||= []) << type_name
    end
    env.class_alias_decls.each_key do |type_name|
      yield(type_name)
      (table[type_name.namespace] ||= []) << type_name
    end

    env.class_alias_decls.each_key do |alias_name|
      normalized_name = env.normalize_module_name?(alias_name) or next
      each_type_name_under(alias_name, normalized_name, table: table, &block)
    end

    resolve_pairs = [] #: Array[[::RBS::TypeName, ::RBS::TypeName]]

    map.instance_eval do
      @map.each_key do |name|
        relative_name = ::RBS::TypeName.new(name: name, namespace: ::RBS::Namespace.empty)
        if absolute_name = resolve?(relative_name)
          if env.type_name?(absolute_name)
            # Yields only if the relative type name resolves to existing absolute type name
            resolve_pairs << [relative_name, absolute_name]
          end
        end
      end
    end

    resolve_pairs.each do |use_name, absolute_name|
      yield use_name
      each_type_name_under(use_name, absolute_name, table: table, &block)
    end
  else
    enum_for :each_type_name
  end
end

#each_type_name_under(module_name, normalized_name, table:, &block) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/steep/services/completion_provider/type_name.rb', line 150

def each_type_name_under(module_name, normalized_name, table:, &block)
  if children = table.fetch(normalized_name.to_namespace, nil)
    module_namespace = module_name.to_namespace

    children.each do |normalized_child_name|
      child_name = ::RBS::TypeName.new(namespace: module_namespace, name: normalized_child_name.name)

      yield child_name

      if normalized_child_name.class?
        each_type_name_under(child_name, env.normalize_module_name(normalized_child_name), table: table, &block)
      end
    end
  end
end

#find_type_names(prefix) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/steep/services/completion_provider/type_name.rb', line 211

def find_type_names(prefix)
  case prefix
  when Prefix::RawIdentPrefix
    each_type_name.filter do |type_name|
      type_name.split.any? {|sym| sym.to_s.downcase.include?(prefix.ident.downcase) }
    end
  when Prefix::NamespacedIdentPrefix
    absolute_namespace =
      if prefix.namespace.empty?
        ::RBS::Namespace.root
      else
        type_name_resolver.resolve(prefix.namespace.to_type_name, context: context)&.to_namespace || prefix.namespace
      end

    each_type_name.filter do|name|
      name.namespace == absolute_namespace &&
        name.name.to_s.downcase.include?(prefix.ident.downcase)
    end
  when Prefix::NamespacePrefix
    absolute_namespace = type_name_resolver.resolve(prefix.namespace.to_type_name, context: context)&.to_namespace || prefix.namespace
    each_type_name.filter {|name| name.namespace == absolute_namespace }
  else
    # Returns all of the accessible type names from the context
    namespaces = each_outer_module.to_set
    # Relative type name means a *use*d type name
    each_type_name.filter {|name| namespaces.include?(name.namespace) || !name.absolute? }
  end
end

#resolve_name_in_context(name) ⇒ Object



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/steep/services/completion_provider/type_name.rb', line 184

def resolve_name_in_context(name)
  if resolved_name = resolve_used_name(name)
    return [resolved_name, name]
  end

  name.absolute? or raise

  if normalized_name = env.normalize_type_name?(name)
    name.namespace.path.reverse_each.inject(::RBS::TypeName.new(namespace: ::RBS::Namespace.empty, name: name.name)) do |relative_name, component|
      if type_name_resolver.resolve(relative_name, context: context) == name
        return [normalized_name, relative_name]
      end

      ::RBS::TypeName.new(
        namespace: ::RBS::Namespace.new(path: [component, *relative_name.namespace.path], absolute: false),
        name: name.name
      )
    end

    if type_name_resolver.resolve(name.relative!, context: context) == name && !resolve_used_name(name.relative!)
      [normalized_name, name.relative!]
    else
      [normalized_name, name]
    end
  end
end

#resolve_used_name(name) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/steep/services/completion_provider/type_name.rb', line 166

def resolve_used_name(name)
  return nil if name.absolute?

  case
  when resolved = map.resolve?(name)
    resolved
  when name.namespace.empty?
    nil
  else
    if resolved_parent = resolve_used_name(name.namespace.to_type_name)
      resolved_name = ::RBS::TypeName.new(namespace: resolved_parent.to_namespace, name: name.name)
      if env.normalize_type_name?(resolved_name)
        resolved_name
      end
    end
  end
end