Skip to content

Commit

Permalink
Merge pull request #593 from soutaro/revert-592-revert-582-class-var-…
Browse files Browse the repository at this point in the history
…validation

Revert "Revert "Add class variable validation""
  • Loading branch information
soutaro authored Jul 20, 2022
2 parents fb59ee8 + 9d6b29c commit fad3589
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
18 changes: 18 additions & 0 deletions lib/steep/diagnostic/signature.rb
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,24 @@ def header_line
end
end

class ClassVariableDuplicationError < Base
attr_reader :class_name
attr_reader :other_class_name
attr_reader :variable_name

def initialize(class_name:, other_class_name:, variable_name:, location:)
super(location: location)

@class_name = class_name
@other_class_name = other_class_name
@variable_name = variable_name
end

def header_line
"Class variable definition `#{variable_name}` in `#{class_name}` may be overtaken by `#{other_class_name}`"
end
end

class InstanceVariableTypeError < Base
attr_reader :name
attr_reader :variable
Expand Down
19 changes: 19 additions & 0 deletions lib/steep/signature/validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,25 @@ def validate_one_class(name)
end
end

definition.class_variables.each do |name, var|
if var.declared_in == definition.type_name
if (parent = var.parent_variable) && var.declared_in != parent.declared_in
class_var = definition.entry.decls.flat_map {|decl| decl.decl.members }.find do |member|
member.is_a?(RBS::AST::Members::ClassVariable) && member.name == name
end

if class_var
@errors << Diagnostic::Signature::ClassVariableDuplicationError.new(
class_name: definition.type_name,
other_class_name: parent.declared_in,
variable_name: name,
location: class_var.location[:name]
)
end
end
end
end

ancestors = builder.ancestor_builder.one_singleton_ancestors(name)
mixin_constraints(definition, ancestors.extended_modules, immediate_self_types: ancestors.self_types).each do |relation, ancestor|
checker.check(
Expand Down
36 changes: 36 additions & 0 deletions test/validation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,42 @@ class D
end
end

def test_validate_class_variables
with_checker <<-EOF do |checker|
class A
@@foo: Integer
end
class B < A
@@foo: Integer?
end
class C < B
end
EOF
Validator.new(checker: checker).tap do |validator|
validator.validate_one_class(TypeName("::A"))

assert_predicate validator, :no_error?
end

Validator.new(checker: checker).tap do |validator|
validator.validate_one_class(TypeName("::C"))

assert_predicate validator, :no_error?
end

Validator.new(checker: checker).tap do |validator|
validator.validate_one_class(TypeName("::B"))

assert_predicate validator, :has_error?
assert_any!(validator.each_error, size: 1) do |error|
assert_instance_of Diagnostic::Signature::ClassVariableDuplicationError, error
end
end
end
end

def test_validate_type_application
with_checker <<-EOF do |checker|
class Foo[X < Numeric]
Expand Down

0 comments on commit fad3589

Please sign in to comment.