Permalink
Browse files

Methods whose name ends in ? must return true, false, or nil.

  • Loading branch information...
1 parent 175b75d commit 5d737eb1e8815dbaf1b7c9833b95bb4dfb91a297 Michael Edgar committed Aug 22, 2011
@@ -163,6 +163,12 @@ def check_return_type_against_expectations(return_type)
@proc.ast_node.add_error(ImproperOverloadTypeError.new(
"All methods named #{self.name} should return a subtype of #{expectation.inspect}",
@proc.ast_node))
+ elsif self.name.end_with?('?')
+ if !Types.subtype?(return_type, Types::BOOL_OR_NIL)
+ @proc.ast_node.add_error(ImproperOverloadTypeError.new(
+ "All methods whose name ends in ? should return a subtype of TrueClass | FalseClass | NilClass",
+ @proc.ast_node))
+ end
end
end
View
@@ -217,6 +217,7 @@ def signature
FALSECLASS = ClassObjectType.new('FalseClass')
FALSY = UnionType.new([FALSECLASS, NILCLASS])
BOOLEAN = UnionType.new([TRUECLASS, FALSECLASS])
+ BOOL_OR_NIL = UnionType.new([BOOLEAN, NILCLASS])
BLOCK = UnionType.new([PROC, NILCLASS])
EMPTY = UnionType.new([])
@@ -143,7 +143,7 @@ def !
have_error(ImproperOverloadTypeError).with_message(/\!/))
end
- it "should not warn against a method named ! that always returns a boolean" do
+ it "should not warn against a method named ! that always returns a boolean" do
g = cfg <<-EOF
class OverI3
def !
@@ -157,4 +157,34 @@ def !
ClassRegistry["OverI3"].instance_method(:!).proc.ast_node.should_not(
have_error(ImproperOverloadTypeError))
end
+
+ it 'should warn when a method whose name ends in ? does not return a bool | nil' do
+ g = cfg <<-EOF
+class OverI4
+ def silly?(x, y)
+ x == y && y # whoops, returns y's type. How about a boolean?
+ end
+end
+EOF
+ ClassRegistry["OverI4"].instance_method(:silly?).
+ return_type_for_types(
+ ClassRegistry["OverI4"].as_type, [Types::FIXNUM, Types::FIXNUM])
+ ClassRegistry["OverI4"].instance_method(:silly?).proc.ast_node.should(
+ have_error(ImproperOverloadTypeError))
+ end
+
+ it 'should not warn when a method whose name ends in ? does return a bool | nil' do
+ g = cfg <<-EOF
+class OverI5
+ def silly?(x, y)
+ x == y || nil
+ end
+end
+EOF
+ ClassRegistry["OverI5"].instance_method(:silly?).
+ return_type_for_types(
+ ClassRegistry["OverI5"].as_type, [Types::FIXNUM, Types::FIXNUM])
+ ClassRegistry["OverI5"].instance_method(:silly?).proc.ast_node.should_not(
+ have_error(ImproperOverloadTypeError))
+ end
end

0 comments on commit 5d737eb

Please sign in to comment.