diff options
author | Robert Speicher <rspeicher@gmail.com> | 2016-05-27 17:10:39 -0400 |
---|---|---|
committer | Robert Speicher <rspeicher@gmail.com> | 2016-05-27 17:10:39 -0400 |
commit | 439c304f5ed15cac416cb1a63e15c43fc300bbfd (patch) | |
tree | bec71e2b0d1ce0f3deabf0739570ab87ab351d04 | |
parent | f9bb9151b595fdc1afc1742bb51c816965908f53 (diff) | |
download | gitlab-ce-rs-array-literal-delimiter-cop.tar.gz |
WIP: Add custom cop for ArrayLiteralDelimiterrs-array-literal-delimiter-cop
-rw-r--r-- | .rubocop.yml | 4 | ||||
-rw-r--r-- | lib/rubocop/cop/style/array_literal_delimiter.rb | 43 | ||||
-rw-r--r-- | spec/lib/rubocop/cop/style/array_literal_delimiter_spec.rb | 102 |
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 |