Class: RuboCop::DirectiveComment

Inherits:
Object
  • Object
show all
Defined in:
lib/rubocop/directive_comment.rb

Overview

This class wraps the ‘Parser::Source::Comment` object that represents a special `rubocop:disable` and `rubocop:enable` comment and exposes what cops it contains.

Constant Summary collapse

LINT_DEPARTMENT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'Lint'
LINT_REDUNDANT_DIRECTIVE_COP =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"#{LINT_DEPARTMENT}/RedundantCopDisableDirective"
LINT_SYNTAX_COP =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"#{LINT_DEPARTMENT}/Syntax"
COP_NAME_PATTERN =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'([A-Za-z]\w+/)*(?:[A-Za-z]\w+)'
COP_NAME_PATTERN_NC =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'(?:[A-Za-z]\w+/)*[A-Za-z]\w+'
COP_NAMES_PATTERN_NC =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"(?:#{COP_NAME_PATTERN_NC} , )*#{COP_NAME_PATTERN_NC}"
COP_NAMES_PATTERN =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}"
COPS_PATTERN =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"(all|#{COP_NAMES_PATTERN})"
PUSH_POP_ARGS_PATTERN =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"([+\\-]#{COP_NAME_PATTERN_NC}(?:\\s+[+\\-]#{COP_NAME_PATTERN_NC})*)"
AVAILABLE_MODES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

%w[disable enable todo push pop].freeze
DIRECTIVE_MARKER_PATTERN =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'# rubocop : '
DIRECTIVE_MARKER_REGEXP =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Regexp.new(DIRECTIVE_MARKER_PATTERN.gsub(' ', '\s*'))
DIRECTIVE_HEADER_PATTERN =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"#{DIRECTIVE_MARKER_PATTERN}((?:#{AVAILABLE_MODES.join('|')}))\\b"
DIRECTIVE_COMMENT_REGEXP =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Regexp.new(
  "#{DIRECTIVE_HEADER_PATTERN}(?:\\s+#{COPS_PATTERN}|\\s+#{PUSH_POP_ARGS_PATTERN})?"
    .gsub(' ', '\s*')
)
TRAILING_COMMENT_MARKER =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'--'
MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Regexp.new(
  "\\A#{DIRECTIVE_HEADER_PATTERN}\\s*\\z".gsub(' ', '\s*')
)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(comment, cop_registry = Cop::Registry.global) ⇒ DirectiveComment

Returns a new instance of DirectiveComment.



52
53
54
55
56
57
# File 'lib/rubocop/directive_comment.rb', line 52

def initialize(comment, cop_registry = Cop::Registry.global)
  @comment = comment
  @cop_registry = cop_registry
  @match_data = comment.text.match(DIRECTIVE_COMMENT_REGEXP)
  @mode, @cops = match_captures
end

Instance Attribute Details

#commentObject (readonly)

Returns the value of attribute comment.



50
51
52
# File 'lib/rubocop/directive_comment.rb', line 50

def comment
  @comment
end

#cop_registryObject (readonly)

Returns the value of attribute cop_registry.



50
51
52
# File 'lib/rubocop/directive_comment.rb', line 50

def cop_registry
  @cop_registry
end

#copsObject (readonly)

Returns the value of attribute cops.



50
51
52
# File 'lib/rubocop/directive_comment.rb', line 50

def cops
  @cops
end

#modeObject (readonly)

Returns the value of attribute mode.



50
51
52
# File 'lib/rubocop/directive_comment.rb', line 50

def mode
  @mode
end

Class Method Details

.before_comment(line) ⇒ Object



46
47
48
# File 'lib/rubocop/directive_comment.rb', line 46

def self.before_comment(line)
  line.split(DIRECTIVE_COMMENT_REGEXP).first
end

Instance Method Details

#all_cops?Boolean

Checks if all cops specified in this directive

Returns:

  • (Boolean)


145
146
147
# File 'lib/rubocop/directive_comment.rb', line 145

def all_cops?
  cops == 'all'
end

#cop_namesObject

Returns array of specified in this directive cop names



150
151
152
# File 'lib/rubocop/directive_comment.rb', line 150

def cop_names
  @cop_names ||= all_cops? ? all_cop_names : parsed_cop_names
end

#department_namesObject

Returns array of specified in this directive department names when all department disabled



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

def department_names
  raw_cop_names.select { |cop| department?(cop) }
end

#directive_countObject



175
176
177
# File 'lib/rubocop/directive_comment.rb', line 175

def directive_count
  raw_cop_names.count
end

#disabled?Boolean

Checks if this directive disables cops

Returns:

  • (Boolean)


110
111
112
# File 'lib/rubocop/directive_comment.rb', line 110

def disabled?
  %w[disable todo].include?(mode)
end

#disabled_all?Boolean

Checks if this directive disables all cops

Returns:

  • (Boolean)


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

def disabled_all?
  disabled? && all_cops?
end

#enabled?Boolean

Checks if this directive enables cops

Returns:

  • (Boolean)


115
116
117
# File 'lib/rubocop/directive_comment.rb', line 115

def enabled?
  mode == 'enable'
end

#enabled_all?Boolean

Checks if this directive enables all cops

Returns:

  • (Boolean)


135
136
137
# File 'lib/rubocop/directive_comment.rb', line 135

def enabled_all?
  !disabled? && all_cops?
end

#in_directive_department?(cop) ⇒ Boolean

Checks if directive departments include cop

Returns:

  • (Boolean)


166
167
168
# File 'lib/rubocop/directive_comment.rb', line 166

def in_directive_department?(cop)
  department_names.any? { |department| cop.start_with?(department) }
end

#line_numberObject

Returns line number for directive



180
181
182
# File 'lib/rubocop/directive_comment.rb', line 180

def line_number
  comment.source_range.line
end

#malformed?Boolean

Checks if the comment is malformed as a ‘# rubocop:` directive

