Skip to content

Commit

Permalink
Merge pull request #840 from ruby/validate_mixin_args
Browse files Browse the repository at this point in the history
Validate `extend` arguments
  • Loading branch information
soutaro authored Dec 12, 2021
2 parents 537f3c6 + c1bebc5 commit 9a2fd38
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 10 deletions.
29 changes: 29 additions & 0 deletions lib/rbs/definition_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ def build_singleton0(type_name)
end

one_ancestors.each_extended_module do |mod|
mod.args.each do |arg|
validate_type_presence(arg)
end

mod_defn = build_instance(mod.name, no_self_types: true)
merge_definition(src: mod_defn,
dest: definition,
Expand All @@ -299,6 +303,10 @@ def build_singleton0(type_name)

interface_methods = {}
one_ancestors.each_extended_interface do |mod|
mod.args.each do |arg|
validate_type_presence(arg)
end

mod_defn = build_interface(mod.name)
subst = Substitution.build(mod_defn.type_params, mod.args)

Expand Down Expand Up @@ -831,5 +839,26 @@ def update(env:, except:, ancestor_builder:)
end
end
end

def validate_type_presence(type)
case type
when Types::ClassInstance, Types::ClassSingleton, Types::Interface, Types::Alias
validate_type_name(type.name, type.location)
end

type.each_type do |type|
validate_type_presence(type)
end
end

def validate_type_name(name, location)
name = name.absolute!

return if name.class? && env.class_decls.key?(name)
return if name.interface? && env.interface_decls.key?(name)
return if name.alias? && env.alias_decls.key?(name)

raise NoTypeFoundError.new(type_name: name, location: location)
end
end
end
16 changes: 6 additions & 10 deletions lib/rbs/validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,17 @@ def validate_type(type, context:)
end
end

definition_builder.validate_type_name(type.name, type.location)

type_params = case type
when Types::ClassInstance
env.class_decls[type.name]&.type_params
env.class_decls[type.name].type_params
when Types::Interface
env.interface_decls[type.name]&.decl&.type_params
env.interface_decls[type.name].decl.type_params
when Types::Alias
env.alias_decls[type.name]&.decl&.type_params
env.alias_decls[type.name].decl.type_params
end

unless type_params
raise NoTypeFoundError.new(type_name: type.name, location: type.location)
end

InvalidTypeApplicationError.check!(
type_name: type.name,
args: type.args,
Expand All @@ -48,9 +46,7 @@ def validate_type(type, context:)
)

when Types::ClassSingleton
# @type var type: Types::ClassSingleton
type = _ = absolute_type(type, context: context) { type.name.absolute! }
NoTypeFoundError.check!(type.name, env: env, location: type.location)
definition_builder.validate_type_presence(type)
end

type.each_type do |type|
Expand Down
7 changes: 7 additions & 0 deletions sig/definition_builder.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ module RBS

def define_methods: (Definition, interface_methods: Hash[Symbol, Definition::Method], methods: MethodBuilder::Methods, super_interface_method: bool) -> void

# Validates presence of type names recursively.
# Assumes the type names are already resolved.
#
def validate_type_presence: (Types::t) -> void

def validate_type_name: (TypeName, Location[untyped, untyped]?) -> void

# Expand a type alias of given name without type arguments.
# Raises an error if the type alias requires arguments.
#
Expand Down
19 changes: 19 additions & 0 deletions test/rbs/cli_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,25 @@ class Hello::World
assert_equal "::Hello", error.type_name.to_s
end
end

with_cli do |cli|
Dir.mktmpdir do |dir|
(Pathname(dir) + 'a.rbs').write(<<~RBS)
class Foo[A]
extend Bar[A]
end
module Bar[B]
end
RBS

error = assert_raises RBS::NoTypeFoundError do
cli.run(["-I", dir, "validate"])
end

assert_equal "::A", error.type_name.to_s
end
end
end

def test_constant
Expand Down

0 comments on commit 9a2fd38

Please sign in to comment.