-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
method_definition_in_included.rb
107 lines (96 loc) · 2.83 KB
/
method_definition_in_included.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# frozen_string_literal: true
module RuboCop
module Cop
module Sevencop
# Do not define methods in `included` blocks.
#
# @example
# # bad
# module A
# extend ::ActiveSupport::Concern
#
# included do
# def foo
# end
# end
# end
#
# # good
# module A
# extend ::ActiveSupport::Concern
#
# def foo
# end
# end
class MethodDefinitionInIncluded < RuboCop::Cop::Base
extend AutoCorrector
include RangeHelp
include VisibilityHelp
MSG = 'Do not define methods in `included` blocks.'
# @param node [RuboCop::AST::DefNode]
# @return [void]
def on_def(node)
block = find_ancestor_included_block(node)
return unless block
add_offense(node) do |corrector|
corrector.insert_before(
range_with_comments_and_lines(block),
"#{range_with_comments_and_lines(node).source}\n".sub(
/\bdef /, "#{node_visibility(node)} def "
)
)
corrector.remove(
range_with_comments_and_lines(node)
)
end
end
private
# @param range1 [Parser::Source::Range]
# @param range2 [Parser::Source::Range]
# @return [Parser::Source::Range]
def add_range(
range1,
range2
)
range1.with(
begin_pos: [range1.begin_pos, range2.begin_pos].min,
end_pos: [range1.end_pos, range2.end_pos].max
)
end
# @param node [RuboCop::AST::DefNode]
# @return [RuboCop::AST::BlockNode, nil]
def find_ancestor_included_block(node)
if node.parent&.block_type?
node.parent if node.parent.method?(:included)
elsif node.parent&.begin_type?
node.parent.parent if node.parent.parent&.block_type? && node.parent.parent&.method?(:included)
end
end
# @param node [RuboCop::AST::DefNode]
# @return [Boolean]
def private?(node)
node_visibility(node) == :private
end
# @param node [RuboCop::AST::Node]
# @return [Paresr::Source::Range]
def range_with_comments(node)
ranges = [
node,
*processed_source.ast_with_comments[node]
].map(&:source_range)
ranges.reduce do |result, range|
add_range(result, range)
end
end
# @param node [RuboCop::AST::Node]
# @return [Parser::Source::Range]
def range_with_comments_and_lines(node)
range_by_whole_lines(
range_with_comments(node),
include_final_newline: true
)
end
end
end
end
end