Returns:

  • (Boolean)


65
66
67
68
69
70
71
# File 'lib/rubocop/directive_comment.rb', line 65

def malformed?
  return true if !start_with_marker? || @match_data.nil?
  return true if missing_cop_name?

  tail = @match_data.post_match.lstrip
  !(tail.empty? || tail.start_with?(TRAILING_COMMENT_MARKER))
end

#match?(cop_names) ⇒ Boolean

Checks if this directive contains all the given cop names

Returns:

  • (Boolean)


86
87
88
# File 'lib/rubocop/directive_comment.rb', line 86

def match?(cop_names)
  parsed_cop_names.uniq.sort == cop_names.uniq.sort
end

#match_capturesObject

Returns match captures to directive comment pattern



99
100
101
102
103
104
105
106
107
# File 'lib/rubocop/directive_comment.rb', line 99

def match_captures
  @match_captures ||= @match_data && begin
    captures = @match_data.captures
    mode = captures[0]
    # COPS_PATTERN is at captures[1], PUSH_POP_ARGS_PATTERN is at captures[4]
    cops = captures[1] || captures[4]
    [mode, cops]
  end
end

#missing_cop_name?Boolean

Checks if the directive comment is missing a cop name

Returns:

  • (Boolean)


74
75
76
77
78
# File 'lib/rubocop/directive_comment.rb', line 74

def missing_cop_name?
  return false if push? || pop?

  MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP.match?(comment.text)
end

#overridden_by_department?(cop) ⇒ Boolean

Checks if cop department has already used in directive comment

Returns:

  • (Boolean)


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

def overridden_by_department?(cop)
  in_directive_department?(cop) && raw_cop_names.include?(cop)
end

#pop?Boolean

Checks if this directive is a pop

Returns:

  • (Boolean)


125
126
127
# File 'lib/rubocop/directive_comment.rb', line 125

def pop?
  mode == 'pop'
end

#push?Boolean

Checks if this directive is a push

Returns:

  • (Boolean)


120
121
122
# File 'lib/rubocop/directive_comment.rb', line 120

def push?
  mode == 'push'
end

#push_argsObject

Returns the push arguments as a hash of cop names with their operations



130
131
132
# File 'lib/rubocop/directive_comment.rb', line 130

def push_args
  @push_args ||= parse_push_args
end

#rangeObject



90
91
92
93
94
95
96
# File 'lib/rubocop/directive_comment.rb', line 90

def range
  match = comment.text.match(DIRECTIVE_COMMENT_REGEXP)
  begin_pos = comment.source_range.begin_pos
  Parser::Source::Range.new(
    comment.source_range.source_buffer, begin_pos + match.begin(0), begin_pos + match.end(0)
  )
end

#raw_cop_namesObject

Returns an array of cops for this directive comment, without resolving departments



155
156
157
# File 'lib/rubocop/directive_comment.rb', line 155

def raw_cop_names
  @raw_cop_names ||= (cops || '').split(/,\s*/)
end

#single_line?Boolean

Checks if this directive relates to single line

Returns:

  • (Boolean)


81
82
83
# File 'lib/rubocop/directive_comment.rb', line 81

def single_line?
  !comment.text.start_with?(DIRECTIVE_COMMENT_REGEXP)
end

#start_with_marker?Boolean

Checks if the comment starts with ‘# rubocop:` marker

Returns:

  • (Boolean)


60
61
62
# File 'lib/rubocop/directive_comment.rb', line 60

def start_with_marker?
  comment.text.start_with?(DIRECTIVE_MARKER_REGEXP)
end