Skip to content

Commit 7122e32

Browse files
authored
Merge pull request #2300 from ruby/mixin-class-var
Fix class variable
2 parents 6ef2455 + 8578699 commit 7122e32

File tree

3 files changed

+125
-14
lines changed

3 files changed

+125
-14
lines changed

lib/rbs/definition_builder.rb

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def tapp_subst(name, args)
8282
AST::TypeParam.application(params, args) || Substitution.new()
8383
end
8484

85-
def define_instance(definition, type_name, subst)
85+
def define_instance(definition, type_name, subst, define_class_vars:)
8686
one_ancestors = ancestor_builder.one_instance_ancestors(type_name)
8787
methods = method_builder.build_instance(type_name)
8888

@@ -104,7 +104,7 @@ def define_instance(definition, type_name, subst)
104104
validate_type_presence(arg)
105105
end
106106

107-
define_instance(definition, mod.name, subst + tapp_subst(mod.name, mod.args))
107+
define_instance(definition, mod.name, subst + tapp_subst(mod.name, mod.args), define_class_vars: define_class_vars)
108108
end
109109

110110
all_interfaces = one_ancestors.each_included_interface.flat_map do |interface|
@@ -120,7 +120,7 @@ def define_instance(definition, type_name, subst)
120120
validate_type_presence(arg)
121121
end
122122

123-
define_instance(definition, mod.name, subst + tapp_subst(mod.name, mod.args))
123+
define_instance(definition, mod.name, subst + tapp_subst(mod.name, mod.args), define_class_vars: define_class_vars)
124124
end
125125

126126
entry = env.class_decls[type_name] or raise "Unknown name for build_instance: #{type_name}"
@@ -161,7 +161,9 @@ def define_instance(definition, type_name, subst)
161161
)
162162

163163
when AST::Members::ClassVariable
164-
insert_variable(type_name, definition.class_variables, name: member.name, type: member.type, source: member)
164+
if define_class_vars
165+
insert_variable(type_name, definition.class_variables, name: member.name, type: member.type, source: member)
166+
end
165167
end
166168
end
167169
end
@@ -216,13 +218,13 @@ def build_instance(type_name)
216218
if ans.name.interface?
217219
define_interface(definition, ans.name, subst)
218220
else
219-
define_instance(definition, ans.name, subst)
221+
define_instance(definition, ans.name, subst, define_class_vars: true)
220222
end
221223
end
222224
end
223225
end
224226

225-
define_instance(definition, type_name, Substitution.new)
227+
define_instance(definition, type_name, Substitution.new, define_class_vars: true)
226228
end
227229
end
228230
end
@@ -251,7 +253,6 @@ def build_singleton0(type_name)
251253

252254
definition.methods.merge!(defn.methods)
253255
definition.instance_variables.merge!(defn.instance_variables)
254-
definition.class_variables.merge!(defn.class_variables)
255256
end
256257

257258
one_ancestors.each_extended_module do |mod|
@@ -260,7 +261,7 @@ def build_singleton0(type_name)
260261
end
261262

262263
subst = tapp_subst(mod.name, mod.args)
263-
define_instance(definition, mod.name, subst)
264+
define_instance(definition, mod.name, subst, define_class_vars: false)
264265
end
265266

266267
all_interfaces = one_ancestors.each_extended_interface.flat_map do |interface|
@@ -290,12 +291,12 @@ def build_singleton0(type_name)
290291

291292
when AST::Members::ClassInstanceVariable
292293
insert_variable(type_name, definition.instance_variables, name: member.name, type: member.type, source: member)
293-
294-
when AST::Members::ClassVariable
295-
insert_variable(type_name, definition.class_variables, name: member.name, type: member.type, source: member)
296294
end
297295
end
298296
end
297+
298+
instance_definition = build_instance(type_name)
299+
definition.class_variables.replace(instance_definition.class_variables)
299300
end
300301
end
301302
end

sig/definition_builder.rbs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,13 @@ module RBS
107107

108108
def validate_variable: (Definition::Variable) -> void
109109

110-
def insert_variable: (TypeName, Hash[Symbol, Definition::Variable], name: Symbol, type: Types::t, source: Definition::Variable::source) -> void
110+
def insert_variable: (
111+
TypeName,
112+
Hash[Symbol, Definition::Variable],
113+
name: Symbol,
114+
type: Types::t,
115+
source: Definition::Variable::source
116+
) -> void
111117

