rbs 3.0.0.dev.1 → 3.0.0.dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +0 -3
  3. data/CHANGELOG.md +28 -0
  4. data/Gemfile.lock +2 -2
  5. data/README.md +1 -0
  6. data/Rakefile +75 -1
  7. data/core/array.rbs +1 -1
  8. data/core/builtin.rbs +1 -1
  9. data/core/hash.rbs +1 -1
  10. data/core/module.rbs +1 -1
  11. data/ext/rbs_extension/constants.c +16 -2
  12. data/ext/rbs_extension/constants.h +8 -1
  13. data/ext/rbs_extension/extconf.rb +1 -1
  14. data/ext/rbs_extension/lexer.c +834 -777
  15. data/ext/rbs_extension/lexer.h +3 -1
  16. data/ext/rbs_extension/lexer.re +3 -1
  17. data/ext/rbs_extension/lexstate.c +4 -2
  18. data/ext/rbs_extension/parser.c +264 -44
  19. data/ext/rbs_extension/ruby_objs.c +56 -2
  20. data/ext/rbs_extension/ruby_objs.h +7 -1
  21. data/lib/rbs/annotate/rdoc_annotator.rb +1 -1
  22. data/lib/rbs/ast/declarations.rb +49 -2
  23. data/lib/rbs/ast/directives.rb +39 -0
  24. data/lib/rbs/cli.rb +32 -18
  25. data/lib/rbs/collection/config/lockfile_generator.rb +25 -20
  26. data/lib/rbs/collection/config.rb +2 -2
  27. data/lib/rbs/collection/sources/git.rb +1 -1
  28. data/lib/rbs/definition_builder/ancestor_builder.rb +24 -8
  29. data/lib/rbs/definition_builder.rb +8 -8
  30. data/lib/rbs/environment/use_map.rb +77 -0
  31. data/lib/rbs/environment.rb +352 -83
  32. data/lib/rbs/environment_loader.rb +9 -7
  33. data/lib/rbs/environment_walker.rb +1 -1
  34. data/lib/rbs/errors.rb +34 -37
  35. data/lib/rbs/locator.rb +1 -1
  36. data/lib/rbs/parser_aux.rb +8 -6
  37. data/lib/rbs/resolver/constant_resolver.rb +23 -7
  38. data/lib/rbs/resolver/type_name_resolver.rb +2 -1
  39. data/lib/rbs/sorter.rb +3 -3
  40. data/lib/rbs/test/setup.rb +1 -1
  41. data/lib/rbs/type_alias_dependency.rb +1 -1
  42. data/lib/rbs/type_alias_regularity.rb +3 -3
  43. data/lib/rbs/validator.rb +23 -2
  44. data/lib/rbs/variance_calculator.rb +2 -2
  45. data/lib/rbs/version.rb +1 -1
  46. data/lib/rbs/writer.rb +28 -2
  47. data/lib/rbs.rb +2 -2
  48. data/lib/rdoc_plugin/parser.rb +2 -2
  49. data/rbs.gemspec +1 -1
  50. data/sig/ancestor_graph.rbs +22 -2
  51. data/sig/collection/config/lockfile_generator.rbs +8 -10
  52. data/sig/collection/config.rbs +1 -1
  53. data/sig/collection/sources.rbs +12 -6
  54. data/sig/constant.rbs +1 -1
  55. data/sig/declarations.rbs +36 -3
  56. data/sig/definition.rbs +1 -1
  57. data/sig/definition_builder.rbs +0 -1
  58. data/sig/directives.rbs +61 -0
  59. data/sig/environment.rbs +150 -28
  60. data/sig/environment_loader.rbs +1 -1
  61. data/sig/errors.rbs +22 -1
  62. data/sig/parser.rbs +8 -15
  63. data/sig/resolver/constant_resolver.rbs +1 -2
  64. data/sig/shims/bundler.rbs +18 -0
  65. data/sig/shims/rubygems.rbs +6 -0
  66. data/sig/use_map.rbs +35 -0
  67. data/sig/validator.rbs +12 -5
  68. data/sig/writer.rbs +4 -2
  69. metadata +7 -9
  70. data/lib/rbs/constant_table.rb +0 -167
  71. data/lib/rbs/type_name_resolver.rb +0 -67
  72. data/sig/constant_table.rbs +0 -30
  73. data/sig/type_name_resolver.rbs +0 -26
  74. data/steep/Gemfile +0 -3
  75. data/steep/Gemfile.lock +0 -61
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBS
4
+ module AST
5
+ module Directives
6
+ class Base
7
+ end
8
+
9
+ class Use < Base
10
+ class SingleClause
11
+ attr_reader :type_name, :new_name, :location
12
+
13
+ def initialize(type_name:, new_name:, location:)
14
+ @type_name = type_name
15
+ @new_name = new_name
16
+ @location = location
17
+ end
18
+ end
19
+
20
+ class WildcardClause
21
+ attr_reader :namespace, :location
22
+
23
+ def initialize(namespace:, location:)
24
+ @location = location
25
+ @namespace = namespace
26
+ end
27
+ end
28
+
29
+ attr_reader :clauses, :location
30
+
31
+ def initialize(clauses:, location:)
32
+ @clauses = clauses
33
+ @location = location
34
+ end
35
+ end
36
+
37
+ end
38
+ end
39
+ end
data/lib/rbs/cli.rb CHANGED
@@ -438,15 +438,15 @@ EOU
438
438
  env = Environment.from_loader(loader).resolve_type_names
