diff --git a/lib/rubocop/comment_config.rb b/lib/rubocop/comment_config.rb index c0041e10e51..c1bd6db86df 100644 --- a/lib/rubocop/comment_config.rb +++ b/lib/rubocop/comment_config.rb @@ -4,9 +4,6 @@ module RuboCop # This class parses the special `rubocop:disable` comments in a source # and provides a way to check if each cop is enabled at arbitrary line. class CommentConfig - # @api private - REDUNDANT_DISABLE = 'Lint/RedundantCopDisableDirective' - CopAnalysis = Struct.new(:line_ranges, :start_line_number) attr_reader :processed_source @@ -130,35 +127,18 @@ def directive_on_comment_line?(comment) def each_directive processed_source.comments.each do |comment| - directive = directive_parts(comment) - next unless directive + directive = DirectiveComment.new(comment) + next unless directive.cop_names - yield comment, *directive + # TODO: pass only directive + yield directive.comment, directive.cop_names, directive.disabled? end end - def directive_parts(comment) - match_captures = DirectiveComment.new(comment).match_captures - return unless match_captures - - switch, cops_string = match_captures - - cop_names = - cops_string == 'all' ? all_cop_names : cops_string.split(/,\s*/) - - disabled = %w[disable todo].include?(switch) - - [cop_names, disabled] - end - def qualified_cop_name(cop_name) Cop::Registry.qualified_cop_name(cop_name.strip, processed_source.file_path) end - def all_cop_names - @all_cop_names ||= Cop::Registry.global.names - [REDUNDANT_DISABLE] - end - def non_comment_token_line_numbers @non_comment_token_line_numbers ||= begin non_comment_tokens = processed_source.tokens.reject(&:comment?) diff --git a/lib/rubocop/directive_comment.rb b/lib/rubocop/directive_comment.rb index a7554ed7ee9..486b485aedc 100644 --- a/lib/rubocop/directive_comment.rb +++ b/lib/rubocop/directive_comment.rb @@ -5,6 +5,8 @@ module RuboCop # special `rubocop:disable` and `rubocop:enable` comment and exposes what # cops it contains. class DirectiveComment + # @api private + REDUNDANT_COP = 'Lint/RedundantCopDisableDirective' # @api private COP_NAME_PATTERN = '([A-Z]\w+/)*(?:[A-Z]\w+)' # @api private @@ -47,10 +49,29 @@ def match_captures @match_captures ||= comment.text.match(DIRECTIVE_COMMENT_REGEXP)&.captures end + # Checks if this directive disables cops + def disabled? + %w[disable todo].include?(mode) + end + + # Checks if all cops specified in this directive + def all_cops? + cops == 'all' + end + + # Returns array of specified in this directive cop names + def cop_names + @cop_names ||= all_cops? ? all_cop_names : parsed_cop_names + end + private def parsed_cop_names (cops || '').split(/,\s*/) end + + def all_cop_names + Cop::Registry.global.names - [REDUNDANT_COP] + end end end diff --git a/spec/rubocop/directive_comment_spec.rb b/spec/rubocop/directive_comment_spec.rb index 2b69277d574..7ca994be332 100644 --- a/spec/rubocop/directive_comment_spec.rb +++ b/spec/rubocop/directive_comment_spec.rb @@ -116,4 +116,59 @@ end end end + + describe '#disabled?' do + subject { directive_comment.disabled? } + + [ + ['when disable', '# rubocop:disable all', true], + ['when enable', '# rubocop:enable Foo/Bar', false], + ['when todo', '# rubocop:todo all', true] + ].each do |example| + context example[0] do + let(:text) { example[1] } + + it { is_expected.to eq example[2] } + end + end + end + + describe '#all_cops?' do + subject { directive_comment.all_cops? } + + [ + ['when mentioned all', '# rubocop:disable all', true], + ['when mentioned specific cops', '# rubocop:enable Foo/Bar', false] + ].each do |example| + context example[0] do + let(:text) { example[1] } + + it { is_expected.to eq example[2] } + end + end + end + + describe '#cop_names' do + subject(:cop_names) { directive_comment.cop_names } + + context 'when all cops mentioned' do + let(:comment_cop_names) { 'all' } + let(:global) { instance_double(RuboCop::Cop::Registry, names: names) } + let(:names) { %w[all_names Lint/RedundantCopDisableDirective] } + + before { allow(RuboCop::Cop::Registry).to receive(:global).and_return(global) } + + it 'returns all cop names except redundant' do + expect(cop_names).to eq(%w[all_names]) + end + end + + context 'when cop specified' do + let(:comment_cop_names) { 'Foo/Bar' } + + it 'returns parsed cop names' do + expect(cop_names).to eq(%w[Foo/Bar]) + end + end + end end