diff --git a/spec/ameba/rule/style/multiline_curly_block_spec.cr b/spec/ameba/rule/style/multiline_curly_block_spec.cr new file mode 100644 index 000000000..fc902b82a --- /dev/null +++ b/spec/ameba/rule/style/multiline_curly_block_spec.cr @@ -0,0 +1,36 @@ +require "../../../spec_helper" + +module Ameba::Rule::Style + describe MultilineCurlyBlock do + subject = MultilineCurlyBlock.new + + it "doesn't report if a curly block is on a single line" do + expect_no_issues subject, <<-CRYSTAL + foo { :bar } + CRYSTAL + end + + it "doesn't report for `do`...`end` blocks" do + expect_no_issues subject, <<-CRYSTAL + foo do + :bar + end + CRYSTAL + end + + it "doesn't report for `do`...`end` blocks on a single line" do + expect_no_issues subject, <<-CRYSTAL + foo do :bar end + CRYSTAL + end + + it "reports if there is a multi-line curly block" do + expect_issue subject, <<-CRYSTAL + foo { + # ^ error: Use `do`...`end` instead of curly brackets for multi-line blocks + :bar + } + CRYSTAL + end + end +end diff --git a/src/ameba/rule/documentation/documentation_admonition.cr b/src/ameba/rule/documentation/documentation_admonition.cr index 5b7993838..a9fd7e8e9 100644 --- a/src/ameba/rule/documentation/documentation_admonition.cr +++ b/src/ameba/rule/documentation/documentation_admonition.cr @@ -45,9 +45,9 @@ module Ameba::Rule::Documentation MSG_ERR = "%s admonition error: %s" @[YAML::Field(ignore: true)] - private getter location : Time::Location { + private getter location : Time::Location do Time::Location.load(self.timezone) - } + end def test(source) Tokenizer.new(source).run do |token| diff --git a/src/ameba/rule/style/multiline_curly_block.cr b/src/ameba/rule/style/multiline_curly_block.cr new file mode 100644 index 000000000..45c2130ce --- /dev/null +++ b/src/ameba/rule/style/multiline_curly_block.cr @@ -0,0 +1,46 @@ +module Ameba::Rule::Style + # A rule that disallows multi-line blocks that use curly brackets + # instead of `do`...`end`. + # + # For example, this is considered invalid: + # + # ``` + # (0..10).map { |i| + # i * 2 + # } + # ``` + # + # And should be rewritten to the following: + # + # ``` + # (0..10).map do |i| + # i * 2 + # end + # ``` + # + # YAML configuration example: + # + # ``` + # Style/MultilineCurlyBlock: + # Enabled: true + # ``` + class MultilineCurlyBlock < Base + include AST::Util + + properties do + since_version "1.7.0" + description "Disallows multi-line blocks using curly block syntax" + end + + MSG = "Use `do`...`end` instead of curly brackets for multi-line blocks" + + def test(source, node : Crystal::Block) + return unless start_location = node.location + return unless end_location = node.end_location + return if start_location.line_number == end_location.line_number + return unless source.code[source.pos(start_location)]? == '{' + + issue_for node, MSG + end + end +end