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

Sign up to get free protection for your applications and to get access to all the features.
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