Skip to content

Commit 6f4e8c5

Browse files
authored
Merge pull request #1394 from ruby/backport-type-name-normalization
Backport type name normalization
2 parents 2995ca3 + 62f61ac commit 6f4e8c5

22 files changed

Lines changed: 609 additions & 109 deletions

lib/rbs/definition_builder.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -753,12 +753,14 @@ def expand_alias(type_name)
753753
end
754754

755755
def expand_alias1(type_name)
756+
type_name = env.normalize_type_name(type_name)
756757
entry = env.type_alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
757758
as = entry.decl.type_params.each.map { Types::Bases::Any.new(location: nil) }
758759
expand_alias2(type_name, as)
759760
end
760761

761762
def expand_alias2(type_name, args)
763+
type_name = env.normalize_type_name(type_name)
762764
entry = env.type_alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
763765

764766
ensure_namespace!(type_name.namespace, location: entry.decl.location)
@@ -811,9 +813,8 @@ def validate_type_presence(type)
811813
end
812814

813815
def validate_type_name(name, location)
814-
name = name.absolute!
815-
816-
return if env.type_name?(name)
816+
name = name.absolute! unless name.absolute?
817+
return if env.type_name?(env.normalize_type_name(name))
817818

818819
raise NoTypeFoundError.new(type_name: name, location: location)
819820
end

lib/rbs/environment.rb

Lines changed: 73 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -275,53 +275,96 @@ def constant_entry(type_name)
275275
class_entry(type_name) || module_entry(type_name) || constant_decls[type_name]
276276
end
277277

278+
def normalize_type_name?(name)
279+
if name.class?
280+
normalize_module_name?(name)
281+
else
282+
unless name.namespace.empty?
283+
parent = name.namespace.to_type_name
284+
parent = normalize_module_name?(parent)
285+
return parent unless parent
286+
287+
TypeName.new(namespace: parent.to_namespace, name: name.name)
288+
else
289+
name
290+
end
291+
end
292+
end
293+
294+
def normalize_type_name!(name)
295+
result = normalize_type_name?(name)
296+
297+
case result
298+
when TypeName
299+
result
300+
when false
301+
raise "Type name `#{name}` cannot be normalized because it's a cyclic definition"
302+
when nil
303+
raise "Type name `#{name}` cannot be normalized because of unknown type name in the path"
304+
end
305+
end
306+
307+
def normalized_type_name?(type_name)
308+
case
309+
when type_name.interface?
310+
interface_decls.key?(type_name)
311+
when type_name.class?
312+
class_decls.key?(type_name)
313+
when type_name.alias?
314+
type_alias_decls.key?(type_name)
315+
else
316+
false
317+
end
318+
end
319+
320+
def normalized_type_name!(name)
321+
normalized_type_name?(name) or raise "Normalized type name is expected but given `#{name}`, which is normalized to `#{normalize_type_name?(name)}`"
322+
name
323+
end
324+
325+
def normalize_type_name(name)
326+
normalize_type_name?(name) || name
327+
end
328+
278329
def normalize_module_name(name)
279330
normalize_module_name?(name) or name
280331
end
281332

282333
def normalize_module_name?(name)
283334
raise "Class/module name is expected: #{name}" unless name.class?
284-
name = name.absolute! if name.relative!
335+
name = name.absolute! unless name.absolute?
285336

286337
if @normalize_module_name_cache.key?(name)
287338
return @normalize_module_name_cache[name]
288339
end
289340

341+
unless name.namespace.empty?
342+
parent = name.namespace.to_type_name
343+
if normalized_parent = normalize_module_name?(parent)
344+
type_name = TypeName.new(namespace: normalized_parent.to_namespace, name: name.name)
345+
else
346+
@normalize_module_name_cache[name] = nil
347+
return
348+
end
349+
else
350+
type_name = name
351+
end
352+
290353
@normalize_module_name_cache[name] = false
291354

