diff --git a/spec/ameba/rules/empty_expression_spec.cr b/spec/ameba/rules/empty_expression_spec.cr new file mode 100644 index 00000000..69e82d89 --- /dev/null +++ b/spec/ameba/rules/empty_expression_spec.cr @@ -0,0 +1,85 @@ +require "../../spec_helper" + +module Ameba + subject = Rules::EmptyExpression.new + + def it_detects_empty_expression(code) + it "detects empty expression" do + s = Source.new code + rule = Rules::EmptyExpression.new + rule.catch(s).should_not be_valid + end + end + + describe Rules::EmptyExpression do + it "passes if there is no empty expression" do + s = Source.new %( + def method() + end + + method() + method(1, 2, 3) + method(nil) + + a = nil + a = "" + a = 0 + ) + subject.catch(s).should be_valid + end + + it_detects_empty_expression %(()) + it_detects_empty_expression %(((()))) + it_detects_empty_expression %(a = ()) + it_detects_empty_expression %((();())) + it_detects_empty_expression %(if (); end) + it_detects_empty_expression %( + if foo + 1 + elsif () + 2 + end + ) + it_detects_empty_expression %( + case foo + when :foo then () + end + ) + it_detects_empty_expression %( + case foo + when :foo then 1 + else + () + end + ) + it_detects_empty_expression %( + case foo + when () then 1 + end + ) + it_detects_empty_expression %( + def method + a = 1 + () + end + ) + it_detects_empty_expression %( + def method + rescue + () + end + ) + + it "reports rule, pos and message" do + s = Source.new %( + if () + end + ) + subject.catch(s).should_not be_valid + error = s.errors.first + error.rule.should_not be_nil + error.pos.should eq 2 + error.message.should eq "Avoid empty expression '()'" + end + end +end diff --git a/src/ameba/ast/traverse.cr b/src/ameba/ast/traverse.cr index a7d9bb2b..d0bf3c02 100644 --- a/src/ameba/ast/traverse.cr +++ b/src/ameba/ast/traverse.cr @@ -14,6 +14,7 @@ module Ameba::AST InstanceVar, LibDef, ModuleDef, + NilLiteral, StringInterpolation, Unless, Var, diff --git a/src/ameba/rules/empty_expression.cr b/src/ameba/rules/empty_expression.cr new file mode 100644 index 00000000..de67b82c --- /dev/null +++ b/src/ameba/rules/empty_expression.cr @@ -0,0 +1,40 @@ +module Ameba::Rules + # A rule that disallows empty expressions. + # + # This is considered invalid: + # + # ``` + # foo = () + # + # if () + # bar + # end + # ``` + # + # And this is valid: + # + # ``` + # foo = (some_expression) + # + # if (some_expression) + # bar + # end + # ``` + # + struct EmptyExpression < Rule + include AST::Util + + def test(source) + AST::Visitor.new self, source + end + + def test(source, node : Crystal::NilLiteral) + exp = node_source(node, source.lines).try &.join + + return if exp.nil? || exp == "nil" + + source.error self, node.location.try &.line_number, + "Avoid empty expression '#{exp}'" + end + end +end