Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rubocop v0.87+ compatibility #179

Merged
merged 4 commits into from Aug 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -8,3 +8,5 @@
.bundle

.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml

gemfiles/Gemfile*.lock
1 change: 1 addition & 0 deletions .rubocop.yml
Expand Up @@ -5,4 +5,5 @@ AllCops:
TargetRubyVersion: 2.4
Exclude:
- 'vendor/**/*'
- 'gemfiles/vendor/**/*'
DisplayCopNames: true
5 changes: 3 additions & 2 deletions .travis.yml
@@ -1,12 +1,13 @@
language: ruby
before_install:
- rm ./Gemfile.lock
cache: bundler
rvm:
- 2.4.1
- 2.5
- 2.6
- 2.7
gemfile:
- gemfiles/Gemfile.rubocop-old
- gemfiles/Gemfile.rubocop-next
script:
- bundle exec rspec spec
- bundle exec rubocop
11 changes: 6 additions & 5 deletions Gemfile.lock
Expand Up @@ -5,6 +5,7 @@ PATH
activesupport
better_html (~> 1.0.7)
html_tokenizer
parser (>= 2.7.1.4)
rainbow
rubocop (~> 0.79)
smart_properties
Expand All @@ -23,7 +24,7 @@ GEM
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
ast (2.4.0)
ast (2.4.1)
better_html (1.0.15)
actionview (>= 4.0)
activesupport (>= 4.0)
Expand All @@ -42,16 +43,16 @@ GEM
i18n (1.8.1)
concurrent-ruby (~> 1.0)
jaro_winkler (1.5.4)
loofah (2.5.0)
loofah (2.6.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mini_portile2 (2.4.0)
minitest (5.13.0)
nokogiri (1.10.9)
nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
parallel (1.19.1)
parser (2.7.1.2)
ast (~> 2.4.0)
parser (2.7.1.4)
ast (~> 2.4.1)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
Expand Down
1 change: 1 addition & 0 deletions erb_lint.gemspec
Expand Up @@ -27,6 +27,7 @@ Gem::Specification.new do |s|
s.add_dependency('better_html', '~> 1.0.7')
s.add_dependency('html_tokenizer')
s.add_dependency('rubocop', '~> 0.79')
s.add_dependency('parser', '>= 2.7.1.4')
thegedge marked this conversation as resolved.
Show resolved Hide resolved
s.add_dependency('activesupport')
s.add_dependency('smart_properties')
s.add_dependency('rainbow')
Expand Down
5 changes: 5 additions & 0 deletions gemfiles/Gemfile.rubocop-next
@@ -0,0 +1,5 @@
# frozen_string_literal: true

eval_gemfile "../Gemfile"

gem "rubocop", ">= 0.87"
5 changes: 5 additions & 0 deletions gemfiles/Gemfile.rubocop-old
@@ -0,0 +1,5 @@
# frozen_string_literal: true

eval_gemfile "../Gemfile"

gem "rubocop", "< 0.87"
2 changes: 2 additions & 0 deletions lib/erb_lint.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require 'rubocop'

require 'erb_lint/corrector'
require 'erb_lint/file_loader'
require 'erb_lint/linter_config'
Expand Down
17 changes: 14 additions & 3 deletions lib/erb_lint/corrector.rb
Expand Up @@ -17,11 +17,22 @@ def corrections
end

def corrector
RuboCop::Cop::Corrector.new(@processed_source.source_buffer, corrections)
BASE.new(@processed_source.source_buffer, corrections)
end

def diagnostics
corrector.diagnostics
if ::RuboCop::Version::STRING.to_f >= 0.87
require 'rubocop/cop/legacy/corrector'
BASE = ::RuboCop::Cop::Legacy::Corrector

def diagnostics
[]
end
else
BASE = ::RuboCop::Cop::Corrector

def diagnostics
corrector.diagnostics
end
end
end
end
2 changes: 1 addition & 1 deletion lib/erb_lint/linters/hard_coded_string.rb
Expand Up @@ -63,7 +63,7 @@ def autocorrect(processed_source, offense)
string = offense.source_range.source
return unless (klass = load_corrector)
return unless string.strip.length > 1
node = RuboCop::AST::StrNode.new(:str, [string])
node = ::RuboCop::AST::StrNode.new(:str, [string])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for explicitly fully qualifying the Rubocop references?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first thing I wanted to check in the code was all dependencies on RuboCop. Given that erb_lint has a class called Rubocop (no capital 'C' though), this wasn't perfectly clear at first so I thought that it was a good idea to do this, instead of relying on the context or how the letter 'c' is capitalized.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm 👍 with fully qualifying external references (in general), but especially if there's a similarly named thing internally.

corrector = klass.new(node, processed_source.filename, corrector_i18n_load_path, offense.source_range)
corrector.autocorrect(tag_start: '<%= ', tag_end: ' %>')
rescue MissingCorrector, MissingI18nLoadPath
Expand Down
93 changes: 62 additions & 31 deletions lib/erb_lint/linters/rubocop.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true

require 'better_html'
require 'rubocop'
require 'tempfile'
require 'erb_lint/utils/offset_corrector'

Expand All @@ -26,7 +25,7 @@ def initialize(file_loader, config)
super
@only_cops = @config.only
custom_config = config_from_hash(@config.rubocop_config)
@rubocop_config = RuboCop::ConfigLoader.merge_with_default(custom_config, '')
@rubocop_config = ::RuboCop::ConfigLoader.merge_with_default(custom_config, '')
end

def run(processed_source)
Expand All @@ -35,17 +34,29 @@ def run(processed_source)
end
end

def autocorrect(processed_source, offense)
return unless offense.context

lambda do |corrector|
passthrough = Utils::OffsetCorrector.new(
processed_source,
corrector,
offense.context[:offset],
offense.context[:bound_range],
)
offense.context[:rubocop_correction].call(passthrough)
if ::RuboCop::Version::STRING.to_f >= 0.87
def autocorrect(_processed_source, offense)
return unless offense.context
rubocop_correction = offense.context[:rubocop_correction]
return unless rubocop_correction

lambda do |corrector|
corrector.import!(rubocop_correction, offset: offense.context[:offset])
end
end
else
def autocorrect(processed_source, offense)
return unless offense.context

lambda do |corrector|
passthrough = Utils::OffsetCorrector.new(
processed_source,
corrector,
offense.context[:offset],
offense.context[:bound_range],
)
offense.context[:rubocop_correction].call(passthrough)
end
end
end

Expand All @@ -62,29 +73,49 @@ def inspect_content(processed_source, erb_node)
original_source = code_node.loc.source
trimmed_source = original_source.sub(BLOCK_EXPR, '').sub(SUFFIX_EXPR, '')
alignment_column = code_node.loc.column
offset = code_node.loc.begin_pos - alignment_column
aligned_source = "#{' ' * alignment_column}#{trimmed_source}"

source = rubocop_processed_source(aligned_source, processed_source.filename)
return unless source.valid_syntax?

team = build_team
team.inspect_file(source)
team.cops.each do |cop|
correction_offset = 0
cop.offenses.reject(&:disabled?).each do |rubocop_offense|
if rubocop_offense.corrected?
correction = cop.corrections[correction_offset]
correction_offset += 1
end
activate_team(processed_source, source, offset, code_node, build_team)
end

if ::RuboCop::Version::STRING.to_f >= 0.87
def activate_team(processed_source, source, offset, code_node, team)
report = team.investigate(source)
report.offenses.each do |rubocop_offense|
next if rubocop_offense.disabled?

correction = rubocop_offense.corrector if rubocop_offense.corrected?

offset = code_node.loc.begin_pos - alignment_column
offense_range = processed_source
.to_source_range(rubocop_offense.location)
.offset(offset)

add_offense(rubocop_offense, offense_range, correction, offset, code_node.loc.range)
end
end
else
def activate_team(processed_source, source, offset, code_node, team)
team.inspect_file(source)
team.cops.each do |cop|
correction_offset = 0
cop.offenses.reject(&:disabled?).each do |rubocop_offense|
if rubocop_offense.corrected?
correction = cop.corrections[correction_offset]
correction_offset += 1
end

offense_range = processed_source
.to_source_range(rubocop_offense.location)
.offset(offset)

add_offense(rubocop_offense, offense_range, correction, offset, code_node.loc.range)
end
end
end
end

def tempfile_from(filename, content)
Expand All @@ -97,7 +128,7 @@ def tempfile_from(filename, content)
end

def rubocop_processed_source(content, filename)
RuboCop::ProcessedSource.new(
::RuboCop::ProcessedSource.new(
content,
@rubocop_config.target_ruby_version,
filename
Expand All @@ -106,15 +137,15 @@ def rubocop_processed_source(content, filename)

def cop_classes
if @only_cops.present?
selected_cops = RuboCop::Cop::Cop.all.select { |cop| cop.match?(@only_cops) }
RuboCop::Cop::Registry.new(selected_cops)
selected_cops = ::RuboCop::Cop::Cop.all.select { |cop| cop.match?(@only_cops) }
::RuboCop::Cop::Registry.new(selected_cops)
else
RuboCop::Cop::Registry.new(RuboCop::Cop::Cop.all)
::RuboCop::Cop::Registry.new(::RuboCop::Cop::Cop.all)
end
end

def build_team
RuboCop::Cop::Team.new(
::RuboCop::Cop::Team.new(
cop_classes,
@rubocop_config,
extra_details: true,
Expand All @@ -129,15 +160,15 @@ def config_from_hash(hash)
resolve_inheritance(hash, inherit_from)

tempfile_from('.erblint-rubocop', hash.to_yaml) do |tempfile|
RuboCop::ConfigLoader.load_file(tempfile.path)
::RuboCop::ConfigLoader.load_file(tempfile.path)
end
end

def resolve_inheritance(hash, inherit_from)
base_configs(inherit_from)
.reverse_each do |base_config|
base_config.each do |k, v|
hash[k] = hash.key?(k) ? RuboCop::ConfigLoader.merge(v, hash[k]) : v if v.is_a?(Hash)
hash[k] = hash.key?(k) ? ::RuboCop::ConfigLoader.merge(v, hash[k]) : v if v.is_a?(Hash)
end
end
end
Expand All @@ -146,7 +177,7 @@ def base_configs(inherit_from)
regex = URI::DEFAULT_PARSER.make_regexp(%w(http https))
configs = Array(inherit_from).compact.map do |base_name|
if base_name =~ /\A#{regex}\z/
RuboCop::ConfigLoader.load_file(RuboCop::RemoteConfig.new(base_name, Dir.pwd))
::RuboCop::ConfigLoader.load_file(::RuboCop::RemoteConfig.new(base_name, Dir.pwd))
else
config_from_hash(@file_loader.yaml(base_name))
end
Expand Down
4 changes: 2 additions & 2 deletions lib/erb_lint/linters/rubocop_text.rb
Expand Up @@ -28,9 +28,9 @@ def descendant_nodes(parser)
end

def cop_classes
selected_cops = RuboCop::Cop::Cop.all.select { |cop| cop.match?(@only_cops) }
selected_cops = ::RuboCop::Cop::Cop.all.select { |cop| cop.match?(@only_cops) }

RuboCop::Cop::Registry.new(selected_cops)
::RuboCop::Cop::Registry.new(selected_cops)
end
end
end
Expand Down