Class: RuboCop::DirectiveComment
- Inherits:
-
Object
- Object
- RuboCop::DirectiveComment
- 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"- STYLE_DISABLE_COPS_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.
'Style/DisableCopsWithinSourceCodeDirective'- 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 disable-next todo-next enable-next next].freeze
- MODES_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.
Longest first, so a
-nextmode is not matched as its prefix (-is a word boundary). AVAILABLE_MODES.sort_by { |mode| -mode.length }.join('|').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}((?:#{MODES_PATTERN}))\\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*') )
- SIGNED_OPERATIONS =
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[+ -].freeze
- 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
-
#comment ⇒ Object
readonly
Returns the value of attribute comment.
-
#cop_registry ⇒ Object
readonly
Returns the value of attribute cop_registry.
-
#cops ⇒ Object
readonly
Returns the value of attribute cops.
-
#mode ⇒ Object
readonly
Returns the value of attribute mode.
Class Method Summary collapse
Instance Method Summary collapse
-
#all_cops? ⇒ Boolean
Checks if all cops specified in this directive.
-
#cop_names ⇒ Object
Returns array of specified in this directive cop names.
-
#department_names ⇒ Object
Returns array of specified in this directive department names when all department disabled.
- #directive_count ⇒ Object
-
#disable_next? ⇒ Boolean
Checks if this directive disables cops for the next statement only.
-
#disabled? ⇒ Boolean
Checks if this directive disables cops.
-
#disabled_all? ⇒ Boolean
Checks if this directive disables all cops.
-
#enable_next? ⇒ Boolean
Checks if this directive enables cops for the next statement only.
-
#enabled? ⇒ Boolean
Checks if this directive enables cops.
-
#enabled_all? ⇒ Boolean
Checks if this directive enables all cops.
-
#in_directive_department?(cop) ⇒ Boolean
Checks if directive departments include cop.
-
#initialize(comment, cop_registry = Cop::Registry.global) ⇒ DirectiveComment
constructor
A new instance of DirectiveComment.
-
#invalid_signed_args? ⇒ Boolean
pushandnextarguments must be+/-prefixed cop names, andpoptakes no arguments at all. -
#line_number ⇒ Object
Returns line number for directive.
-
#malformed? ⇒ Boolean
Checks if the comment is malformed as a
# rubocop:directive. -
#match?(cop_names) ⇒ Boolean
Checks if this directive contains all the given cop names.
-
#match_captures ⇒ Object
Returns match captures to directive comment pattern.
-
#missing_cop_name? ⇒ Boolean
Checks if the directive comment is missing a cop name.
-
#next? ⇒ Boolean
Checks if this directive toggles cops for the next statement only.
-
#overridden_by_department?(cop) ⇒ Boolean
Checks if cop department has already used in directive comment.
-
#pop? ⇒ Boolean
Checks if this directive is a pop.
-
#push? ⇒ Boolean
Checks if this directive is a push.
- #range ⇒ Object
-
#range_with_reason ⇒ Object
#rangestops at the cop list, so a--reason sits outside it. -
#raw_cop_names ⇒ Object
Returns an array of cops for this directive comment, without resolving departments.
-
#reason ⇒ Object
The text of the directive's optional
--trailing comment, ornilwhen there is none. -
#signed_args ⇒ Object
(also: #push_args)
Returns the
+/-arguments of apushornextdirective as a hash of operations to cop names. -
#single_line? ⇒ Boolean
Checks if this directive relates to single line.
-
#start_with_marker? ⇒ Boolean
Checks if the comment starts with
# rubocop:marker.
Constructor Details
#initialize(comment, cop_registry = Cop::Registry.global) ⇒ DirectiveComment
Returns a new instance of DirectiveComment.
61 62 63 64 65 66 67 |
# 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 |
Instance Attribute Details
#comment ⇒ Object (readonly)
Returns the value of attribute comment.
59 60 61 |
# File 'lib/rubocop/directive_comment.rb', line 59 def comment @comment end |
#cop_registry ⇒ Object (readonly)
Returns the value of attribute cop_registry.
59 60 61 |
# File 'lib/rubocop/directive_comment.rb', line 59 def cop_registry @cop_registry end |
#cops ⇒ Object (readonly)
Returns the value of attribute cops.
59 60 61 |
# File 'lib/rubocop/directive_comment.rb', line 59 def cops @cops end |
#mode ⇒ Object (readonly)
Returns the value of attribute mode.
59 60 61 |
# File 'lib/rubocop/directive_comment.rb', line 59 def mode @mode end |
Class Method Details
.before_comment(line) ⇒ Object
55 56 57 |
# File 'lib/rubocop/directive_comment.rb', line 55 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
207 208 209 |
# File 'lib/rubocop/directive_comment.rb', line 207 def all_cops? cops == 'all' end |
#cop_names ⇒ Object
Returns array of specified in this directive cop names
212 213 214 |
# File 'lib/rubocop/directive_comment.rb', line 212 def cop_names @cop_names ||= all_cops? ? all_cop_names : parsed_cop_names end |
#department_names ⇒ Object
Returns array of specified in this directive department names when all department disabled
223 224 225 |
# File 'lib/rubocop/directive_comment.rb', line 223 def department_names raw_cop_names.select { |cop| department?(cop) } end |
#directive_count ⇒ Object
237 238 239 240 241 |
# 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 |
#disable_next? ⇒ Boolean
Checks if this directive disables cops for the next statement only
160 161 162 |
# File 'lib/rubocop/directive_comment.rb', line 160 def disable_next? %w[disable-next todo-next].include?(mode) end |
#disabled? ⇒ Boolean
Checks if this directive disables cops
155 156 157 |
# File 'lib/rubocop/directive_comment.rb', line 155 def disabled? %w[disable todo].include?(mode) || disable_next? end |
#disabled_all? ⇒ Boolean
Checks if this directive disables all cops
202 203 204 |
# File 'lib/rubocop/directive_comment.rb', line 202 def disabled_all? disabled? && all_cops? end |
#enable_next? ⇒ Boolean
Checks if this directive enables cops for the next statement only
170 171 172 |
# File 'lib/rubocop/directive_comment.rb', line 170 def enable_next? mode == 'enable-next' end |
#enabled? ⇒ Boolean
Checks if this directive enables cops
165 166 167 |
# File 'lib/rubocop/directive_comment.rb', line 165 def enabled? mode == 'enable' || enable_next? end |
#enabled_all? ⇒ Boolean
Checks if this directive enables all cops
197 198 199 |
# File 'lib/rubocop/directive_comment.rb', line 197 def enabled_all? !disabled? && all_cops? end |
#in_directive_department?(cop) ⇒ Boolean
Checks if directive departments include cop
228 229 230 |
# File 'lib/rubocop/directive_comment.rb', line 228 def in_directive_department?(cop) department_names.any? { |department| cop.start_with?(department) } end |
#invalid_signed_args? ⇒ Boolean
push and next arguments must be +/- prefixed cop names, and
pop takes no arguments at all.
92 93 94 95 96 97 98 |
# File 'lib/rubocop/directive_comment.rb', line 92 def invalid_signed_args? return cops ? !cops.empty? : false if pop? return false unless push? || next? return false unless cops cops.split.any? { |cop_spec| !cop_spec.start_with?('+', '-') } end |
#line_number ⇒ Object
Returns line number for directive
244 245 246 |
# File 'lib/rubocop/directive_comment.rb', line 244 def line_number comment.source_range.line end |
#malformed? ⇒ Boolean
Checks if the comment is malformed as a # rubocop: directive
75 76 77 78 79 80 81 |
# 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 |
#match?(cop_names) ⇒ Boolean
Checks if this directive contains all the given cop names
118 119 120 |
# File 'lib/rubocop/directive_comment.rb', line 118 def match?(cop_names) parsed_cop_names.uniq.sort == cop_names.uniq.sort end |
#match_captures ⇒ Object
Returns match captures to directive comment pattern
144 145 146 147 148 149 150 151 152 |
# File 'lib/rubocop/directive_comment.rb', line 144 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
84 85 86 87 88 |
# 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 |
#next? ⇒ Boolean
Checks if this directive toggles cops for the next statement only
185 186 187 |
# File 'lib/rubocop/directive_comment.rb', line 185 def next? mode == 'next' end |
#overridden_by_department?(cop) ⇒ Boolean
Checks if cop department has already used in directive comment
233 234 235 |
# File 'lib/rubocop/directive_comment.rb', line 233 def overridden_by_department?(cop) in_directive_department?(cop) && raw_cop_names.include?(cop) end |
#pop? ⇒ Boolean
Checks if this directive is a pop
180 181 182 |
# File 'lib/rubocop/directive_comment.rb', line 180 def pop? mode == 'pop' end |
#push? ⇒ Boolean
Checks if this directive is a push
175 176 177 |
# File 'lib/rubocop/directive_comment.rb', line 175 def push? mode == 'push' end |
#range ⇒ Object
122 123 124 125 126 127 128 |
# 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 ⇒ Object
#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.
133 134 135 136 137 138 139 140 141 |
# 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 ⇒ Object
Returns an array of cops for this directive comment, without resolving departments
217 218 219 |
# File 'lib/rubocop/directive_comment.rb', line 217 def raw_cop_names @raw_cop_names ||= (cops || '').split(/,\s*/) end |
#reason ⇒ Object
The text of the directive's optional -- trailing comment, or nil
when there is none.
102 103 104 105 106 107 108 109 110 |
# 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 ⇒ Object Also known as: push_args
Returns the +/- arguments of a push or next directive as a hash
of operations to cop names
191 192 193 |
# File 'lib/rubocop/directive_comment.rb', line 191 def signed_args @signed_args ||= parse_signed_args end |
#single_line? ⇒ Boolean
Checks if this directive relates to single line
113 114 115 |
# File 'lib/rubocop/directive_comment.rb', line 113 def single_line? !comment.text.start_with?(DIRECTIVE_COMMENT_REGEXP) end |
#start_with_marker? ⇒ Boolean
Checks if the comment starts with # rubocop: marker
70 71 72 |
# File 'lib/rubocop/directive_comment.rb', line 70 def start_with_marker? comment.text.start_with?(DIRECTIVE_MARKER_REGEXP) end |