Module: RuboCop::Cop::Util

Overview

This module contains a collection of useful utility methods.

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



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

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)


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

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



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

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



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

def args_end(node)
  node.loc.expression.end
end

.begins_its_line?(range) ⇒ Boolean

Returns:

  • (Boolean)


100
101
102
# File 'lib/rubocop/cop/util.rb', line 100

def begins_its_line?(range)
  range.source_line.match?(LINE_BEGINS_REGEX_CACHE[range.column])
end

.comment_line?(line_source) ⇒ Boolean

This is a bad API

Returns:

  • (Boolean)


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

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)


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

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)


122
123
124
125
126
127
128
129
130
# File 'lib/rubocop/cop/util.rb', line 122

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



136
137
138
# File 'lib/rubocop/cop/util.rb', line 136

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.



106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/rubocop/cop/util.rb', line 106

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



171
172
173
# File 'lib/rubocop/cop/util.rb', line 171

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

.interpret_string_escapes(string) ⇒ Object



153
154
155
# File 'lib/rubocop/cop/util.rb', line 153

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

.line(node_or_range) ⇒ Object



157
158
159
160
161
162
163
# File 'lib/rubocop/cop/util.rb', line 157

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



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

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

.needs_escaping?(string) ⇒ Boolean

Returns:

  • (Boolean)


132
133
134
# File 'lib/rubocop/cop/util.rb', line 132

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

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

Yields:

  • (sexp)


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

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)


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

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

.same_line?(node1, node2) ⇒ Boolean

Returns:

  • (Boolean)


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

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

.to_string_literal(string) ⇒ Object



140
141
142
143
144
145
146
147
# File 'lib/rubocop/cop/util.rb', line 140

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



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

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



149
150
151
# File 'lib/rubocop/cop/util.rb', line 149

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