439
439
 
440
440
  builder = DefinitionBuilder.new(env: env)
441
- validator = Validator.new(env: env, resolver: TypeNameResolver.from_env(env))
441
+ validator = Validator.new(env: env, resolver: Resolver::TypeNameResolver.new(env))
442
442
 
443
443
  env.class_decls.each do |name, decl|
444
444
  stdout.puts "Validating class/module definition: `#{name}`..."
445
445
  builder.build_instance(name).each_type do |type|
446
- validator.validate_type type, context: [Namespace.root]
446
+ validator.validate_type type, context: nil
447
447
  end
448
448
  builder.build_singleton(name).each_type do |type|
449
- validator.validate_type type, context: [Namespace.root]
449
+ validator.validate_type type, context: nil
450
450
  end
451
451
 
452
452
  d = decl.primary.decl
@@ -467,10 +467,15 @@ EOU
467
467
  end
468
468
  end
469
469
 
470
+ env.class_alias_decls.each do |name, entry|
471
+ stdout.puts "Validating class/module alias definition: `#{name}`..."
472
+ validator.validate_class_alias(entry: entry)
473
+ end
474
+
470
475
  env.interface_decls.each do |name, decl|
471
476
  stdout.puts "Validating interface: `#{name}`..."
472
477
  builder.build_interface(name).each_type do |type|
473
- validator.validate_type type, context: [Namespace.root]
478
+ validator.validate_type type, context: nil
474
479
  end
475
480
 