112118
# Add method definition to `methods`, which will be merged to `class_definition` after defining all methods at this *level* -- class, module, or interface
113119
#
@@ -144,11 +150,17 @@ module RBS
144150
Hash[Symbol, Definition::Method]? self_type_methods,
145151
) -> void
146152

147-
# Updates `definition` with methods and variables of `type_name` that can be a module or a class
153+
# Updates `definition` with methods and instance variables of `type_name` that can be a module or a class
148154
#
149155
# It processes includes and prepends recursively.
156+
# If `define_class_vars:` is falsy, it skips inserting class variables.
150157
#
151-
def define_instance: (Definition definition, TypeName type_name, Substitution subst) -> void
158+
def define_instance: (
159+
Definition definition,
160+
TypeName type_name,
161+
Substitution subst,
162+
define_class_vars: bool
163+
) -> void
152164

153165
# Updates `definition` with methods defined in an interface `type_name`
154166
#

test/rbs/definition_builder_test.rb

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2706,6 +2706,104 @@ module Foo
27062706
end
27072707
end
27082708

2709+
def test_class_var__mixin__include_defines_class_var
2710+
SignatureManager.new() do |manager|
2711+
manager.add_file("foo.rbs", <<-EOF)
2712+
module M1
2713+
@@m1: Integer
2714+
end
2715+
2716+
class Foo
2717+
include M1
2718+
end
2719+
EOF
2720+
2721+
manager.build do |env|
2722+
builder = DefinitionBuilder.new(env: env)
2723+
2724+
builder.build_instance(type_name("::Foo")).tap do |definition|
2725+
definition.class_variables[:@@m1].tap do |var|
2726+
assert_instance_of Definition::Variable, var
2727+
assert_equal type_name("::M1"), var.declared_in
2728+
assert_nil var.parent_variable
2729+
assert_equal "@@m1: Integer", var.source.location.source
2730+
end
2731+
end
2732+
2733+
builder.build_singleton(type_name("::Foo")).tap do |definition|
2734+
definition.class_variables[:@@m1].tap do |var|
2735+
assert_instance_of Definition::Variable, var
2736+
assert_equal type_name("::M1"), var.declared_in
2737+
assert_nil var.parent_variable
2738+
assert_equal "@@m1: Integer", var.source.location.source
2739+
end
2740+
end
2741+
end
2742+
end
2743+
end
2744+
2745+
def test_class_var__mixin__extend_no_class_var
2746+
SignatureManager.new() do |manager|
2747+
manager.add_file("foo.rbs", <<-EOF)
2748+
module M1
2749+
@@m1: Integer
2750+
end
2751+
2752+
class Foo
2753+
extend M1
2754+
end
2755+
EOF
2756+
2757+
manager.build do |env|
2758+
builder = DefinitionBuilder.new(env: env)
2759+
2760+
builder.build_instance(type_name("::Foo")).tap do |definition|
2761+
assert_nil definition.class_variables[:@@m1]
2762+
end
2763+
2764+
builder.build_singleton(type_name("::Foo")).tap do |definition|
2765+
assert_nil definition.class_variables[:@@m1]
2766+
end
2767+
end
2768+
end
2769+
end
2770+
2771+
def test_class_var__mixin__prepend_class_var
2772+
SignatureManager.new() do |manager|
2773+
manager.add_file("foo.rbs", <<-EOF)
2774+
module M1
2775+
@@m1: Integer
2776+
end
2777+
2778+
class Foo
2779+
prepend M1
2780+
end
2781+
EOF
2782+
2783+
manager.build do |env|
2784+
builder = DefinitionBuilder.new(env: env)
2785+
2786+
builder.build_instance(type_name("::Foo")).tap do |definition|
2787+
definition.class_variables[:@@m1].tap do |var|
2788+
assert_instance_of Definition::Variable, var
2789+
assert_equal type_name("::M1"), var.declared_in
2790+
assert_nil var.parent_variable
2791+
assert_equal "@@m1: Integer", var.source.location.source
2792+
end
2793+
end
2794+
2795+
builder.build_singleton(type_name("::Foo")).tap do |definition|
2796+
definition.class_variables[:@@m1].tap do |var|
2797+
assert_instance_of Definition::Variable, var
2798+
assert_equal type_name("::M1"), var.declared_in
2799+
assert_nil var.parent_variable
2800+
assert_equal "@@m1: Integer", var.source.location.source
2801+
end
2802+
end
2803+
end
2804+
end
2805+
end
2806+
27092807
def test_duplicated_variable
27102808
SignatureManager.new do |manager|
27112809
manager.add_file("instance.rbs", <<-EOF)

0 commit comments

Comments
 (0)