Module: RuboCop::Cop::Util

Overview

This module contains a collection of useful utility methods. rubocop:disable Metrics/ModuleLength

Constant Summary collapse

LITERAL_REGEX =

Match literal regex characters, not including anchors, character classes, alternatives, groups, repetitions, references, etc

%r{[\w\s\-,"'!#%&<>=;:`~/]|\\[^AbBdDgGhHkpPRwWXsSzZ0-9]}.freeze

Constants included from PathUtil

PathUtil::HIDDEN_FILE_PATTERN

Class Method Summary collapse

Methods included from PathUtil

absolute?, glob?, hidden_dir?, hidden_file?, hidden_file_in_not_hidden_dir?, match_path?, maybe_hidden_file?, relative_path, smart_path

Class Method Details

.add_parentheses(node, corrector) ⇒ Object

rubocop:disable Metrics/AbcSize, Metrics/MethodLength



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/rubocop/cop/util.rb', line 35

def add_parentheses(node, corrector)
  if node.args_type?
    arguments_range = node.source_range
    args_with_space = range_with_surrounding_space(arguments_range, side: :left)
    leading_space = range_between(args_with_space.begin_pos, arguments_range.begin_pos)
    corrector.replace(leading_space, '(')
    corrector.insert_after(arguments_range, ')')
  elsif !node.respond_to?(:arguments)
    corrector.wrap(node, '(', ')')
  elsif node.arguments.empty?
    corrector.insert_after(node, '()')
  else
    args_begin = args_begin(node)

    corrector.remove(args_begin)
    corrector.insert_before(args_begin, '(')
    corrector.insert_after(args_end(node), ')')
  end
end

.any_descendant?(node, *types) ⇒ Boolean

rubocop:enable Metrics/AbcSize, Metrics/MethodLength

Returns:

  • (Boolean)


56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/rubocop/cop/util.rb', line 56

def any_descendant?(node, *types)
  if block_given?
    node.each_descendant(*types) do |descendant|
      return true if yield(descendant)
    end
  else
    # Use a block version to avoid allocating enumerators.
    node.each_descendant do # rubocop:disable Lint/UnreachableLoop
      return true
    end
  end

  false
end

.args_begin(node) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rubocop/cop/util.rb', line 71

def args_begin(node)
  loc = node.loc
  selector = if node.super_type? || node.yield_type?
               loc.keyword
             elsif node.def_type? || node.defs_type?
               loc.name
             else
               loc.selector
             end
  selector.end.resize(1)
end

.args_end(node) ⇒ Object



83
84
85
# File 'lib/rubocop/cop/util.rb', line 83

def args_end(node)
  node.source_range.end
end

.begins_its_line?(range) ⇒ Boolean

Returns:

  • (Boolean)


104
105
106
107
108
109
110
# File 'lib/rubocop/cop/util.rb', line 104

def begins_its_line?(range)
  if (regex = LINE_BEGINS_REGEX_CACHE[range.column])
    range.source_line.match?(regex)
  else
    range.source_line.index(/\S/) == range.column
  end
end

.comment_line?(line_source) ⇒ Boolean

This is a bad API

Returns:

  • (Boolean)


17
18
19
# File 'lib/rubocop/cop/util.rb', line 17

def comment_line?(line_source)
  /^\s*#/.match?(line_source)
end

.comment_lines?(node) ⇒ Boolean

Deprecated.

Use ProcessedSource#line_with_comment?, contains_comment? or similar

Returns:

  • (Boolean)


22
23
24
# File 'lib/rubocop/cop/util.rb', line 22

def comment_lines?(node)
  processed_source[line_range(node)].any? { |line| comment_line?(line) }
end

.double_quotes_required?(string) ⇒ Boolean

If converting a string to Ruby string literal source code, must double quotes be used?

Returns:

  • (Boolean)


130
131
132
133
134
135
136
137
138
# File 'lib/rubocop/cop/util.rb', line 130

def double_quotes_required?(string)
  # Double quotes are required for strings which either:
  # - Contain single quotes
  # - Contain non-printable characters, which must use an escape

  # Regex matches IF there is a ' or there is a \\ in the string that is
  # not preceded/followed by another \\ (e.g. "\\x34") but not "\\\\".
  /'|(?<! \\) \\{2}* \\ (?![\\"])/x.match?(string)
end

.escape_string(string) ⇒ Object



144
145
146
# File 'lib/rubocop/cop/util.rb', line 144

def escape_string(string)
  string.inspect[1..-2].tap { |s| s.gsub!('\\"', '"') }
end

.first_part_of_call_chain(node) ⇒ Object

Returns, for example, a bare if node if the given node is an if with calls chained to the end of it.



114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/rubocop/cop/util.rb', line 114

def first_part_of_call_chain(node)
  while node
    case node.type
    when :send
      node = node.receiver
    when :block
      node = node.send_node
    else
      break
    end
  end
  node
end

.indent(node, offset: 0) ⇒ Object



179
180
181
# File 'lib/rubocop/cop/util.rb', line 179

def indent(node, offset: 0)
  ' ' * (node.loc.column + offset)
end

.interpret_string_escapes(string) ⇒ Object



161
162
163
# File 'lib/rubocop/cop/util.rb', line 161

def interpret_string_escapes(string)
  StringInterpreter.interpret(string)
end

.line(node_or_range) ⇒ Object



165
166
167
168
169
170
171
# File 'lib/rubocop/cop/util.rb', line 165

def line(node_or_range)
  if node_or_range.respond_to?(:line)
    node_or_range.line
  elsif node_or_range.respond_to?(:loc)
    node_or_range.loc.line
  end
end

.line_range(node) ⇒ Object



26
27
28
# File 'lib/rubocop/cop/util.rb', line 26

def line_range(node)
  node.first_line..node.last_line
end

.needs_escaping?(string) ⇒ Boolean

Returns:

  • (Boolean)


140
141
142
# File 'lib/rubocop/cop/util.rb', line 140

def needs_escaping?(string)
  double_quotes_required?(escape_string(string))
end

.on_node(syms, sexp, excludes = []) {|sexp| ... } ⇒ Object

Yields:

  • (sexp)


87
88
89
90
91
92
93
94
# File 'lib/rubocop/cop/util.rb', line 87

def on_node(syms, sexp, excludes = [], &block)
  return to_enum(:on_node, syms, sexp, excludes) unless block

  yield sexp if include_or_equal?(syms, sexp.type)
  return if include_or_equal?(excludes, sexp.type)

  sexp.each_child_node { |elem| on_node(syms, elem, excludes, &block) }
end

.parentheses?(node) ⇒ Boolean

Returns:

  • (Boolean)


30
31
32
# File 'lib/rubocop/cop/util.rb', line 30

def parentheses?(node)
  node.loc.respond_to?(:end) && node.loc.end && node.loc.end.is?(')')
end

.same_line?(node1, node2) ⇒ Boolean

Returns:

  • (Boolean)


173
174
175
176
177
# File 'lib/rubocop/cop/util.rb', line 173

def same_line?(node1, node2)
  line1 = line(node1)
  line2 = line(node2)
  line1 && line2 && line1 == line2
end

.to_string_literal(string) ⇒ Object



148
149
150
151
152
153
154
155
# File 'lib/rubocop/cop/util.rb', line 148

def to_string_literal(string)
  if needs_escaping?(string) && compatible_external_encoding_for?(string)
    string.inspect
  else
    # In a single-quoted strings, double quotes don't need to be escaped
    "'#{string.gsub('\\') { '\\\\' }.gsub('\"', '"')}'"
  end
end

.to_supported_styles(enforced_style) ⇒ Object



185
186
187
188
# File 'lib/rubocop/cop/util.rb', line 185

def to_supported_styles(enforced_style)
  @to_supported_styles_cache[enforced_style] ||=
    enforced_style.sub(/^Enforced/, 'Supported').sub('Style', 'Styles')
end

.trim_string_interpolation_escape_character(str) ⇒ Object



157
158
159
# File 'lib/rubocop/cop/util.rb', line 157

def trim_string_interpolation_escape_character(str)
  str.gsub(/\\\#\{(.*?)\}/) { "\#{#{Regexp.last_match(1)}}" }
end