diff --git a/spec/ameba/rules/predicate_name_spec.cr b/spec/ameba/rules/predicate_name_spec.cr new file mode 100644 index 00000000..7e7ab3c6 --- /dev/null +++ b/spec/ameba/rules/predicate_name_spec.cr @@ -0,0 +1,45 @@ +require "../../spec_helper" + +module Ameba::Rules + subject = PredicateName.new + + describe PredicateName do + it "passes if predicate name is correct" do + s = Source.new %q( + def valid?(x) + end + + class Image + def picture?(x) + end + end + ) + subject.catch(s).valid?.should be_true + end + + it "fails if predicate name is wrong" do + s = Source.new %q( + def is_valid?(x) + end + ) + subject.catch(s).valid?.should be_false + end + + it "reports rule, pos and message" do + s = Source.new %q( + class Image + def has_picture?(x) + true + end + end + ) + subject.catch(s).valid?.should be_false + + error = s.errors.first + error.rule.should_not be_nil + error.pos.should eq 3 + error.message.should eq( + "Favour method name 'picture?' over 'has_picture?'") + end + end +end diff --git a/src/ameba/ast/traverse.cr b/src/ameba/ast/traverse.cr index 7be3ed5f..293a3477 100644 --- a/src/ameba/ast/traverse.cr +++ b/src/ameba/ast/traverse.cr @@ -4,6 +4,7 @@ module Ameba::AST NODE_VISITORS = [ Call, Case, + Def, If, StringInterpolation, Unless, diff --git a/src/ameba/rules/predicate_name.cr b/src/ameba/rules/predicate_name.cr new file mode 100644 index 00000000..96d92220 --- /dev/null +++ b/src/ameba/rules/predicate_name.cr @@ -0,0 +1,37 @@ +module Ameba::Rules + # A rule that disallows tautological predicate names, meaning those that + # start with the prefix `has_` or the prefix `is_`. + # + # Favour these: + # + # ``` + # def valid?(x) + # end + # + # def picture?(x) + # end + # ``` + # + # Over these: + # + # ``` + # def is_valid?(x) + # end + # + # def has_picture?(x) + # end + # ``` + # + struct PredicateName < Rule + def test(source) + AST::DefVisitor.new self, source + end + + def test(source, node : Crystal::Def) + if node.name =~ /(is|has)_(\w+)\?/ + source.error self, node.location.try &.line_number, + "Favour method name '#{$2}?' over '#{node.name}'" + end + end + end +end