Class: RuboCop::DirectiveComment
| Relationships & Source Files | |
| Inherits: | Object |
| 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
-
AVAILABLE_MODES =
# File 'lib/rubocop/directive_comment.rb', line 29%w[disable enable todo push pop disable-next todo-next enable-next next].freeze
-
COPS_PATTERN =
# File 'lib/rubocop/directive_comment.rb', line 25"(all|#{COP_NAMES_PATTERN})" -
COP_NAMES_PATTERN =
# File 'lib/rubocop/directive_comment.rb', line 23"(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}" -
COP_NAMES_PATTERN_NC =
# File 'lib/rubocop/directive_comment.rb', line 21"(?:#{COP_NAME_PATTERN_NC} , )*#{COP_NAME_PATTERN_NC}" -
COP_NAME_PATTERN =
# File 'lib/rubocop/directive_comment.rb', line 17'([A-Za-z]\w+/)*(?:[A-Za-z]\w+)' -
COP_NAME_PATTERN_NC =
# File 'lib/rubocop/directive_comment.rb', line 19'(?:[A-Za-z]\w+/)*[A-Za-z]\w+' -
DIRECTIVE_COMMENT_REGEXP =
# File 'lib/rubocop/directive_comment.rb', line 42Regexp.new( "#{DIRECTIVE_HEADER_PATTERN}(?:\\s+#{COPS_PATTERN}|\\s+#{PUSH_POP_ARGS_PATTERN})?" .gsub(' ', '\s*') )
-
DIRECTIVE_HEADER_PATTERN =
# File 'lib/rubocop/directive_comment.rb', line 40"#{DIRECTIVE_MARKER_PATTERN}((?:#{MODES_PATTERN}))\\b" -
DIRECTIVE_MARKER_PATTERN =
# File 'lib/rubocop/directive_comment.rb', line 36'# rubocop : ' -
DIRECTIVE_MARKER_REGEXP =
# File 'lib/rubocop/directive_comment.rb', line 38Regexp.new(DIRECTIVE_MARKER_PATTERN.gsub(' ', '\s*'))
-
LINT_DEPARTMENT =
# File 'lib/rubocop/directive_comment.rb', line 9'Lint' -
LINT_REDUNDANT_DIRECTIVE_COP =
# File 'lib/rubocop/directive_comment.rb', line 11"#{LINT_DEPARTMENT}/RedundantCopDisableDirective" -
LINT_SYNTAX_COP =
# File 'lib/rubocop/directive_comment.rb', line 13"#{LINT_DEPARTMENT}/Syntax" -
MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP =
# File 'lib/rubocop/directive_comment.rb', line 51Regexp.new( "\\A#{DIRECTIVE_HEADER_PATTERN}\\s*\\z".gsub(' ', '\s*') )
-
MODES_PATTERN =
# File 'lib/rubocop/directive_comment.rb', line 34
Longest first, so a
-nextmode is not matched as its prefix (-is a word boundary).AVAILABLE_MODES.sort_by { |mode| -mode.length }.join('|').freeze
-
PUSH_POP_ARGS_PATTERN =
# File 'lib/rubocop/directive_comment.rb', line 27"([+\\-]#{COP_NAME_PATTERN_NC}(?:\\s+[+\\-]#{COP_NAME_PATTERN_NC})*)" -
SIGNED_OPERATIONS =
# File 'lib/rubocop/directive_comment.rb', line 47%w[+ -].freeze
-
STYLE_DISABLE_COPS_DIRECTIVE_COP =
# File 'lib/rubocop/directive_comment.rb', line 15'Style/DisableCopsWithinSourceCodeDirective' -
TRAILING_COMMENT_MARKER =
# File 'lib/rubocop/directive_comment.rb', line 49'--'
Class Method Summary
Instance Attribute Summary
-
#all_cops? ⇒ Boolean
readonly
Checks if all cops specified in this directive.
- #comment readonly
- #cop_registry readonly
- #cops readonly
-
#disable_next? ⇒ Boolean
readonly
Checks if this directive disables cops for the next statement only.
-
#disabled? ⇒ Boolean
readonly
Checks if this directive disables cops.
-
#disabled_all? ⇒ Boolean
readonly
Checks if this directive disables all cops.
-
#enable_next? ⇒ Boolean
readonly
Checks if this directive enables cops for the next statement only.
-
#enabled? ⇒ Boolean
readonly
Checks if this directive enables cops.
-
#enabled_all? ⇒ Boolean
readonly
Checks if this directive enables all cops.
-
#invalid_signed_args? ⇒ Boolean
readonly
pushandnextarguments must be+/-prefixed cop names, andpoptakes no arguments at all. -
#malformed? ⇒ Boolean
readonly
Checks if the comment is malformed as a
# rubocop:directive. -
#missing_cop_name? ⇒ Boolean
readonly
Checks if the directive comment is missing a cop name.
- #mode readonly
-
#next? ⇒ Boolean
readonly
Checks if this directive toggles cops for the next statement only.
-
#pop? ⇒ Boolean
readonly
Checks if this directive is a pop.
-
#push? ⇒ Boolean
readonly
Checks if this directive is a push.
-
#single_line? ⇒ Boolean
readonly
Checks if this directive relates to single line.
-
#start_with_marker? ⇒ Boolean
readonly
Checks if the comment starts with
# rubocop:marker.
Instance Method Summary
-
#cop_names
Returns array of specified in this directive cop names.
-
#department_names
Returns array of specified in this directive department names when all department disabled.
- #directive_count
-
#in_directive_department?(cop) ⇒ Boolean
Checks if directive departments include cop.
-
#line_number
Returns line number for directive.
-
#match?(cop_names) ⇒ Boolean
Checks if this directive contains all the given cop names.
-
#match_captures
Returns match captures to directive comment pattern.
-
#overridden_by_department?(cop) ⇒ Boolean
Checks if cop department has already used in directive comment.
-
#push_args
Alias for #signed_args.
- #range
-
#range_with_reason
#range stops at the cop list, so a
--reason sits outside it. -
#raw_cop_names
Returns an array of cops for this directive comment, without resolving departments.
-
#reason
The text of the directive’s optional
--trailing comment, ornilwhen there is none. -
#signed_args
(also: #push_args)
Returns the
+/-arguments of apushornextdirective as a hash of operations to cop names. - #all_cop_names private
- #cop_names_for_department(department) private
- #department?(name) ⇒ Boolean private
- #exclude_lint_department_cops(cops) private
- #parse_signed_args private
- #parsed_cop_names private
Constructor Details
.new(comment, cop_registry = Cop::Registry.global) ⇒ DirectiveComment
# File 'lib/rubocop/directive_comment.rb', line 61
def initialize(comment, cop_registry = Cop::Registry.global) @comment = comment @cop_registry = cop_registry match_data = comment.text.match(DIRECTIVE_COMMENT_REGEXP) @match_data = match_data&.pre_match&.match?(/\A#\s*\z/) ? nil : match_data @mode, @cops = match_captures end
Class Method Details
.before_comment(line)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 55
def self.before_comment(line) line.split(DIRECTIVE_COMMENT_REGEXP).first end
Instance Attribute Details
#all_cops? ⇒ Boolean (readonly)
Checks if all cops specified in this directive
# File 'lib/rubocop/directive_comment.rb', line 207
def all_cops? cops == 'all' end
#comment (readonly)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 59
attr_reader :comment, :cop_registry, :mode, :cops
#cop_registry (readonly)
[ GitHub ]#cops (readonly)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 59
attr_reader :comment, :cop_registry, :mode, :cops
#disable_next? ⇒ Boolean (readonly)
Checks if this directive disables cops for the next statement only
# File 'lib/rubocop/directive_comment.rb', line 160
def disable_next? %w[disable-next todo-next].include?(mode) end
#disabled? ⇒ Boolean (readonly)
Checks if this directive disables cops
# File 'lib/rubocop/directive_comment.rb', line 155
def disabled? %w[disable todo].include?(mode) || disable_next? end
#disabled_all? ⇒ Boolean (readonly)
Checks if this directive disables all cops
#enable_next? ⇒ Boolean (readonly)
Checks if this directive enables cops for the next statement only
# File 'lib/rubocop/directive_comment.rb', line 170
def enable_next? mode == 'enable-next' end
#enabled? ⇒ Boolean (readonly)
Checks if this directive enables cops
# File 'lib/rubocop/directive_comment.rb', line 165
def enabled? mode == 'enable' || enable_next? end
#enabled_all? ⇒ Boolean (readonly)
Checks if this directive enables all cops
#invalid_signed_args? ⇒ Boolean (readonly)
push and next arguments must be +/- prefixed cop names, and
pop takes no arguments at all.
#malformed? ⇒ Boolean (readonly)
Checks if the comment is malformed as a # rubocop: directive
# File 'lib/rubocop/directive_comment.rb', line 75
def malformed? return true if !start_with_marker? || @match_data.nil? return true if missing_cop_name? || invalid_signed_args? tail = @match_data.post_match.lstrip !(tail.empty? || tail.start_with?(TRAILING_COMMENT_MARKER)) end
#missing_cop_name? ⇒ Boolean (readonly)
Checks if the directive comment is missing a cop name
# File 'lib/rubocop/directive_comment.rb', line 84
def missing_cop_name? return false if push? || pop? MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP.match?(comment.text) end
#mode (readonly)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 59
attr_reader :comment, :cop_registry, :mode, :cops
#next? ⇒ Boolean (readonly)
Checks if this directive toggles cops for the next statement only
# File 'lib/rubocop/directive_comment.rb', line 185
def next? mode == 'next' end
#pop? ⇒ Boolean (readonly)
Checks if this directive is a pop
# File 'lib/rubocop/directive_comment.rb', line 180
def pop? mode == 'pop' end
#push? ⇒ Boolean (readonly)
Checks if this directive is a push
# File 'lib/rubocop/directive_comment.rb', line 175
def push? mode == 'push' end
#single_line? ⇒ Boolean (readonly)
Checks if this directive relates to single line
# File 'lib/rubocop/directive_comment.rb', line 113
def single_line? !comment.text.start_with?(DIRECTIVE_COMMENT_REGEXP) end
#start_with_marker? ⇒ Boolean (readonly)
Checks if the comment starts with # rubocop: marker
# File 'lib/rubocop/directive_comment.rb', line 70
def start_with_marker? comment.text.start_with?(DIRECTIVE_MARKER_REGEXP) end
Instance Method Details
#all_cop_names (private)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 261
def all_cop_names exclude_lint_department_cops(cop_registry.names) end
#cop_names
Returns array of specified in this directive cop names
# File 'lib/rubocop/directive_comment.rb', line 212
def cop_names @cop_names ||= all_cops? ? all_cop_names : parsed_cop_names end
#cop_names_for_department(department) (private)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 265
def cop_names_for_department(department) names = cop_registry.names_for_department(department) department == LINT_DEPARTMENT ? exclude_lint_department_cops(names) : names end
#department?(name) ⇒ Boolean (private)
# File 'lib/rubocop/directive_comment.rb', line 257
def department?(name) cop_registry.department?(name) end
#department_names
Returns array of specified in this directive department names when all department disabled
# File 'lib/rubocop/directive_comment.rb', line 223
def department_names raw_cop_names.select { |cop| department?(cop) } end
#directive_count
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 237
def directive_count return signed_args.values.sum(&:count) if push? || next? raw_cop_names.count end
#exclude_lint_department_cops(cops) (private)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 270
def exclude_lint_department_cops(cops) cops - [LINT_REDUNDANT_DIRECTIVE_COP, LINT_SYNTAX_COP] end
#in_directive_department?(cop) ⇒ Boolean
Checks if directive departments include cop
# File 'lib/rubocop/directive_comment.rb', line 228
def in_directive_department?(cop) department_names.any? { |department| cop.start_with?(department) } end
#line_number
Returns line number for directive
# File 'lib/rubocop/directive_comment.rb', line 244
def line_number comment.source_range.line end
#match?(cop_names) ⇒ Boolean
Checks if this directive contains all the given cop names
# File 'lib/rubocop/directive_comment.rb', line 118
def match?(cop_names) parsed_cop_names.uniq.sort == cop_names.uniq.sort end
#match_captures
Returns match captures to directive comment pattern
#overridden_by_department?(cop) ⇒ Boolean
Checks if cop department has already used in directive comment
# File 'lib/rubocop/directive_comment.rb', line 233
def overridden_by_department?(cop) in_directive_department?(cop) && raw_cop_names.include?(cop) end
#parse_signed_args (private)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 274
def parse_signed_args return {} unless (push? || next?) && cops args = {} cops.split.each do |cop_spec| op = cop_spec[0] cop_name = cop_spec[1..] next unless SIGNED_OPERATIONS.include?(op) args[op] ||= [] args[op] << cop_name end args end
#parsed_cop_names (private)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 250
def parsed_cop_names cops = raw_cop_names.map do |name| department?(name) ? cop_names_for_department(name) : name end.flatten cops - [LINT_SYNTAX_COP] end
#push_args
Alias for #signed_args.
# File 'lib/rubocop/directive_comment.rb', line 194
alias push_args signed_args
#range
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 122
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
#range_with_reason
#range stops at the cop list, so a -- reason sits outside it. The reason documents the
directive and means nothing once the directive is gone, so removal has to cover both. Any
other trailing text is an ordinary comment and is left alone.
# File 'lib/rubocop/directive_comment.rb', line 133
def range_with_reason directive_range = range trailing = Parser::Source::Range.new( comment.source_range.source_buffer, directive_range.end_pos, comment.source_range.end_pos ) return directive_range unless trailing.source.lstrip.start_with?(TRAILING_COMMENT_MARKER) directive_range.with(end_pos: comment.source_range.end_pos) end
#raw_cop_names
Returns an array of cops for this directive comment, without resolving departments
# File 'lib/rubocop/directive_comment.rb', line 217
def raw_cop_names @raw_cop_names ||= (cops || '').split(/,\s*/) end
#reason
The text of the directive’s optional -- trailing comment, or nil
when there is none.
# File 'lib/rubocop/directive_comment.rb', line 102
def reason return unless @match_data tail = @match_data.post_match.lstrip return unless tail.start_with?(TRAILING_COMMENT_MARKER) reason = tail.delete_prefix(TRAILING_COMMENT_MARKER).strip reason unless reason.empty? end
#signed_args Also known as: #push_args
Returns the +/- arguments of a push or next directive as a hash
of operations to cop names
# File 'lib/rubocop/directive_comment.rb', line 191
def signed_args @signed_args ||= parse_signed_args end