diff --git a/.rubocop.yml b/.rubocop.yml index fc5f688..26eb1c0 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -8,3 +8,8 @@ inherit_mode: AllCops: TargetRubyVersion: 2.3 + +# for checking cops with interpolation +Lint/InterpolationCheck: + Exclude: + - 'spec/**/*.rb' diff --git a/CHANGELOG.md b/CHANGELOG.md index e4b201c..7d4c653 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ The format is described in [Contributing notes](CONTRIBUTING.md#changelog-entry- ### Added * Enable `rubocop-rails` cops for rails config. ([@ula][]) +* Add `Style/NestedInterpolation` cop. ([@r.dubrovsky][]) ## 0.7.0 (2020-01-27) diff --git a/config/base.yml b/config/base.yml index 2b1ddc3..101c279 100644 --- a/config/base.yml +++ b/config/base.yml @@ -22,7 +22,6 @@ Layout/ArrayAlignmentExtended: - with_fixed_indentation IndentationWidth: ~ - Layout/HashAlignment: EnforcedLastArgumentHashStyle: always_ignore @@ -64,5 +63,8 @@ Style/EmptyMethod: Style/FrozenStringLiteralComment: Enabled: false +Style/NestedInterpolation: + Enabled: true + Style/StringLiterals: EnforcedStyle: double_quotes diff --git a/doc/STYLE_GUIDE.md b/doc/STYLE_GUIDE.md index df0bea1..e8f599a 100644 --- a/doc/STYLE_GUIDE.md +++ b/doc/STYLE_GUIDE.md @@ -35,6 +35,19 @@ This is a small list of differences which we have when compared with community s Adopt a consistent string literal quoting style. [[link](#style-string-quotes)] +* + Avoid using nested interpolation. + [[link](#style-nested-interpolation)] + +```ruby +# bad +"Hello, #{user.blank? ? 'guest' : "dear #{user.name}"}" + +# good +user_name = user.blank? ? 'guest' : "dear #{user.name}" +"Hello, #{user_name}" +``` + * If elements of a hash literal span more than one line, we're aligning them by keys. Also, the first hash key is aligned by an indentation level. diff --git a/lib/datarockets/style.rb b/lib/datarockets/style.rb index e2aef78..dd80dcd 100644 --- a/lib/datarockets/style.rb +++ b/lib/datarockets/style.rb @@ -4,6 +4,7 @@ require "datarockets/style/version" require "datarockets/style/cop/layout/array_alignment_extended" +require "datarockets/style/cop/style/nested_interpolation" module Datarockets # Datarickors sharable config diff --git a/lib/datarockets/style/cop/style/nested_interpolation.rb b/lib/datarockets/style/cop/style/nested_interpolation.rb new file mode 100644 index 0000000..4c94b74 --- /dev/null +++ b/lib/datarockets/style/cop/style/nested_interpolation.rb @@ -0,0 +1,29 @@ +module Datarockets + module Style + module Cop + module Style + # This cop checks nested interpolations + # + # @example + # + # # bad + # "Hello, #{user.blank? ? 'guest' : "dear #{user.name}"}" + # + # # good + # user_name = user.blank? ? 'guest' : "dear #{user.name}" + # "Hello, #{user_name}" + class NestedInterpolation < RuboCop::Cop::Cop + include RuboCop::Cop::Interpolation + + MSG = "Redundant nested interpolation.".freeze + + def on_interpolation(node) + node.each_descendant(:begin) do |descendant_node| + add_offense(descendant_node) + end + end + end + end + end + end +end diff --git a/manual/cops_layout.md b/manual/cops_layout.md index 87ee5e9..2b4b07e 100644 --- a/manual/cops_layout.md +++ b/manual/cops_layout.md @@ -51,3 +51,24 @@ Name | Default value | Configurable values --- | --- | --- EnforcedStyle | `with_first_parameter` | `with_first_parameter`, `with_fixed_indentation` IndentationWidth | `` | Integer + +# Style + +## Style/NestedInterpolation + +Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged +--- | --- | --- | --- | --- +Enabled | Yes | No | 0.8.0 | - + +This cop checks nested interpolations + +### Example + +```ruby +# bad +"Hello, #{user.blank? ? 'guest' : "dear #{user.name}"}" + +# good +user_name = user.blank? ? 'guest' : "dear #{user.name}" +"Hello, #{user_name}" +``` diff --git a/spec/datarockets/style/cop/style/nested_interpolation_spec.rb b/spec/datarockets/style/cop/style/nested_interpolation_spec.rb new file mode 100644 index 0000000..4ef121e --- /dev/null +++ b/spec/datarockets/style/cop/style/nested_interpolation_spec.rb @@ -0,0 +1,39 @@ +RSpec.describe Datarockets::Style::Cop::Style::NestedInterpolation do + subject(:cop) { described_class.new } + + it "accepts single interpolation" do + expect_no_offenses('"dear #{user.name}"') + end + + it "accepts two single interpolation" do + expect_no_offenses('"Hello #{user1.name} and #{user2.name}"') + end + + it 'registers an offense for "Hello, #{user.blank? ? guest : "dear #{user.name}"}"' do + expect_offense(<<~'RUBY') + "Hello, #{user.blank? ? 'guest' : "dear #{user.name}"}" + ^^^^^^^^^^^^ Redundant nested interpolation. + RUBY + end + + it 'registers an offense for %|Hello, #{user.blank? ? guest : "dear #{user.name}"|' do + expect_offense(<<~'RUBY') + %|Hello, #{user.blank? ? 'guest' : "dear #{user.name}"}| + ^^^^^^^^^^^^ Redundant nested interpolation. + RUBY + end + + it 'registers an offense for %Q(Hello, #{user.blank? ? guest : "dear #{user.name}")' do + expect_offense(<<~'RUBY') + %Q(Hello, #{user.blank? ? 'guest' : "dear #{user.name}"}) + ^^^^^^^^^^^^ Redundant nested interpolation. + RUBY + end + + it 'registers an offense for ["Hello, #{user.blank? ? guest : "dear #{user.name}"}"]' do + expect_offense(<<~'RUBY') + ["Hello, #{user.blank? ? 'guest' : "dear #{user.name}"}", 'foo'] + ^^^^^^^^^^^^ Redundant nested interpolation. + RUBY + end +end