292-
entry = constant_entry(name)
293-
case entry
294-
when ClassEntry, ModuleEntry
295-
@normalize_module_name_cache[name] = entry.name
296-
entry.name
355+
entry = constant_entry(type_name)
297356

298-
when ClassAliasEntry, ModuleAliasEntry
299-
old_name = entry.decl.old_name
300-
if old_name.namespace.empty?
301-
@normalize_module_name_cache[name] = normalize_module_name?(old_name)
357+
normalized_type_name =
358+
case entry
359+
when ClassEntry, ModuleEntry
360+
type_name
361+
when ClassAliasEntry, ModuleAliasEntry
362+
normalize_module_name?(entry.decl.old_name)
302363
else
303-
parent = old_name.namespace.to_type_name
304-
305-
if normalized_parent = normalize_module_name?(parent)
306-
@normalize_module_name_cache[name] =
307-
if normalized_parent == parent
308-
normalize_module_name?(old_name)
309-
else
310-
normalize_module_name?(
311-
TypeName.new(name: old_name.name, namespace: normalized_parent.to_namespace)
312-
)
313-
end
314-
else
315-
@normalize_module_name_cache[name] = nil
316-
end
364+
nil
317365
end
318366

319-
when ConstantEntry
320-
raise "#{name} is a constant name"
321-
322-
else
323-
@normalize_module_name_cache[name] = nil
324-
end
367+
@normalize_module_name_cache[name] = normalized_type_name
325368
end
326369

327370
def insert_decl(decl, outer:, namespace:)

lib/rbs/errors.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ def location
185185
end
186186

187187
def self.check!(super_decl, env:)
188-
return if env.class_decl?(super_decl.name) || env.class_alias?(super_decl.name)
188+
super_name = env.normalize_type_name(super_decl.name)
189+
return if env.class_decl?(super_name) || env.class_alias?(super_name)
189190

190191
raise new(super_decl)
191192
end
@@ -205,9 +206,8 @@ def initialize(type_name:, location:)
205206
end
206207

207208
def self.check!(self_type, env:)
208-
type_name = self_type.name
209-
210-
(env.module_name?(type_name) || env.interface_name?(type_name)) or raise new(type_name: type_name, location: self_type.location)
209+
self_name = env.normalize_type_name(self_type.name)
210+
(env.module_name?(self_name) || env.interface_name?(self_name)) or raise new(type_name: self_type.name, location: self_type.location)
211211
end
212212
end
213213

lib/rbs/resolver/type_name_resolver.rb

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ module Resolver
55
class TypeNameResolver
66
attr_reader :all_names
77
attr_reader :cache
8+
attr_reader :env
89

910
def initialize(env)
1011
@all_names = Set[]
1112
@cache = {}
13+
@env = env
1214

1315
all_names.merge(env.class_decls.keys)
1416
all_names.merge(env.interface_decls.keys)
@@ -29,22 +31,53 @@ def resolve(type_name, context:)
2931
end
3032

3133
try_cache([type_name, context]) do
32-
resolve_in(type_name, context)
34+
head, tail = partition(type_name)
35+
36+
head = resolve_in(head, context)
37+
38+
if head
39+
if tail
40+
absolute_name = tail.with_prefix(head.to_namespace)
41+
if env.normalize_type_name?(absolute_name)
42+
absolute_name
43+
end
44+
else
45+
head
46+
end
47+
end
48+
end
49+
end
50+
51+
def partition(type_name)
52+
if type_name.namespace.empty?
53+
head = type_name.name
54+
tail = nil
55+
else
56+
head, *tail = type_name.namespace.path
57+
58+
head or raise
59+
60+
tail = TypeName.new(
61+
name: type_name.name,
62+
namespace: Namespace.new(absolute: false, path: tail)
63+
)
3364
end
65+
66+
[head, tail]
3467
end
3568

