Skip to content

Commit

Permalink
Add mixins folder
Browse files Browse the repository at this point in the history
This moves several files to a new `mixins/` folder. I was going to add
some new macros, per [this comment][1], but thought it might clutter
things up a bit to put them in the root folder. I thought of adding a
`macros/` folder, but decided to emulate the [rubocop source][2]
instead.

[1]: #934 (comment)
[2]: https://github.com/rubocop-hq/rubocop/tree/master/lib/rubocop/cop/mixin
  • Loading branch information
mockdeep authored and pirj committed Nov 2, 2020
1 parent 29459ae commit 29c4e54
Show file tree
Hide file tree
Showing 25 changed files with 171 additions and 158 deletions.
10 changes: 6 additions & 4 deletions lib/rubocop-rspec.rb
Expand Up @@ -12,17 +12,19 @@
require_relative 'rubocop/rspec/wording'
require_relative 'rubocop/rspec/language'
require_relative 'rubocop/rspec/language/node_pattern'
require_relative 'rubocop/rspec/top_level_group'

require_relative 'rubocop/cop/rspec/mixin/top_level_group'
require_relative 'rubocop/cop/rspec/mixin/variable'
require_relative 'rubocop/cop/rspec/mixin/final_end_location'
require_relative 'rubocop/cop/rspec/mixin/empty_line_separation'

require_relative 'rubocop/rspec/concept'
require_relative 'rubocop/rspec/example_group'
require_relative 'rubocop/rspec/example'
require_relative 'rubocop/rspec/hook'
require_relative 'rubocop/rspec/variable'
require_relative 'rubocop/cop/rspec/base'
require_relative 'rubocop/rspec/align_let_brace'
require_relative 'rubocop/rspec/factory_bot'
require_relative 'rubocop/rspec/final_end_location'
require_relative 'rubocop/rspec/empty_line_separation'
require_relative 'rubocop/rspec/corrector/move_node'

RuboCop::RSpec::Inject.defaults!
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/describe_class.rb
Expand Up @@ -35,7 +35,7 @@ module RSpec
# describe "A feature example", type: :feature do
# end
class DescribeClass < Base
include RuboCop::RSpec::TopLevelGroup
include TopLevelGroup

MSG = 'The first argument to describe should be '\
'the class or module being tested.'
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/describe_method.rb
Expand Up @@ -17,7 +17,7 @@ module RSpec
# describe MyClass, '.my_class_method' do
# end
class DescribeMethod < Base
include RuboCop::RSpec::TopLevelGroup
include TopLevelGroup

MSG = 'The second argument to describe should be the method '\
"being tested. '#instance' or '.class'."
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/empty_line_after_example.rb
Expand Up @@ -43,7 +43,7 @@ module RSpec
#
class EmptyLineAfterExample < Base
extend AutoCorrector
include RuboCop::RSpec::EmptyLineSeparation
include EmptyLineSeparation

MSG = 'Add an empty line after `%<example>s`.'

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/empty_line_after_example_group.rb
Expand Up @@ -25,7 +25,7 @@ module RSpec
#
class EmptyLineAfterExampleGroup < Base
extend AutoCorrector
include RuboCop::RSpec::EmptyLineSeparation
include EmptyLineSeparation

MSG = 'Add an empty line after `%<example_group>s`.'

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/empty_line_after_final_let.rb
Expand Up @@ -18,7 +18,7 @@ module RSpec
# it { does_something }
class EmptyLineAfterFinalLet < Base
extend AutoCorrector
include RuboCop::RSpec::EmptyLineSeparation
include EmptyLineSeparation

MSG = 'Add an empty line after the last `%<let>s`.'

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/empty_line_after_hook.rb
Expand Up @@ -35,7 +35,7 @@ module RSpec
#
class EmptyLineAfterHook < Base
extend AutoCorrector
include RuboCop::RSpec::EmptyLineSeparation
include EmptyLineSeparation

MSG = 'Add an empty line after `%<hook>s`.'

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/empty_line_after_subject.rb
Expand Up @@ -16,7 +16,7 @@ module RSpec
# let(:foo) { bar }
class EmptyLineAfterSubject < Base
extend AutoCorrector
include RuboCop::RSpec::EmptyLineSeparation
include EmptyLineSeparation

MSG = 'Add an empty line after `%<subject>s`.'

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/file_path.rb
Expand Up @@ -57,7 +57,7 @@ module RSpec
# my_class_spec.rb # describe MyClass, '#method'
#
class FilePath < Base
include RuboCop::RSpec::TopLevelGroup
include TopLevelGroup

MSG = 'Spec path should end with `%<suffix>s`.'

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/instance_variable.rb
Expand Up @@ -47,7 +47,7 @@ module RSpec
# end
#
class InstanceVariable < Base
include RuboCop::RSpec::TopLevelGroup
include TopLevelGroup

MSG = 'Avoid instance variables – use let, ' \
'a method call, or a local variable (if possible).'
Expand Down
51 changes: 51 additions & 0 deletions lib/rubocop/cop/rspec/mixin/empty_line_separation.rb
@@ -0,0 +1,51 @@
# frozen_string_literal: true

module RuboCop
module Cop
module RSpec
# Helps determine the offending location if there is not an empty line
# following the node. Allows comments to follow directly after.
module EmptyLineSeparation
include FinalEndLocation
include RangeHelp

def missing_separating_line_offense(node)
return if last_child?(node)

