lib/rbs/environment.rb in rbs-3.0.0.dev.1 vs lib/rbs/environment.rb in rbs-3.0.0.dev.2
- old
+ new
@@ -4,19 +4,25 @@
class Environment
attr_reader :declarations
attr_reader :class_decls
attr_reader :interface_decls
- attr_reader :alias_decls
+ attr_reader :type_alias_decls
attr_reader :constant_decls
attr_reader :global_decls
+ attr_reader :class_alias_decls
+ attr_reader :buffer_directives
module ContextUtil
def calculate_context(decls)
- decls.each.with_object([Namespace.root]) do |decl, array|
- first = array.first or raise
- array.unshift(first + decl.name.to_namespace)
+ decls.inject(nil) do |context, decl| #$ Resolver::context
+ if (_, last = context)
+ last or raise
+ [context, last + decl.name]
+ else
+ [nil, decl.name.absolute!]
+ end
end
end
end
class MultiEntry
@@ -88,16 +94,10 @@
decls.first or raise("decls cannot be empty")
end
end
end
- def foo
- a = [1].sample()
- return unless a
- a + 1
- end
-
class ClassEntry < MultiEntry
def primary
@primary ||= begin
validate_type_params
decls.find {|d| d.decl.super_class } || decls.first or raise("decls cannot be empty")
@@ -117,57 +117,225 @@
end
include ContextUtil
def context
- @context = calculate_context(outer)
+ @context ||= calculate_context(outer)
end
end
+ class ModuleAliasEntry < SingleEntry
+ end
+
+ class ClassAliasEntry < SingleEntry
+ end
+
+ class InterfaceEntry < SingleEntry
+ end
+
+ class TypeAliasEntry < SingleEntry
+ end
+
+ class ConstantEntry < SingleEntry
+ end
+
+ class GlobalEntry < SingleEntry
+ end
+
def initialize
@buffers = []
@declarations = []
@class_decls = {}
@interface_decls = {}
- @alias_decls = {}
+ @type_alias_decls = {}
@constant_decls = {}
@global_decls = {}
+ @class_alias_decls = {}
+ @normalize_module_name_cache = {}
+ @buffer_directives = {}
end
def initialize_copy(other)
@buffers = other.buffers.dup
@declarations = other.declarations.dup
@class_decls = other.class_decls.dup
@interface_decls = other.interface_decls.dup
- @alias_decls = other.alias_decls.dup
+ @type_alias_decls = other.type_alias_decls.dup
@constant_decls = other.constant_decls.dup
@global_decls = other.global_decls.dup
+ @class_alias_decls = other.class_alias_decls.dup
+ @buffer_directives = other.buffer_directives.dup
end
def self.from_loader(loader)
self.new.tap do |env|
loader.load(env: env)
end
end
- def cache_name(cache, name:, decl:, outer:)
- if cache.key?(name)
- raise DuplicatedDeclarationError.new(_ = name, _ = decl, _ = cache[name].decl)
+ def interface_name?(name)
+ interface_decls.key?(name)
+ end
+
+ def type_alias_name?(name)
+ type_alias_decls.key?(name)
+ end
+
+ def module_name?(name)
+ class_decls.key?(name) || class_alias_decls.key?(name)
+ end
+
+ def type_name?(name)
+ interface_name?(name) ||
+ type_alias_name?(name) ||
+ module_name?(name)
+ end
+
+ def constant_name?(name)
+ constant_decl?(name) || module_name?(name)
+ end
+
+ def constant_decl?(name)
+ constant_decls.key?(name)
+ end
+
+ def class_decl?(name)
+ class_decls[name].is_a?(ClassEntry)
+ end
+
+ def module_decl?(name)
+ class_decls[name].is_a?(ModuleEntry)
+ end
+
+ def module_alias?(name)
+ if decl = class_alias_decls[name]
+ decl.decl.is_a?(AST::Declarations::ModuleAlias)
+ else
+ false
end
+ end
- cache[name] = SingleEntry.new(name: name, decl: decl, outer: outer)
+ def class_alias?(name)
+ if decl = class_alias_decls[name]
+ decl.decl.is_a?(AST::Declarations::ClassAlias)
+ else
+ false
+ end
end
+ def class_entry(type_name)
+ case
+ when (class_entry = class_decls[type_name]).is_a?(ClassEntry)
+ class_entry
+ when (class_alias = class_alias_decls[type_name]).is_a?(ClassAliasEntry)
+ class_alias
+ end
+ end
+
+ def module_entry(type_name)
+ case
+ when (module_entry = class_decls[type_name]).is_a?(ModuleEntry)
+ module_entry
+ when (module_alias = class_alias_decls[type_name]).is_a?(ModuleAliasEntry)
+ module_alias
+ end
+ end
+
+ def normalized_class_entry(type_name)
+ if name = normalize_module_name?(type_name)
+ case entry = class_entry(name)
+ when ClassEntry, nil
+ entry
+ when ClassAliasEntry
+ raise
+ end
+ end
+ end
+
+ def normalized_module_entry(type_name)
+ if name = normalize_module_name?(type_name)
+ case entry = module_entry(name)
+ when ModuleEntry, nil
+ entry
+ when ModuleAliasEntry
+ raise
+ end
+ end
+ end
+
+ def module_class_entry(type_name)
+ class_entry(type_name) || module_entry(type_name)
+ end
+
+ def normalized_module_class_entry(type_name)
+ normalized_class_entry(type_name) || normalized_module_entry(type_name)
+ end
+
+ def constant_entry(type_name)
+ class_entry(type_name) || module_entry(type_name) || constant_decls[type_name]
+ end
+
+ def normalize_module_name(name)
+ normalize_module_name?(name) or name
+ end
+
+ def normalize_module_name?(name)
+ raise "Class/module name is expected: #{name}" unless name.class?
+ name = name.absolute! if name.relative!
+
+ if @normalize_module_name_cache.key?(name)
+ return @normalize_module_name_cache[name]
+ end
+
+ @normalize_module_name_cache[name] = false
+
+ entry = constant_entry(name)
+ case entry
+ when ClassEntry, ModuleEntry
+ @normalize_module_name_cache[name] = entry.name
+ entry.name
+
+ when ClassAliasEntry, ModuleAliasEntry
+ old_name = entry.decl.old_name
+ if old_name.namespace.empty?
+ @normalize_module_name_cache[name] = normalize_module_name?(old_name)
+ else
+ parent = old_name.namespace.to_type_name
+
+ if normalized_parent = normalize_module_name?(parent)
+ @normalize_module_name_cache[name] =
+ if normalized_parent == parent
+ normalize_module_name?(old_name)
+ else
+ normalize_module_name?(
+ TypeName.new(name: old_name.name, namespace: normalized_parent.to_namespace)
+ )
+ end
+ else
+ @normalize_module_name_cache[name] = nil
+ end
+ end
+
+ when ConstantEntry
+ raise "#{name} is a constant name"
+
+ else
+ @normalize_module_name_cache[name] = nil
+ end
+ end
+
def insert_decl(decl, outer:, namespace:)
case decl
when AST::Declarations::Class, AST::Declarations::Module
name = decl.name.with_prefix(namespace)
- if constant_decls.key?(name)
- raise DuplicatedDeclarationError.new(name, decl, constant_decls[name].decl)
+ if cdecl = constant_entry(name)
+ if cdecl.is_a?(ConstantEntry) || cdecl.is_a?(ModuleAliasEntry) || cdecl.is_a?(ClassAliasEntry)
+ raise DuplicatedDeclarationError.new(name, decl, cdecl.decl)
+ end
end
unless class_decls.key?(name)
case decl
when AST::Declarations::Class
@@ -179,16 +347,12 @@
existing_entry = class_decls[name]
case
when decl.is_a?(AST::Declarations::Module) && existing_entry.is_a?(ModuleEntry)
- # @type var existing_entry: ModuleEntry
- # @type var decl: AST::Declarations::Module
existing_entry.insert(decl: decl, outer: outer)
when decl.is_a?(AST::Declarations::Class) && existing_entry.is_a?(ClassEntry)
- # @type var existing_entry: ClassEntry
- # @type var decl: AST::Declarations::Class
existing_entry.insert(decl: decl, outer: outer)
else
raise DuplicatedDeclarationError.new(name, decl, existing_entry.decls[0].decl)
end
@@ -197,95 +361,176 @@
decl.each_decl do |d|
insert_decl(d, outer: prefix, namespace: ns)
end
when AST::Declarations::Interface
- cache_name interface_decls, name: decl.name.with_prefix(namespace), decl: decl, outer: outer
+ name = decl.name.with_prefix(namespace)
- when AST::Declarations::Alias
- cache_name alias_decls, name: decl.name.with_prefix(namespace), decl: decl, outer: outer
+ if interface_entry = interface_decls[name]
+ DuplicatedDeclarationError.new(name, decl, interface_entry.decl)
+ end
+ interface_decls[name] = InterfaceEntry.new(name: name, decl: decl, outer: outer)
+
+ when AST::Declarations::TypeAlias
+ name = decl.name.with_prefix(namespace)
+
+ if entry = type_alias_decls[name]
+ DuplicatedDeclarationError.new(name, decl, entry.decl)
+ end
+
+ type_alias_decls[name] = TypeAliasEntry.new(name: name, decl: decl, outer: outer)
+
when AST::Declarations::Constant
name = decl.name.with_prefix(namespace)
- if class_decls.key?(name)
- raise DuplicatedDeclarationError.new(name, decl, class_decls[name].decls[0].decl)
+ if entry = constant_entry(name)
+ case entry
+ when ClassAliasEntry, ModuleAliasEntry, ConstantEntry
+ raise DuplicatedDeclarationError.new(name, decl, entry.decl)
+ when ClassEntry, ModuleEntry
+ raise DuplicatedDeclarationError.new(name, decl, *entry.decls.map(&:decl))
+ end
end
- cache_name constant_decls, name: name, decl: decl, outer: outer
+ constant_decls[name] = ConstantEntry.new(name: name, decl: decl, outer: outer)
when AST::Declarations::Global
- cache_name global_decls, name: decl.name, decl: decl, outer: outer
+ if entry = global_decls[decl.name]
+ raise DuplicatedDeclarationError.new(name, decl, entry.decl)
+ end
+
+ global_decls[decl.name] = GlobalEntry.new(name: decl.name, decl: decl, outer: outer)
+
+ when AST::Declarations::ClassAlias, AST::Declarations::ModuleAlias
+ name = decl.new_name.with_prefix(namespace)
+
+ if entry = constant_entry(name)
+ case entry
+ when ClassAliasEntry, ModuleAliasEntry, ConstantEntry
+ raise DuplicatedDeclarationError.new(name, decl, entry.decl)
+ when ClassEntry, ModuleEntry
+ raise DuplicatedDeclarationError.new(name, decl, *entry.decls.map(&:decl))
+ end
+ end
+
+ case decl
+ when AST::Declarations::ClassAlias
+ class_alias_decls[name] = ClassAliasEntry.new(name: name, decl: decl, outer: outer)
+ when AST::Declarations::ModuleAlias
+ class_alias_decls[name] = ModuleAliasEntry.new(name: name, decl: decl, outer: outer)
+ end
end
end
def <<(decl)
declarations << decl
insert_decl(decl, outer: [], namespace: Namespace.root)
self
end
+ def add_signature(buffer:, directives:, decls:)
+ buffer_directives[buffer] = directives
+ decls.each do |decl|
+ self << decl
+ end
+ end
+
def validate_type_params
class_decls.each_value do |decl|
decl.primary
end
end
def resolve_type_names(only: nil)
- resolver = TypeNameResolver.from_env(self)
- env = Environment.new()
+ resolver = Resolver::TypeNameResolver.new(self)
+ env = Environment.new
- declarations.each do |decl|
- if only && !only.member?(decl)
- env << decl
- else
- env << resolve_declaration(resolver, decl, outer: [], prefix: Namespace.root)
+ table = UseMap::Table.new()
+ table.known_types.merge(class_decls.keys)
+ table.known_types.merge(class_alias_decls.keys)
+ table.known_types.merge(type_alias_decls.keys)
+ table.known_types.merge(interface_decls.keys)
+ table.compute_children
+
+ buffers_decls.each do |buffer, decls|
+ dirs = buffer_directives.fetch(buffer)
+
+ map = UseMap.new(table: table)
+ dirs.each do |dir|
+ dir.clauses.each do |clause|
+ map.build_map(clause)
+ end
end
+
+ decls = decls.map do |decl|
+ if only && !only.member?(decl)
+ decl
+ else
+ resolve_declaration(resolver, map, decl, outer: [], prefix: Namespace.root)
+ end
+ end
+
+ env.add_signature(buffer: buffer, directives: dirs, decls: decls)
end
env
end
- def resolve_declaration(resolver, decl, outer:, prefix:)
+ def resolver_context(*nesting)
+ nesting.inject(nil) {|context, decl| #$ Resolver::context
+ append_context(context, decl)
+ }
+ end
+
+ def append_context(context, decl)
+ if (_, last = context)
+ last or raise
+ [context, last + decl.name]
+ else
+ [nil, decl.name.absolute!]
+ end
+ end
+
+ def resolve_declaration(resolver, map, decl, outer:, prefix:)
if decl.is_a?(AST::Declarations::Global)
# @type var decl: AST::Declarations::Global
return AST::Declarations::Global.new(
name: decl.name,
- type: absolute_type(resolver, decl.type, context: [Namespace.root]),
+ type: absolute_type(resolver, map, decl.type, context: nil),
location: decl.location,
comment: decl.comment
)
end
- context = (outer + [decl]).each.with_object([Namespace.root]) do |decl, array|
- head = array.first or raise
- array.unshift(head + decl.name.to_namespace)
- end
+ context = resolver_context(*outer)
- outer_context = context.drop(1)
-
case decl
when AST::Declarations::Class
+ outer_context = context
+ inner_context = append_context(outer_context, decl)
+
outer_ = outer + [decl]
prefix_ = prefix + decl.name.to_namespace
AST::Declarations::Class.new(
name: decl.name.with_prefix(prefix),
- type_params: resolve_type_params(resolver, decl.type_params, context: context),
+ type_params: resolve_type_params(resolver, map, decl.type_params, context: inner_context),
super_class: decl.super_class&.yield_self do |super_class|
AST::Declarations::Class::Super.new(
- name: absolute_type_name(resolver, super_class.name, context: outer_context),
- args: super_class.args.map {|type| absolute_type(resolver, type, context: outer_context) },
+ name: absolute_type_name(resolver, map, super_class.name, context: outer_context),
+ args: super_class.args.map {|type| absolute_type(resolver, map, type, context: outer_context) },
location: super_class.location
)
end,
members: decl.members.map do |member|
case member
when AST::Members::Base
- resolve_member(resolver, member, context: context)
+ resolve_member(resolver, map, member, context: inner_context)
when AST::Declarations::Base
resolve_declaration(
resolver,
+ map,
member,
outer: outer_,
prefix: prefix_
)
else
@@ -294,30 +539,35 @@
end,
location: decl.location,
annotations: decl.annotations,
comment: decl.comment
)
+
when AST::Declarations::Module
+ outer_context = context
+ inner_context = append_context(outer_context, decl)
+
outer_ = outer + [decl]
prefix_ = prefix + decl.name.to_namespace
AST::Declarations::Module.new(
name: decl.name.with_prefix(prefix),
- type_params: resolve_type_params(resolver, decl.type_params, context: context),
+ type_params: resolve_type_params(resolver, map, decl.type_params, context: inner_context),
self_types: decl.self_types.map do |module_self|
AST::Declarations::Module::Self.new(
- name: absolute_type_name(resolver, module_self.name, context: context),
- args: module_self.args.map {|type| absolute_type(resolver, type, context: context) },
+ name: absolute_type_name(resolver, map, module_self.name, context: inner_context),
+ args: module_self.args.map {|type| absolute_type(resolver, map, type, context: inner_context) },
location: module_self.location
)
end,
members: decl.members.map do |member|
case member
when AST::Members::Base
- resolve_member(resolver, member, context: context)
+ resolve_member(resolver, map, member, context: inner_context)
when AST::Declarations::Base
resolve_declaration(
resolver,
+ map,
member,
outer: outer_,
prefix: prefix_
)
else
@@ -326,50 +576,68 @@
end,
location: decl.location,
annotations: decl.annotations,
comment: decl.comment
)
+
when AST::Declarations::Interface
AST::Declarations::Interface.new(
name: decl.name.with_prefix(prefix),
- type_params: resolve_type_params(resolver, decl.type_params, context: context),
+ type_params: resolve_type_params(resolver, map, decl.type_params, context: context),
members: decl.members.map do |member|
- resolve_member(resolver, member, context: context)
+ resolve_member(resolver, map, member, context: context)
end,
comment: decl.comment,
location: decl.location,
annotations: decl.annotations
)
- when AST::Declarations::Alias
- AST::Declarations::Alias.new(
+
+ when AST::Declarations::TypeAlias
+ AST::Declarations::TypeAlias.new(
name: decl.name.with_prefix(prefix),
- type_params: resolve_type_params(resolver, decl.type_params, context: context),
- type: absolute_type(resolver, decl.type, context: context),
+ type_params: resolve_type_params(resolver, map, decl.type_params, context: context),
+ type: absolute_type(resolver, map, decl.type, context: context),
location: decl.location,
annotations: decl.annotations,
comment: decl.comment
)
when AST::Declarations::Constant
AST::Declarations::Constant.new(
name: decl.name.with_prefix(prefix),
- type: absolute_type(resolver, decl.type, context: context),
+ type: absolute_type(resolver, map, decl.type, context: context),
location: decl.location,
comment: decl.comment
)
+
+ when AST::Declarations::ClassAlias
+ AST::Declarations::ClassAlias.new(
+ new_name: decl.new_name.with_prefix(prefix),
+ old_name: absolute_type_name(resolver, map, decl.old_name, context: context),
+ location: decl.location,
+ comment: decl.comment
+ )
+
+ when AST::Declarations::ModuleAlias
+ AST::Declarations::ModuleAlias.new(
+ new_name: decl.new_name.with_prefix(prefix),
+ old_name: absolute_type_name(resolver, map, decl.old_name, context: context),
+ location: decl.location,
+ comment: decl.comment
+ )
end
end
- def resolve_member(resolver, member, context:)
+ def resolve_member(resolver, map, member, context:)
case member
when AST::Members::MethodDefinition
AST::Members::MethodDefinition.new(
name: member.name,
kind: member.kind,
overloads: member.overloads.map do |overload|
overload.update(
- method_type: resolve_method_type(resolver, overload.method_type, context: context)
+ method_type: resolve_method_type(resolver, map, overload.method_type, context: context)
)
end,
comment: member.comment,
overloading: member.overloading?,
annotations: member.annotations,
@@ -377,115 +645,116 @@
visibility: member.visibility
)
when AST::Members::AttrAccessor
AST::Members::AttrAccessor.new(
name: member.name,
- type: absolute_type(resolver, member.type, context: context),
+ type: absolute_type(resolver, map, member.type, context: context),
kind: member.kind,
annotations: member.annotations,
comment: member.comment,
location: member.location,
ivar_name: member.ivar_name,
visibility: member.visibility
)
when AST::Members::AttrReader
AST::Members::AttrReader.new(
name: member.name,
- type: absolute_type(resolver, member.type, context: context),
+ type: absolute_type(resolver, map, member.type, context: context),
kind: member.kind,
annotations: member.annotations,
comment: member.comment,
location: member.location,
ivar_name: member.ivar_name,
visibility: member.visibility
)
when AST::Members::AttrWriter
AST::Members::AttrWriter.new(
name: member.name,
- type: absolute_type(resolver, member.type, context: context),
+ type: absolute_type(resolver, map, member.type, context: context),
kind: member.kind,
annotations: member.annotations,
comment: member.comment,
location: member.location,
ivar_name: member.ivar_name,
visibility: member.visibility
)
when AST::Members::InstanceVariable
AST::Members::InstanceVariable.new(
name: member.name,
- type: absolute_type(resolver, member.type, context: context),
+ type: absolute_type(resolver, map, member.type, context: context),
comment: member.comment,
location: member.location
)
when AST::Members::ClassInstanceVariable
AST::Members::ClassInstanceVariable.new(
name: member.name,
- type: absolute_type(resolver, member.type, context: context),
+ type: absolute_type(resolver, map, member.type, context: context),
comment: member.comment,
location: member.location
)
when AST::Members::ClassVariable
AST::Members::ClassVariable.new(
name: member.name,
- type: absolute_type(resolver, member.type, context: context),
+ type: absolute_type(resolver, map, member.type, context: context),
comment: member.comment,
location: member.location
)
when AST::Members::Include
AST::Members::Include.new(
- name: absolute_type_name(resolver, member.name, context: context),
- args: member.args.map {|type| absolute_type(resolver, type, context: context) },
+ name: absolute_type_name(resolver, map, member.name, context: context),
+ args: member.args.map {|type| absolute_type(resolver, map, type, context: context) },
comment: member.comment,
location: member.location,
annotations: member.annotations
)
when AST::Members::Extend
AST::Members::Extend.new(
- name: absolute_type_name(resolver, member.name, context: context),
- args: member.args.map {|type| absolute_type(resolver, type, context: context) },
+ name: absolute_type_name(resolver, map, member.name, context: context),
+ args: member.args.map {|type| absolute_type(resolver, map, type, context: context) },
comment: member.comment,
location: member.location,
annotations: member.annotations
)
when AST::Members::Prepend
AST::Members::Prepend.new(
- name: absolute_type_name(resolver, member.name, context: context),
- args: member.args.map {|type| absolute_type(resolver, type, context: context) },
+ name: absolute_type_name(resolver, map, member.name, context: context),
+ args: member.args.map {|type| absolute_type(resolver, map, type, context: context) },
comment: member.comment,
location: member.location,
annotations: member.annotations
)
else
member
end
end
- def resolve_method_type(resolver, type, context:)
+ def resolve_method_type(resolver, map, type, context:)
type.map_type do |ty|
- absolute_type(resolver, ty, context: context)
+ absolute_type(resolver, map, ty, context: context)
end.map_type_bound do |bound|
- _ = absolute_type(resolver, bound, context: context)
+ _ = absolute_type(resolver, map, bound, context: context)
end
end
- def resolve_type_params(resolver, params, context:)
+ def resolve_type_params(resolver, map, params, context:)
params.map do |param|
- param.map_type {|type| _ = absolute_type(resolver, type, context: context) }
+ param.map_type {|type| _ = absolute_type(resolver, map, type, context: context) }
end
end
- def absolute_type_name(resolver, type_name, context:)
+ def absolute_type_name(resolver, map, type_name, context:)
+ type_name = map.resolve(type_name)
resolver.resolve(type_name, context: context) || type_name
end
- def absolute_type(resolver, type, context:)
+ def absolute_type(resolver, map, type, context:)
type.map_type_name do |name, _, _|
- absolute_type_name(resolver, name, context: context)
+ absolute_type_name(resolver, map, name, context: context)
end
end
def inspect
- ivars = %i[@declarations @class_decls @interface_decls @alias_decls @constant_decls @global_decls]
+ ivars = %i[@declarations @class_decls @class_alias_decls @interface_decls @type_alias_decls @constant_decls @global_decls]
"\#<RBS::Environment #{ivars.map { |iv| "#{iv}=(#{instance_variable_get(iv).size} items)"}.join(' ')}>"
end
def buffers
buffers_decls.keys.compact