36-
def resolve_in(type_name, context)
69+
def resolve_in(head, context)
3770
if context
3871
parent, child = context
3972
case child
4073
when false
41-
resolve_in(type_name, parent)
74+
resolve_in(head, parent)
4275
when TypeName
43-
name = type_name.with_prefix(child.to_namespace)
44-
has_name?(name) || resolve_in(type_name, parent)
76+
name = TypeName.new(name: head, namespace: child.to_namespace)
77+
has_name?(name) || resolve_in(head, parent)
4578
end
4679
else
47-
has_name?(type_name.absolute!)
80+
has_name?(TypeName.new(name: head, namespace: Namespace.root))
4881
end
4982
end
5083

lib/rbs/type_alias_dependency.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def circular_definition?(alias_name)
2020
# Construct transitive closure, if not constructed already
2121
transitive_closure() unless @dependencies
2222

23-
# Check for recursive type alias
23+
alias_name = env.normalize_type_name!(alias_name)
2424
@dependencies[alias_name][alias_name]
2525
end
2626

@@ -49,6 +49,16 @@ def transitive_closure
4949
end
5050
end
5151

52+
def direct_dependencies_of(name)
53+
name = env.normalize_type_name!(name)
54+
@direct_dependencies[name]
55+
end
56+
57+
def dependencies_of(name)
58+
name = env.normalize_type_name!(name)
59+
@dependencies[name].each_key.to_set
60+
end
61+
5262
private
5363

5464
# Constructs directed graph recursively
@@ -61,7 +71,7 @@ def direct_dependency(type, result = Set[])
6171
end
6272
when RBS::Types::Alias
6373
# Append type name if the type is an alias
64-
result << type.name
74+
result << env.normalize_type_name(type.name)
6575
end
6676

6777
result

lib/rbs/type_alias_regularity.rb

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ def validate
3737
end
3838

3939
def validate_alias_type(alias_type, names, types)
40-
if names.include?(alias_type.name)
41-
if ex_type = types[alias_type.name]
40+
alias_name = env.normalize_type_name?(alias_type.name) or return
41+
42+
if names.include?(alias_name)
43+
if ex_type = types[alias_name]
4244
unless compatible_args?(ex_type.args, alias_type.args)
43-
diagnostics[alias_type.name] ||=
45+
diagnostics[alias_name] ||=
4446
Diagnostic.new(type_name: alias_type.name, nonregular_type: alias_type)
4547
end
4648

@@ -49,7 +51,7 @@ def validate_alias_type(alias_type, names, types)
4951
types[alias_type.name] = alias_type
5052
end
5153

52-
expanded = builder.expand_alias2(alias_type.name, alias_type.args)
54+
expanded = builder.expand_alias2(alias_name, alias_type.args)
5355
each_alias_type(expanded) do |at|
5456
validate_alias_type(at, names, types)
5557
end
@@ -75,22 +77,27 @@ def compatible_args?(args1, args2)
7577
end
7678

7779
def nonregular?(type_name)
78-
diagnostics[type_name]
80+
diagnostics[env.normalize_type_name!(type_name)]
7981
end
8082

8183
def each_mutual_alias_defs(&block)
82-
# @type var each_node: TSort::_EachNode[TypeName]
83-
each_node = __skip__ = -> (&block) do
84+
# @type var each_node: ^() { (TypeName) -> void } -> void
85+
each_node = -> (&block) do
8486
env.type_alias_decls.each_value do |decl|
85-
block[decl.name]
87+
if normalized = env.normalize_type_name?(decl.name)
88+
block[normalized]
89+
end
8690
end
8791
end
88-
# @type var each_child: TSort::_EachChild[TypeName]
89-
each_child = __skip__ = -> (name, &block) do
92+
93+
# @type var each_child: ^(TypeName) { (TypeName) -> void } -> void
94+
each_child = -> (name, &block) do
9095
if env.type_alias_decls.key?(name)
9196
type = builder.expand_alias1(name)
9297
each_alias_type(type) do |ty|
93-
block[ty.name]
98+
if normalized = env.normalize_type_name?(ty.name)
99+
block[normalized]
100+
end
94101
end
95102
end
96103
end

0 commit comments

Comments
 (0)