Skip to content

Commit a8d756a

Browse files
authored
Merge pull request #915 from rubocop-hq/cleanup-workaround
Cleanup workaround
2 parents 3254778 + dc5d6a0 commit a8d756a

File tree

6 files changed

+51
-75
lines changed

6 files changed

+51
-75
lines changed

bin/build_config

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@ require 'rubocop-rspec'
99
require 'rubocop/rspec/description_extractor'
1010
require 'rubocop/rspec/config_formatter'
1111

12-
glob = File.join(__dir__, '..', 'lib', 'rubocop', 'cop', 'rspec',
12+
glob = File.join('lib', 'rubocop', 'cop', 'rspec',
1313
'{,capybara,factory_bot,rails}', '*.rb')
14-
YARD.parse(Dir[glob], [])
14+
# Due to YARD's sensitivity to file require order (as of 0.9.25),
15+
# we have to prepend the list with our base cop, RuboCop::Cop::RSpec::Cop.
16+
# Otherwise, cop's parent class for cops loaded before our base cop class
17+
# are detected as RuboCop::Cop::Cop, and that complicates the detection
18+
# of their relation with RuboCop RSpec.
19+
rspec_cop_path = File.join('lib', 'rubocop', 'cop', 'rspec', 'cop.rb')
20+
YARD.parse(Dir[glob].prepend(rspec_cop_path), [])
1521

1622
descriptions = RuboCop::RSpec::DescriptionExtractor.new(YARD::Registry.all).to_h
1723
current_config = YAML.load_file('config/default.yml')

lib/rubocop/cop/rspec/cop.rb

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,22 @@
22

33
module RuboCop
44
module Cop
5-
WorkaroundCop = Cop.dup
6-
7-
# Clone of the the normal RuboCop::Cop::Cop class so we can rewrite
8-
# the inherited method without breaking functionality
9-
class WorkaroundCop
10-
# Remove the Cop.inherited method to be a noop. Our RSpec::Cop
11-
# class will invoke the inherited hook instead
12-
class << self
13-
undef inherited
14-
def inherited(*) end
15-
end
16-
17-
# Special case `Module#<` so that the rspec support rubocop exports
18-
# is compatible with our subclass
19-
def self.<(other)
20-
other.equal?(RuboCop::Cop::Cop) || super
21-
end
22-
end
23-
private_constant(:WorkaroundCop)
24-
255
module RSpec
26-
# @abstract parent class to rspec cops
6+
# @abstract parent class to RSpec cops
277
#
288
# The criteria for whether rubocop-rspec analyzes a certain ruby file
299
# is configured via `AllCops/RSpec`. For example, if you want to
3010
# customize your project to scan all files within a `test/` directory
3111
# then you could add this to your configuration:
3212
#
3313
# @example configuring analyzed paths
34-
#
35-
# AllCops:
36-
# RSpec:
37-
# Patterns:
38-
# - '_test.rb$'
39-
# - '(?:^|/)test/'
40-
class Cop < WorkaroundCop
14+
# # .rubocop.yml
15+
# # AllCops:
16+
# # RSpec:
17+
# # Patterns:
18+
# # - '_test.rb$'
19+
# # - '(?:^|/)test/'
20+
class Cop < ::RuboCop::Cop::Cop
4121
include RuboCop::RSpec::Language
4222
include RuboCop::RSpec::Language::NodePattern
4323

lib/rubocop/rspec/description_extractor.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def to_h
2121

2222
# Decorator of a YARD code object for working with documented rspec cops
2323
class CodeObject
24-
COP_CLASS_NAMES = %w[RuboCop::Cop RuboCop::Cop::RSpec::Cop].freeze
24+
COP_CLASS_NAME = 'RuboCop::Cop::RSpec::Cop'
2525
RSPEC_NAMESPACE = 'RuboCop::Cop::RSpec'
2626

2727
def initialize(yardoc)
@@ -68,11 +68,7 @@ def documented_constant
6868
end
6969

7070
def cop_subclass?
71-
# YARD superclass resolution is a bit flaky: All classes loaded before
72-
# RuboCop::Cop::WorkaroundCop are shown as having RuboCop::Cop as
73-
# superclass, while all the following classes are listed as having
74-
# RuboCop::Cop::RSpec::Cop as their superclass.
75-
COP_CLASS_NAMES.include?(yardoc.superclass.path)
71+
yardoc.superclass.path == COP_CLASS_NAME
7672
end
7773

7874
def abstract?

spec/rubocop/cop/rspec/cop_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
end
2121

2222
let(:fake_cop) do
23-
stub_const('RuboCop::RSpec', Module.new)
2423
# rubocop:disable Style/ClassAndModuleChildren
2524
# rubocop:disable RSpec/LeakyConstantDeclaration
2625
class RuboCop::RSpec::FakeCop < described_class

spec/rubocop/rspec/description_extractor_spec.rb

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,19 @@ def bar
4242
YARD::Registry.all
4343
end
4444

45+
let(:temp_class) do
46+
temp = RuboCop::Cop::Cop.dup
47+
temp.class_exec do
48+
class << self
49+
undef inherited
50+
def inherited(*) end
51+
end
52+
end
53+
temp
54+
end
55+
4556
def stub_cop_const(name)
46-
stub_const(
47-
"RuboCop::Cop::RSpec::#{name}",
48-
Class.new(RuboCop::Cop.const_get(:WorkaroundCop))
49-
)
57+
stub_const("RuboCop::Cop::RSpec::#{name}", Class.new(temp_class))
5058
end
5159

5260
before do

tasks/cops_documentation.rake

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ task generate_cops_documentation: :yard_for_generate_documentation do
8585
h3('Configurable attributes') + to_table(header, content)
8686
end
8787

88-
# rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
89-
def configurable_values(pars, name)
88+
def configurable_values(pars, name) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
9089
case name
9190
when /^Enforced/
9291
supported_style_name = RuboCop::Cop::Util.to_supported_styles(name)
@@ -110,7 +109,6 @@ task generate_cops_documentation: :yard_for_generate_documentation do
110109
end
111110
end
112111
end
113-
# rubocop:enable Metrics/CyclomaticComplexity,Metrics/MethodLength
114112

115113
def to_table(header, content)
116114
table = [
@@ -121,8 +119,7 @@ task generate_cops_documentation: :yard_for_generate_documentation do
121119
table.join("\n") + "\n"
122120
end
123121

124-
# rubocop:disable Metrics/MethodLength
125-
def format_table_value(val)
122+
def format_table_value(val) # rubocop:disable Metrics/MethodLength
126123
value =
127124
case val
128125
when Array
@@ -136,20 +133,19 @@ task generate_cops_documentation: :yard_for_generate_documentation do
136133
end
137134
value.gsub("#{Dir.pwd}/", '').rstrip
138135
end
139-
# rubocop:enable Metrics/MethodLength
140136

141137
def cop_urls(config, cop)
142138
rubocop_version = Gem::Version.new(RuboCop::Version::STRING)
143139

144-
# Since Rubocop v0.75.0 and above, MessageAnnotator#new changed from:
140+
# Since RuboCop v0.75.0 and above, MessageAnnotator#new changed from:
145141
# def initialize(config, cop_config, options)
146142
# to:
147143
# def initialize(config, cop_name, cop_config, options)
148144
#
149-
# Since this library has a loose Rubocop dependency, we select the
145+
# Since this library has a loose RuboCop dependency, we select the
150146
# right arguments based on the installed version.
151147
#
152-
# TODO: When Rubocop < 0.75 is no longer supported, remove the second half
148+
# TODO: When RuboCop < 0.75 is no longer supported, remove the second half
153149
# of this condition.
154150

155151
if rubocop_version >= Gem::Version.new('0.75.0')
@@ -172,30 +168,29 @@ task generate_cops_documentation: :yard_for_generate_documentation do
172168
content
173169
end
174170

175-
# rubocop:disable Metrics/AbcSize
176-
# rubocop:disable Metrics/MethodLength
177-
def print_cops_of_department(cops, department, config)
178-
selected_cops = cops_of_department(cops, department).select do |cop|
179-
cop.to_s.start_with?('RuboCop::Cop::RSpec')
171+
def selected_cops(cops, department)
172+
cops_of_department(cops, department.to_sym).select do |cop|
173+
cop.name.start_with?('RuboCop::Cop::RSpec') &&
174+
cop.name != 'RuboCop::Cop::RSpec::Cop'
180175
end
176+
end
177+
178+
def print_cops_of_department(cops, department, config) # rubocop:disable Metrics/MethodLength
179+
selected_cops = selected_cops(cops, department)
181180
return if selected_cops.empty?
182181

183-
content = +"# #{department}\n"
184-
selected_cops.each do |cop|
185-
content << print_cop_with_doc(cop, config)
186-
end
182+
content = [
183+
"# #{department}\n",
184+
*selected_cops.map { |cop| print_cop_with_doc(cop, config) }
185+
].join
187186
file_name = "#{Dir.pwd}/manual/cops_#{department.downcase}.md"
188187
File.open(file_name, 'w') do |file|
189188
puts "* generated #{file_name}"
190-
file.write(content.strip + "\n")
189+
file.write(content)
191190
end
192191
end
193-
# rubocop:enable Metrics/AbcSize
194-
# rubocop:enable Metrics/MethodLength
195192

196-
# rubocop:disable Metrics/AbcSize
197-
# rubocop:disable Metrics/MethodLength
198-
def print_cop_with_doc(cop, config)
193+
def print_cop_with_doc(cop, config) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
199194
t = config.for_cop(cop)
200195
non_display_keys = %w[Description Enabled StyleGuide Reference]
201196
pars = t.reject { |k| non_display_keys.include? k }
@@ -209,15 +204,9 @@ task generate_cops_documentation: :yard_for_generate_documentation do
209204
end
210205
cops_body(config, cop, description, examples_object, pars)
211206
end
212-
# rubocop:enable Metrics/AbcSize
213-
# rubocop:enable Metrics/MethodLength
214207

215-
# rubocop:disable Metrics/AbcSize
216-
# rubocop:disable Metrics/MethodLength
217208
def table_of_content_for_department(cops, department)
218-
selected_cops = cops_of_department(cops, department.to_sym).select do |cop|
219-
cop.to_s.start_with?('RuboCop::Cop::RSpec')
220-
end
209+
selected_cops = selected_cops(cops, department)
221210
return if selected_cops.empty?
222211

223212
type_title = department[0].upcase + department[1..-1]
@@ -230,8 +219,6 @@ task generate_cops_documentation: :yard_for_generate_documentation do
230219

231220
content
232221
end
233-
# rubocop:enable Metrics/AbcSize
234-
# rubocop:enable Metrics/MethodLength
235222

236223
def print_table_of_contents(cops)
237224
path = "#{Dir.pwd}/manual/cops.md"
@@ -254,7 +241,7 @@ task generate_cops_documentation: :yard_for_generate_documentation do
254241
.map(&:to_s)
255242
.sort
256243
.map { |department| table_of_content_for_department(cops, department) }
257-
.reject(&:nil?)
244+
.compact
258245
.join("\n")
259246
end
260247

0 commit comments

Comments
 (0)