summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Speicher <rspeicher@gmail.com>2016-05-27 17:10:39 -0400
committerRobert Speicher <rspeicher@gmail.com>2016-05-27 17:10:39 -0400
commit439c304f5ed15cac416cb1a63e15c43fc300bbfd (patch)
treebec71e2b0d1ce0f3deabf0739570ab87ab351d04
parentf9bb9151b595fdc1afc1742bb51c816965908f53 (diff)
downloadgitlab-ce-rs-array-literal-delimiter-cop.tar.gz
WIP: Add custom cop for ArrayLiteralDelimiterrs-array-literal-delimiter-cop
-rw-r--r--.rubocop.yml4
-rw-r--r--lib/rubocop/cop/style/array_literal_delimiter.rb43
-rw-r--r--spec/lib/rubocop/cop/style/array_literal_delimiter_spec.rb102
3 files changed, 148 insertions, 1 deletions
diff --git a/.rubocop.yml b/.rubocop.yml
index 2d8eb4077f3..fdca6e5141a 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -1,4 +1,6 @@
-require: rubocop-rspec
+require:
+ - rubocop-rspec
+ - ./lib/rubocop/cop/style/array_literal_delimiter.rb
AllCops:
TargetRubyVersion: 2.1
diff --git a/lib/rubocop/cop/style/array_literal_delimiter.rb b/lib/rubocop/cop/style/array_literal_delimiter.rb
new file mode 100644
index 00000000000..1b0638ce26c
--- /dev/null
+++ b/lib/rubocop/cop/style/array_literal_delimiter.rb
@@ -0,0 +1,43 @@
+# encoding: utf-8
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Style
+ # This cop enforces square brackets for Array literal `%`-style
+ # delimiters.
+ #
+ # @example
+ #
+ # # bad
+ # %w(foo bar) + %w{baz qux}
+ #
+ # # good
+ # %w[foo bar] + %w[baz qux]
+ class ArrayLiteralDelimiter < RuboCop::Cop::Cop
+ def on_array(*args)
+ array = args.first
+
+ first, last = array.loc.begin, array.loc.end
+
+ return unless first && last
+ return unless first.source.start_with?('%')
+
+ return if first.source.start_with?('%w[', '%W[', '%i[', '%I[') &&
+ last.source == ']'
+
+ add_offense(array, :expression, "TODO")
+ end
+
+ def autocorrect(node)
+ -> (corrector) do
+ style = node.loc.begin.source[0..-2]
+
+ corrector.replace(node.loc.begin, "#{style}[")
+ corrector.replace(node.loc.end, ']')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/rubocop/cop/style/array_literal_delimiter_spec.rb b/spec/lib/rubocop/cop/style/array_literal_delimiter_spec.rb
new file mode 100644
index 00000000000..3a11dd07127
--- /dev/null
+++ b/spec/lib/rubocop/cop/style/array_literal_delimiter_spec.rb
@@ -0,0 +1,102 @@
+require 'spec_helper'
+
+require 'rubocop'
+require 'rubocop/cop/style/array_literal_delimiter'
+
+# encoding: utf-8
+# frozen_string_literal: true
+
+require 'tempfile'
+
+module CopHelper
+ extend RSpec::SharedContext
+
+ let(:ruby_version) { 2.2 }
+
+ def inspect_source_file(cop, source)
+ Tempfile.open('tmp') { |f| inspect_source(cop, source, f) }
+ end
+
+ def inspect_source(cop, source, file = nil)
+ if source.is_a?(Array) && source.size == 1
+ raise "Don't use an array for a single line of code: #{source}"
+ end
+ RuboCop::Formatter::DisabledConfigFormatter.config_to_allow_offenses = {}
+ RuboCop::Formatter::DisabledConfigFormatter.detected_styles = {}
+ processed_source = parse_source(source, file)
+ raise 'Error parsing example code' unless processed_source.valid_syntax?
+ _investigate(cop, processed_source)
+ end
+
+ def parse_source(source, file = nil)
+ source = source.join($RS) if source.is_a?(Array)
+
+ if file && file.respond_to?(:write)
+ file.write(source)
+ file.rewind
+ file = file.path
+ end
+
+ RuboCop::ProcessedSource.new(source, ruby_version, file)
+ end
+
+ def autocorrect_source_file(cop, source)
+ Tempfile.open('tmp') { |f| autocorrect_source(cop, source, f) }
+ end
+
+ def autocorrect_source(cop, source, file = nil)
+ cop.instance_variable_get(:@options)[:auto_correct] = true
+ processed_source = parse_source(source, file)
+ _investigate(cop, processed_source)
+
+ corrector =
+ RuboCop::Cop::Corrector.new(processed_source.buffer, cop.corrections)
+ corrector.rewrite
+ end
+
+ def _investigate(cop, processed_source)
+ forces = RuboCop::Cop::Force.all.each_with_object([]) do |klass, instances|
+ next unless cop.join_force?(klass)
+ instances << klass.new([cop])
+ end
+
+ commissioner =
+ RuboCop::Cop::Commissioner.new([cop], forces, raise_error: true)
+ commissioner.investigate(processed_source)
+ commissioner
+ end
+end
+
+module RuboCop
+ module Cop
+ class Cop
+ def messages
+ offenses.sort.map(&:message)
+ end
+
+ def highlights
+ offenses.sort.map { |o| o.location.source }
+ end
+ end
+ end
+end
+
+describe RuboCop::Cop::Style::ArrayLiteralDelimiter do
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ it 'does something' do
+ inspect_source(cop, '%w{foo bar baz}')
+
+ expect(cop.offenses.size).to eq(1)
+ expect(cop.offenses.map(&:line).sort).to eq([1])
+ expect(cop.highlights).to eq(['%w{foo bar baz}'])
+ end
+
+ it 'does something else' do
+ inspect_source(cop, '%w[foo bar baz]')
+
+ expect(cop.offenses.size).to eq(0)
+ end
+end