Module: RuboCop::Cop::Util

Extended by:
AST::Sexp
Includes:
PathUtil
Included in:
Cop, LineBreakCorrector, StringLiteralCorrector
Defined in:
lib/rubocop/cop/util.rb

Overview

This module contains a collection of useful utility methods.

Constant Summary collapse

EQUALS_ASGN_NODES =
%i[lvasgn ivasgn cvasgn gvasgn
casgn masgn].freeze
SHORTHAND_ASGN_NODES =
%i[op_asgn or_asgn and_asgn].freeze
ASGN_NODES =
(EQUALS_ASGN_NODES + SHORTHAND_ASGN_NODES).freeze
MODIFIER_NODES =
%i[if while until].freeze
CONDITIONAL_NODES =
(MODIFIER_NODES + [:case]).freeze
LOGICAL_OPERATOR_NODES =
%i[and or].freeze
OPERATOR_METHODS =

http://phrogz.net/programmingruby/language.html#table_18.4 Backtick is added last just to help editors parse this code.

%w(
  | ^ & <=> == === =~ > >= < <= << >>
  + - * / % ** ~ +@ -@ !@ ~@ [] []= ! != !~
).map(&:to_sym).push(:'`').freeze
LITERAL_REGEX =

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

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

Class Method Summary collapse

Methods included from AST::Sexp

s

Methods included from PathUtil

absolute?, match_path?, pwd, relative_path, reset_pwd, smart_path

Class Method Details

.begins_its_line?(range) ⇒ Boolean

Returns:

  • (Boolean)


58
59
60
# File 'lib/rubocop/cop/util.rb', line 58

def begins_its_line?(range)
  (range.source_line =~ /\S/) == range.column
end

.comment_line?(line_source) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/rubocop/cop/util.rb', line 36

def comment_line?(line_source)
  line_source =~ /^\s*#/
end

.double_quotes_required?(string) ⇒ Boolean

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

Returns:

  • (Boolean)


82
83
84
85
86
87
88
89
90
# File 'lib/rubocop/cop/util.rb', line 82

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 "\\\\".
  string =~ /'|(?<! \\) \\{2}* \\ (?![\\"])/x
end

.escape_string(string) ⇒ Object



96
97
98
# File 'lib/rubocop/cop/util.rb', line 96

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.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rubocop/cop/util.rb', line 64

def first_part_of_call_chain(node)
  while node
    case node.type
    when :send
      receiver, _method_name, _args = *node
      node = receiver
    when :block
      method, _args, _body = *node
      node = method
    else
      break
    end
  end
  node
end

.interpret_string_escapes(string) ⇒ Object



108
109
110
# File 'lib/rubocop/cop/util.rb', line 108

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

.line_range(node) ⇒ Object



40
41
42
# File 'lib/rubocop/cop/util.rb', line 40

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

.needs_escaping?(string) ⇒ Boolean

Returns:

  • (Boolean)


92
93
94
# File 'lib/rubocop/cop/util.rb', line 92

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

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

Yields:

  • (sexp)


49
50
51
52
53
54
55
56
# File 'lib/rubocop/cop/util.rb', line 49

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

  yield sexp if Array(syms).include?(sexp.type)
  return if Array(excludes).include?(sexp.type)

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

.operator?(symbol) ⇒ Boolean

Returns:

  • (Boolean)


32
33
34
# File 'lib/rubocop/cop/util.rb', line 32

def operator?(symbol)
  OPERATOR_METHODS.include?(symbol)
end

.parentheses?(node) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
47
# File 'lib/rubocop/cop/util.rb', line 44

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

.same_line?(node1, node2) ⇒ Boolean

Returns:

  • (Boolean)


112
113
114
115
116
# File 'lib/rubocop/cop/util.rb', line 112

def same_line?(node1, node2)
  node1.respond_to?(:loc) &&
    node2.respond_to?(:loc) &&
    node1.loc.line == node2.loc.line
end

.to_string_literal(string) ⇒ Object



100
101
102
103
104
105
106
# File 'lib/rubocop/cop/util.rb', line 100

def to_string_literal(string)
  if needs_escaping?(string) && compatible_external_encoding_for?(string)
    string.inspect
  else
    "'#{string.gsub('\\') { '\\\\' }}'"
  end
end

.to_supported_styles(enforced_style) ⇒ Object



118
119
120
121
122
# File 'lib/rubocop/cop/util.rb', line 118

def to_supported_styles(enforced_style)
  enforced_style
    .sub(/^Enforced/, 'Supported')
    .sub('Style', 'Styles')
end

.tokens(node) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/rubocop/cop/util.rb', line 124

def tokens(node)
  @tokens ||= {}
  return @tokens[node.object_id] if @tokens[node.object_id]

  source_range = node.source_range
  begin_pos = source_range.begin_pos
  end_pos = source_range.end_pos

  @tokens[node.object_id] = processed_source.tokens.select do |token|
    token.end_pos <= end_pos && token.begin_pos >= begin_pos
  end
end