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

Add mixins folder #1056

Merged
merged 1 commit into from
Oct 23, 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
10 changes: 6 additions & 4 deletions lib/rubocop-rspec.rb
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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.