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].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 41Regexp.new( "#{DIRECTIVE_HEADER_PATTERN}(?:\\s+#{COPS_PATTERN}|\\s+#{PUSH_POP_ARGS_PATTERN})?" .gsub(' ', '\s*') )
-
DIRECTIVE_HEADER_PATTERN =
# File 'lib/rubocop/directive_comment.rb', line 39"#{DIRECTIVE_MARKER_PATTERN}((?:#{MODES_PATTERN}))\\b" -
DIRECTIVE_MARKER_PATTERN =
# File 'lib/rubocop/directive_comment.rb', line 35'# rubocop : ' -
DIRECTIVE_MARKER_REGEXP =
# File 'lib/rubocop/directive_comment.rb', line 37Regexp.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 48Regexp.new( "\\A#{DIRECTIVE_HEADER_PATTERN}\\s*\\z".gsub(' ', '\s*') )
-
MODES_PATTERN =
# File 'lib/rubocop/directive_comment.rb', line 33
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})*)" -
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 46'--'
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.
-
#enabled? ⇒ Boolean
readonly
Checks if this directive enables cops.
-
#enabled_all? ⇒ Boolean
readonly
Checks if this directive enables all cops.
-
#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
-
#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
Returns the push arguments as a hash of cop names with their operations.
- #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. - #all_cop_names private
- #cop_names_for_department(department) private
- #department?(name) ⇒ Boolean private
- #exclude_lint_department_cops(cops) private
- #parse_push_args private
- #parsed_cop_names private
Constructor Details
.new(comment, cop_registry = Cop::Registry.global) ⇒ DirectiveComment
# File 'lib/rubocop/directive_comment.rb', line 58
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 52
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 182
def all_cops? cops == 'all' end
#comment (readonly)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 56
attr_reader :comment, :cop_registry, :mode, :cops
#cop_registry (readonly)
[ GitHub ]#cops (readonly)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 56
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 147
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 142
def disabled? %w[disable todo].include?(mode) || disable_next? end
#disabled_all? ⇒ Boolean (readonly)
Checks if this directive disables all cops
#enabled? ⇒ Boolean (readonly)
Checks if this directive enables cops
# File 'lib/rubocop/directive_comment.rb', line 152
def enabled? mode == 'enable' end
#enabled_all? ⇒ Boolean (readonly)
Checks if this directive enables all cops
#malformed? ⇒ Boolean (readonly)
Checks if the comment is malformed as a # rubocop: directive
# File 'lib/rubocop/directive_comment.rb', line 72
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
#missing_cop_name? ⇒ Boolean (readonly)
Checks if the directive comment is missing a cop name
# File 'lib/rubocop/directive_comment.rb', line 81
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 56
attr_reader :comment, :cop_registry, :mode, :cops
#pop? ⇒ Boolean (readonly)
Checks if this directive is a pop
# File 'lib/rubocop/directive_comment.rb', line 162
def pop? mode == 'pop' end
#push? ⇒ Boolean (readonly)
Checks if this directive is a push
# File 'lib/rubocop/directive_comment.rb', line 157
def push? mode == 'push' end
#single_line? ⇒ Boolean (readonly)
Checks if this directive relates to single line
# File 'lib/rubocop/directive_comment.rb', line 100
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 67
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 234
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 187
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 238
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 230
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 198
def department_names raw_cop_names.select { |cop| department?(cop) } end
#directive_count
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 212
def directive_count raw_cop_names.count end
#exclude_lint_department_cops(cops) (private)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 243
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 203
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 217
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 105
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 208
def overridden_by_department?(cop) in_directive_department?(cop) && raw_cop_names.include?(cop) end
#parse_push_args (private)
[ GitHub ]#parsed_cop_names (private)
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 223
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
Returns the push arguments as a hash of cop names with their operations
# File 'lib/rubocop/directive_comment.rb', line 167
def push_args @push_args ||= parse_push_args end
#range
[ GitHub ]# File 'lib/rubocop/directive_comment.rb', line 109
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 120
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 192
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 89
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