476
481
  validator.validate_type_params(
@@ -495,13 +500,13 @@ EOU
495
500
 
496
501
  env.global_decls.each do |name, global|
497
502
  stdout.puts "Validating global: `#{name}`..."
498
- validator.validate_type global.decl.type, context: [Namespace.root]
503
+ validator.validate_type global.decl.type, context: nil
499
504
  end
500
505
 
501
- env.alias_decls.each do |name, decl|
506
+ env.type_alias_decls.each do |name, decl|
502
507
  stdout.puts "Validating alias: `#{name}`..."
503
508
  builder.expand_alias1(name).tap do |type|
504
- validator.validate_type type, context: [Namespace.root]
509
+ validator.validate_type type, context: nil
505
510
  end
506
511
  validator.validate_type_alias(entry: decl)
507
512
  end
@@ -537,14 +542,26 @@ EOU
537
542
  env = Environment.from_loader(loader).resolve_type_names
538
543
 
539
544
  builder = DefinitionBuilder.new(env: env)
540
- table = ConstantTable.new(builder: builder)
545
+ resolver = Resolver::ConstantResolver.new(builder: builder)
541
546
 
542
- namespace = context ? Namespace.parse(context).absolute! : Namespace.root
543
- stdout.puts "Context: #{namespace}"
544
- name = Namespace.parse(args[0]).to_type_name
545
- stdout.puts "Constant name: #{name}"
547
+ resolver_context = context ? [nil, TypeName(context).absolute!] : nil #: Resolver::context
548
+ stdout.puts "Context: #{context}"
549
+ const_name = TypeName(args[0])
550
+ stdout.puts "Constant name: #{const_name}"
551
+
552
+ if const_name.absolute?
553
+ constant = resolver.table.constant(const_name)
554
+ else
555
+ head, *components = const_name.to_namespace.path
556
+ head or raise
546
557
 
547
- constant = table.resolve_constant_reference(name, context: namespace.ascend.to_a)
558
+ constant = resolver.resolve(head, context: resolver_context)
559
+ constant = components.inject(constant) do |const, component|
560
+ if const
561
+ resolver.resolve_child(const.name, component)
562
+ end
563
+ end
564
+ end
548
565
 
549
566
  if constant
550
567
  stdout.puts " => #{constant.name}: #{constant.type}"
@@ -1043,15 +1060,12 @@ EOB
1043
1060
  case args[0]
1044
1061
  when 'install'
1045
1062
  unless params[:frozen]
1046
- gemfile_lock_path = Bundler.default_lockfile
1047
- Collection::Config.generate_lockfile(config_path: config_path, gemfile_lock_path: gemfile_lock_path)
1063
+ Collection::Config.generate_lockfile(config_path: config_path, definition: Bundler.definition)
1048
1064
  end
1049
1065
  Collection::Installer.new(lockfile_path: lock_path, stdout: stdout).install_from_lockfile
1050
1066
  when 'update'
1051
- gemfile_lock_path = Bundler.default_lockfile
1052
-
1053
1067
  # TODO: Be aware of argv to update only specified gem
1054
- Collection::Config.generate_lockfile(config_path: config_path, gemfile_lock_path: gemfile_lock_path, with_lockfile: false)
1068
+ Collection::Config.generate_lockfile(config_path: config_path, definition: Bundler.definition, with_lockfile: false)
1055
1069
  Collection::Installer.new(lockfile_path: lock_path, stdout: stdout).install_from_lockfile
1056
1070
  when 'init'
1057
1071
  if config_path.exist?
@@ -20,15 +20,15 @@ module RBS
20
20
  end
21
21
  end
22
22
 
23
- attr_reader :config, :lockfile, :gemfile_lock, :existing_lockfile
23
+ attr_reader :config, :lockfile, :definition, :existing_lockfile, :gem_hash
24
24
 
25
- def self.generate(config:, gemfile_lock_path:, with_lockfile: true)
26
- generator = new(config: config, gemfile_lock_path: gemfile_lock_path, with_lockfile: with_lockfile)
25
+ def self.generate(config:, definition:, with_lockfile: true)
26
+ generator = new(config: config, definition: definition, with_lockfile: with_lockfile)
27
27
  generator.generate
28
28
  generator.lockfile
29
29
  end
30
30
 
31
- def initialize(config:, gemfile_lock_path:, with_lockfile:)
31
+ def initialize(config:, definition:, with_lockfile:)
32
32
  @config = config
33
33
 
34
34
  lockfile_path = Config.to_lockfile_path(config.config_path)
@@ -37,7 +37,7 @@ module RBS
37
37
  @lockfile = Lockfile.new(
38
38
  lockfile_path: lockfile_path,
39
39
  path: config.repo_path_data,
40
- gemfile_lock_path: gemfile_lock_path.relative_path_from(lockfile_dir)
40
+ gemfile_lock_path: definition.lockfile.relative_path_from(lockfile_dir)
41
41
  )
42
42
  config.sources.each do |source|
43
43
  case source
@@ -48,10 +48,13 @@ module RBS
48
48
 
49
49
  if with_lockfile && lockfile_path.file?
50
50
  @existing_lockfile = Lockfile.from_lockfile(lockfile_path: lockfile_path, data: YAML.load_file(lockfile_path.to_s))
51
- validate_gemfile_lock_path!(lock: @existing_lockfile, gemfile_lock_path: gemfile_lock_path)
51
+ validate_gemfile_lock_path!(lock: @existing_lockfile, gemfile_lock_path: definition.lockfile)
52
52
  end
53
53
 
54
- @gemfile_lock = Bundler::LockfileParser.new(gemfile_lock_path.read)
54
+ @definition = definition
55
+ @gem_hash = definition.locked_gems.specs.each.with_object({}) do |spec, hash| #$ Hash[String, Bundler::LazySpecification]
56
+ hash[spec.name] = spec
57
+ end
55
58
  end
56
59
 
57
60
  def generate
@@ -67,8 +70,13 @@ module RBS
67
70
  end
68
71
  end
69
72
 
70
- gemfile_lock_gems do |spec|
71
- assign_gem(name: spec.name, version: spec.version, ignored_gems: ignored_gems, src_data: nil)
73
+ definition.dependencies.each do |dep|
74
+ if dep.autorequire && dep.autorequire.empty?
75
+ next
76
+ end
77
+
78
+ spec = gem_hash[dep.name] or raise "Cannot find `#{dep.name}` in bundler context"
79
+ assign_gem(name: dep.name, version: spec.version, ignored_gems: ignored_gems, src_data: nil)
72
80
  end
73
81
 
74
82
  lockfile.lockfile_path.write(YAML.dump(lockfile.to_lockfile))
@@ -82,7 +90,7 @@ module RBS
82
90
  end
83
91
  end
84
92
 
85
- private def assign_gem(name:, version:, ignored_gems:, src_data:)
93
+ private def assign_gem(name:, version:, src_data:, ignored_gems:)
86
94
  return if ignored_gems.include?(name)
87
95
  return if lockfile.gems.key?(name)
88
96
 
@@ -99,9 +107,8 @@ module RBS
99
107
  if src_data
100
108
  Sources.from_config_entry(src_data)
101
109
  else
102
- find_source(name: name)
110
+ find_source(name: name) or return
103
111
  end
104
- return unless source
105
112
 
106
113
  installed_version = version
107
114
  best_version = find_best_version(version: installed_version, versions: source.versions(name))
@@ -116,11 +123,15 @@ module RBS
116
123
  locked or raise
117
124
 
118
125
  lockfile.gems[name] = locked
119
- source = locked[:source]
120
126
 
121
- source.dependencies_of(locked[:name], locked[:version])&.each do |dep|
127
+ locked[:source].dependencies_of(locked[:name], locked[:version])&.each do |dep|
122
128
  assign_stdlib(name: dep["name"], from_gem: name)
123
129
  end
130
+
131
+ gem_hash[name].dependencies.each do |dep|
132
+ spec = gem_hash[dep.name]
133
+ assign_gem(name: dep.name, version: spec.version, src_data: nil, ignored_gems: ignored_gems)
134
+ end
124
135
  end
125
136
 
126
137
  private def assign_stdlib(name:, from_gem:)
@@ -150,12 +161,6 @@ module RBS
150
161
  end
151
162
  end
152
163
 
153
- private def gemfile_lock_gems(&block)
154
- gemfile_lock.specs.each do |spec|
155
- yield spec
156
- end
157
- end
158
-
159
164
  private def find_source(name:)
160
165
  sources = config.sources
161
166
 
@@ -31,9 +31,9 @@ module RBS
31
31
 
32
32
  # Generate a rbs lockfile from Gemfile.lock to `config_path`.
33
33
  # If `with_lockfile` is true, it respects existing rbs lockfile.
34
- def self.generate_lockfile(config_path:, gemfile_lock_path:, with_lockfile: true)
34
+ def self.generate_lockfile(config_path:, definition:, with_lockfile: true)
35
35
  config = from_path(config_path)
36
- lockfile = LockfileGenerator.generate(config: config, gemfile_lock_path: gemfile_lock_path, with_lockfile: with_lockfile)
36
+ lockfile = LockfileGenerator.generate(config: config, definition: definition, with_lockfile: with_lockfile)
37
37
 
38
38
  [config, lockfile]
39
39
  end
@@ -171,7 +171,7 @@ module RBS
171
171
  if commit_hash?
172
172
  revision
173
173
  else
174
- setup! { git('rev-parse', revision).chomp }
174
+ setup! { git('rev-parse', "refs/remotes/origin/#{revision}").chomp }
175
175
  end
176
176
  end
177
177
  end
@@ -190,6 +190,8 @@ module RBS
190
190
  end
191
191
 
192
192
  def one_instance_ancestors(type_name)
193
+ type_name = env.normalize_module_name(type_name)
194
+
193
195
  as = one_instance_ancestors_cache[type_name] and return as
194
196
 
195
197
  entry = env.class_decls[type_name] or raise "Unknown name for one_instance_ancestors: #{type_name}"
@@ -210,6 +212,8 @@ module RBS
210
212
  super_args = []
211
213
  end
212
214
 
215
+ super_name = env.normalize_module_name(super_name)
216
+
213
217
  NoSuperclassFoundError.check!(super_name, env: env, location: primary.decl.location)
214
218
  if super_class
215
219
  InheritModuleError.check!(super_class, env: env)
@@ -236,7 +240,12 @@ module RBS
236
240
  else
237
241
  entry.self_types.each do |module_self|
238
242
  NoSelfTypeFoundError.check!(module_self, env: env)
239
- self_types.push Definition::Ancestor::Instance.new(name: module_self.name, args: module_self.args, source: module_self)
243
+
244
+ module_name = module_self.name
245
+ if module_name.class?
246
+ module_name = env.normalize_module_name(module_name)
247
+ end
248
+ self_types.push Definition::Ancestor::Instance.new(name: module_name, args: module_self.args, source: module_self)
240
249
  end
241
250
  end
242
251
  end
@@ -253,6 +262,7 @@ module RBS
253
262
  end
254
263
 
255
264
  def one_singleton_ancestors(type_name)
265
+ type_name = env.normalize_module_name(type_name)
256
266
  as = one_singleton_ancestors_cache[type_name] and return as
257
267
 
258
268
  entry = env.class_decls[type_name] or raise "Unknown name for one_singleton_ancestors: #{type_name}"
@@ -270,6 +280,8 @@ module RBS
270
280
  super_name = BuiltinNames::Object.name
271
281
  end
272
282
 
283
+ super_name = env.normalize_module_name(super_name)
284
+
273
285
  NoSuperclassFoundError.check!(super_name, env: env, location: primary.decl.location)
274
286
  if super_class
275
287
  InheritModuleError.check!(super_class, env: env)
@@ -328,16 +340,18 @@ module RBS
328
340
  when AST::Members::Include
329
341
  module_name = member.name
330
342
  module_args = member.args.map {|type| align_params ? type.sub(align_params) : type }
331
- ancestor = Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
332
343
 
333
344
  case
334
345
  when member.name.class? && included_modules
335
346
  MixinClassError.check!(type_name: type_name, env: env, member: member)
336
347
  NoMixinFoundError.check!(member.name, env: env, member: member)
337
- included_modules << ancestor
348
+
349
+ module_name = env.normalize_module_name(module_name)
350
+ included_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
338
351
  when member.name.interface? && included_interfaces
339
352
  NoMixinFoundError.check!(member.name, env: env, member: member)
340
- included_interfaces << ancestor
353
+
354
+ included_interfaces << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
341
355
  end
342
356
 
343
357
  when AST::Members::Prepend
@@ -345,7 +359,7 @@ module RBS
345
359
  MixinClassError.check!(type_name: type_name, env: env, member: member)
346
360
  NoMixinFoundError.check!(member.name, env: env, member: member)
347
361
 
348
- module_name = member.name
362
+ module_name = env.normalize_module_name(member.name)
349
363
  module_args = member.args.map {|type| align_params ? type.sub(align_params) : type }
350
364
 
351
365
  prepended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
@@ -354,16 +368,18 @@ module RBS
354
368
  when AST::Members::Extend
355
369
  module_name = member.name
356
370
  module_args = member.args
357
- ancestor = Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
358
371
 
359
372
  case
360
373
  when member.name.class? && extended_modules
361
374
  MixinClassError.check!(type_name: type_name, env: env, member: member)
362
375
  NoMixinFoundError.check!(member.name, env: env, member: member)
363
- extended_modules << ancestor
376
+
377
+ module_name = env.normalize_module_name(module_name)
378
+ extended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
364
379
  when member.name.interface? && extended_interfaces
365
380
  NoMixinFoundError.check!(member.name, env: env, member: member)
366
- extended_interfaces << ancestor
381
+
382
+ extended_interfaces << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
367
383
  end
368
384
  end
369
385
  end
@@ -3,7 +3,6 @@
3
3
  module RBS
4
4
  class DefinitionBuilder
5
5
  attr_reader :env
6
- attr_reader :type_name_resolver
7
6
  attr_reader :ancestor_builder
8
7
  attr_reader :method_builder
9
8
 
@@ -14,7 +13,6 @@ module RBS
14
13
 
15
14
  def initialize(env:, ancestor_builder: nil, method_builder: nil)
16
15
  @env = env
17
- @type_name_resolver = TypeNameResolver.from_env(env)
18
16
  @ancestor_builder = ancestor_builder || AncestorBuilder.new(env: env)
19
17
  @method_builder = method_builder || MethodBuilder.new(env: env)
20
18
 
@@ -72,7 +70,7 @@ module RBS
72
70
  entry = env.interface_decls[name] or raise "Unknown interface name: #{name}"
73
71
  entry.decl.type_params
74
72
  when name.alias?
75
- entry = env.alias_decls[name] or raise "Unknown alias name: #{name}"
73
+ entry = env.type_alias_decls[name] or raise "Unknown alias name: #{name}"
76
74
  entry.decl.type_params
77
75
  when name.class?
78
76
  entry = env.class_decls[name] or raise "Unknown module name: #{name}"
@@ -150,6 +148,8 @@ module RBS
150
148
  end
151
149
 
152
150
  def build_instance(type_name)
151
+ type_name = env.normalize_module_name(type_name)
152
+
153
153
  try_cache(type_name, cache: instance_cache) do
154
154
  entry = env.class_decls[type_name] or raise "Unknown name for build_instance: #{type_name}"
155
155
  ensure_namespace!(type_name.namespace, location: entry.decls[0].decl.location)
@@ -278,6 +278,8 @@ module RBS
278
278
  end
279
279
 
280
280
  def build_singleton(type_name)
281
+ type_name = env.normalize_module_name(type_name)
282
+
281
283
  try_cache type_name, cache: singleton_cache do
282
284
  entry = env.class_decls[type_name] or raise "Unknown name for build_singleton: #{type_name}"
283
285
  ensure_namespace!(type_name.namespace, location: entry.decls[0].decl.location)
@@ -743,13 +745,13 @@ module RBS
743
745
  end
744
746
 
745
747
  def expand_alias1(type_name)
746
- entry = env.alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
748
+ entry = env.type_alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
747
749
  as = entry.decl.type_params.each.map { Types::Bases::Any.new(location: nil) }
748
750
  expand_alias2(type_name, as)
749
751
  end
750
752
 
751
753
  def expand_alias2(type_name, args)
752
- entry = env.alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
754
+ entry = env.type_alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
753
755
 
754
756
  ensure_namespace!(type_name.namespace, location: entry.decl.location)
755
757
  params = entry.decl.type_params.each.map(&:name)
@@ -803,9 +805,7 @@ module RBS
803
805
  def validate_type_name(name, location)
804
806
  name = name.absolute!
805
807
 
806
- return if name.class? && env.class_decls.key?(name)
807
- return if name.interface? && env.interface_decls.key?(name)
808
- return if name.alias? && env.alias_decls.key?(name)
808
+ return if env.type_name?(name)
809
809
 
810
810
  raise NoTypeFoundError.new(type_name: name, location: location)
811
811
  end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBS
4
+ class Environment
5
+ class UseMap
6
+ class Table
7
+ attr_reader :known_types, :children
8
+
9
+ def initialize
10
+ @known_types = Set[]
11
+ @children = {}
12
+ end
13
+
14
+ def compute_children
15
+ children.clear
16
+
17
+ known_types.each do |type|
18
+ unless type.namespace.empty?
19
+ children[type.namespace] ||= Set[]
20
+ children[type.namespace] << type
21
+ end
22
+ end
23
+
24
+ self
25
+ end
26
+ end
27
+
28
+ attr_reader :use_dirs
29
+
30
+ def initialize(table:)
31
+ @use_dirs = []
32
+ @map = {}
33
+ @table = table
34
+ end
35
+
36
+ def build_map(clause)
37
+ case clause
38
+ when AST::Directives::Use::SingleClause
39
+ if clause.new_name
40
+ @map[clause.new_name] = clause.type_name.absolute!
41
+ else
42
+ @map[clause.type_name.name] = clause.type_name.absolute!
43
+ end
44
+ when AST::Directives::Use::WildcardClause
45
+ @table.children.fetch(clause.namespace.absolute!).each do |child|
46
+ @map[child.name] = child
47
+ end
48
+ end
49
+
50
+ self
51
+ end
52
+
53
+ def resolve?(type_name)
54
+ return if type_name.absolute?
55
+
56
+ hd, *tl = type_name.namespace.path
57
+
58
+ if hd
59
+ # namespace is not empty
60
+ if tn = @map[hd]
61
+ path = [*tn.namespace.path, tn.name, *tl]
62
+ TypeName.new(
63
+ namespace: Namespace.new(absolute: true, path: path),
64
+ name: type_name.name
65
+ )
66
+ end
67
+ else
68
+ @map[type_name.name]
69
+ end
70
+ end
71
+
72
+ def resolve(type_name)
73
+ resolve?(type_name) || type_name
74
+ end
75
+ end
76
+ end
77
+ end