missing_separating_line(node) do |location|
msg = yield(node.method_name)
add_offense(location, message: msg) do |corrector|
corrector.insert_after(location.end, "\n")
end
end
end

def missing_separating_line(node)
line = final_end_location(node).line

line += 1 while comment_line?(processed_source[line])

return if processed_source[line].blank?

yield offending_loc(line)
end

def offending_loc(last_line)
offending_line = processed_source[last_line - 1]

content_length = offending_line.lstrip.length
start = offending_line.length - content_length

source_range(processed_source.buffer,
last_line, start, content_length)
end

def last_child?(node)
return true unless node.parent&.begin_type?

node.equal?(node.parent.children.last)
end
end
end
end
end
19 changes: 19 additions & 0 deletions lib/rubocop/cop/rspec/mixin/final_end_location.rb
@@ -0,0 +1,19 @@
# frozen_string_literal: true

module RuboCop
module Cop
module RSpec
# Helps find the true end location of nodes which might contain heredocs.
module FinalEndLocation
def final_end_location(start_node)
heredoc_endings =
start_node.each_node(:str, :dstr, :xstr)
.select(&:heredoc?)
.map { |node| node.loc.heredoc_end }

[start_node.loc.end, *heredoc_endings].max_by(&:line)
end
end
end
end
end
61 changes: 61 additions & 0 deletions lib/rubocop/cop/rspec/mixin/top_level_group.rb
@@ -0,0 +1,61 @@
# frozen_string_literal: true

module RuboCop
module Cop
module RSpec
# Helper methods for top level example group cops
module TopLevelGroup
extend RuboCop::NodePattern::Macros
include RuboCop::RSpec::Language

def_node_matcher :example_or_shared_group?,
(ExampleGroups::ALL + SharedGroups::ALL).block_pattern

def on_new_investigation
super

return unless root_node

top_level_groups.each do |node|
on_top_level_example_group(node) if example_group?(node)
on_top_level_group(node)
end
end

def top_level_groups
@top_level_groups ||=
top_level_nodes(root_node).select do |node|
example_or_shared_group?(node)
end
end

private

# Dummy methods to be overridden in the consumer
def on_top_level_example_group(_node); end

def on_top_level_group(_node); end

def top_level_group?(node)
top_level_groups.include?(node)
end

def top_level_nodes(node)
if node.nil?
[]
elsif node.begin_type?
node.children
elsif node.module_type? || node.class_type?
top_level_nodes(node.body)
else
[node]
end
end

def root_node
processed_source.ast
end
end
end
end
end
18 changes: 18 additions & 0 deletions lib/rubocop/cop/rspec/mixin/variable.rb
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module RuboCop
module Cop
module RSpec
# Helps check offenses with variable definitions
module Variable
include RuboCop::RSpec::Language
extend RuboCop::NodePattern::Macros

def_node_matcher :variable_definition?, <<~PATTERN
(send nil? #{(Helpers::ALL + Subject::ALL).node_pattern_union}
$({sym str dsym dstr} ...) ...)
PATTERN
end
end
end
end
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/multiple_describes.rb
Expand Up @@ -23,7 +23,7 @@ module RSpec
# end
# end
class MultipleDescribes < Base
include RuboCop::RSpec::TopLevelGroup
include TopLevelGroup

MSG = 'Do not use multiple top-level example groups - '\
'try to nest them.'
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/multiple_memoized_helpers.rb
Expand Up @@ -85,7 +85,7 @@ module RSpec
#
class MultipleMemoizedHelpers < Base
include ConfigurableMax
include RuboCop::RSpec::Variable
include Variable

MSG = 'Example group has too many memoized helpers [%<count>d/%<max>d]'

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/nested_groups.rb
Expand Up @@ -87,7 +87,7 @@ module RSpec
#
class NestedGroups < Base
include ConfigurableMax
include RuboCop::RSpec::TopLevelGroup
include TopLevelGroup

MSG = 'Maximum example group nesting exceeded [%<total>d/%<max>d].'

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/subject_stub.rb
Expand Up @@ -22,7 +22,7 @@ module RSpec
# end
#
class SubjectStub < Base
include RuboCop::RSpec::TopLevelGroup
include TopLevelGroup

MSG = 'Do not stub methods of the object under test.'

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/variable_definition.rb
Expand Up @@ -24,7 +24,7 @@ module RSpec
# let('user_name') { 'Adam' }
class VariableDefinition < Base
include ConfigurableEnforcedStyle
include RuboCop::RSpec::Variable
include Variable

MSG = 'Use %<style>s for variable names.'

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/variable_name.rb
Expand Up @@ -42,7 +42,7 @@ module RSpec
class VariableName < Base
include ConfigurableNaming
include IgnoredPattern
include RuboCop::RSpec::Variable
include Variable

MSG = 'Use %<style>s for variable names.'

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/rspec/corrector/move_node.rb
Expand Up @@ -6,7 +6,7 @@ module Corrector
# Helper methods to move a node
class MoveNode
include RuboCop::Cop::RangeHelp
include RuboCop::RSpec::FinalEndLocation
include RuboCop::Cop::RSpec::FinalEndLocation

attr_reader :original, :corrector, :processed_source

Expand Down
48 changes: 0 additions & 48 deletions lib/rubocop/rspec/empty_line_separation.rb

This file was deleted.

17 changes: 0 additions & 17 deletions lib/rubocop/rspec/final_end_location.rb

This file was deleted.

0 comments on commit 29c4e54

Please sign in to comment.