Class: RuboCop::Cop::Cop

Inherits:
Object
  • Object
show all
Extended by:
AST::Sexp
Includes:
IgnoredNode, Util
Defined in:
lib/rubocop/cop/cop.rb

Overview

A scaffold for concrete cops.

The Cop class is meant to be extended.

Cops track offenses and can autocorrect them of the fly.

A commissioner object is responsible for traversing the AST and invoking the specific callbacks on each cop. If a cop needs to do its own processing of the AST or depends on something else, it should define the #investigate method and do the processing there.

Examples:


class CustomCop < Cop
  def investigate(processed_source)
    # Do custom processing
  end
end

Direct Known Subclasses

Lint::AmbiguousOperator, Lint::AmbiguousRegexpLiteral, Lint::AssignmentInCondition, Lint::BlockAlignment, Lint::ConditionPosition, Lint::Debugger, Lint::DefEndAlignment, Lint::DeprecatedClassMethods, Lint::ElseLayout, Lint::EmptyEnsure, Lint::EmptyInterpolation, Lint::EndAlignment, Lint::EndInMethod, Lint::EnsureReturn, Lint::Eval, Lint::HandleExceptions, Lint::InvalidCharacterLiteral, Lint::LiteralInCondition, Lint::LiteralInInterpolation, Lint::Loop, Lint::ParenthesesAsGroupedExpression, Lint::RequireParentheses, Lint::RescueException, Lint::ShadowingOuterLocalVariable, Lint::SpaceBeforeFirstArg, Lint::StringConversionInInterpolation, Lint::UnderscorePrefixedVariableName, Lint::UnreachableCode, Lint::UnusedBlockArgument, Lint::UnusedMethodArgument, Lint::UselessAccessModifier, Lint::UselessAssignment, Lint::UselessComparison, Lint::UselessElseWithoutRescue, Lint::UselessSetterCall, Lint::Void, Metrics::AbcSize, Metrics::BlockNesting, Metrics::ClassLength, Metrics::CyclomaticComplexity, Metrics::LineLength, Metrics::MethodLength, Metrics::ParameterLists, Metrics::PerceivedComplexity, Rails::ActionFilter, Rails::DefaultScope, Rails::Delegate, Rails::HasAndBelongsToMany, Rails::Output, Rails::ReadWriteAttribute, Rails::ScopeArgs, Rails::Validation, Style::AccessModifierIndentation, Style::AccessorMethodName, Style::Alias, Style::AlignArray, Style::AlignHash, Style::AlignParameters, Style::AndOr, Style::ArrayJoin, Style::AsciiComments, Style::AsciiIdentifiers, Style::Attr, Style::BarePercentLiterals, Style::BeginBlock, Style::BlockComments, Style::BlockEndNewline, Style::Blocks, Style::BracesAroundHashParameters, Style::CaseEquality, Style::CaseIndentation, Style::CharacterLiteral, Style::ClassAndModuleCamelCase, Style::ClassAndModuleChildren, Style::ClassCheck, Style::ClassMethods, Style::ClassVars, Style::CollectionMethods, Style::ColonMethodCall, Style::CommentAnnotation, Style::CommentIndentation, Style::ConstantName, Style::DefWithParentheses, Style::DeprecatedHashMethods, Style::Documentation, Style::DotPosition, Style::DoubleNegation, Style::EachWithObject, Style::ElseAlignment, Style::EmptyLineBetweenDefs, Style::EmptyLines, Style::EmptyLinesAroundAccessModifier, Style::EmptyLinesAroundClassBody, Style::EmptyLinesAroundMethodBody, Style::EmptyLinesAroundModuleBody, Style::EmptyLiteral, Style::Encoding, Style::EndBlock, Style::EndOfLine, Style::EvenOdd, Style::FileName, Style::FlipFlop, Style::For, Style::FormatString, Style::GlobalVars, Style::GuardClause, Style::HashSyntax, Style::IfUnlessModifier, Style::IfWithSemicolon, Style::IndentArray, Style::IndentHash, Style::IndentationConsistency, Style::IndentationWidth, Style::InfiniteLoop, Style::InlineComment, Style::Lambda, Style::LambdaCall, Style::LeadingCommentSpace, Style::LineEndConcatenation, Style::MethodCallParentheses, Style::MethodCalledOnDoEndBlock, Style::MethodDefParentheses, Style::MethodName, Style::ModuleFunction, Style::MultilineBlockChain, Style::MultilineBlockLayout, Style::MultilineIfThen, Style::MultilineOperationIndentation, Style::MultilineTernaryOperator, Style::NegatedIf, Style::NegatedWhile, Style::NestedTernaryOperator, Style::Next, Style::NilComparison, Style::NonNilCheck, Style::Not, Style::NumericLiterals, Style::OneLineConditional, Style::OpMethod, Style::ParenthesesAroundCondition, Style::PercentLiteralDelimiters, Style::PercentQLiterals, Style::PerlBackrefs, Style::PredicateName, Style::Proc, Style::RaiseArgs, Style::RedundantBegin, Style::RedundantException, Style::RedundantReturn, Style::RedundantSelf, Style::RegexpLiteral, Style::RescueModifier, Style::SelfAssignment, Style::Semicolon, Style::SignalException, Style::SingleLineBlockParams, Style::SingleLineMethods, Style::SingleSpaceBeforeFirstArg, Style::SpaceAfterColon, Style::SpaceAfterComma, Style::SpaceAfterControlKeyword, Style::SpaceAfterMethodName, Style::SpaceAfterNot, Style::SpaceAfterSemicolon, Style::SpaceAroundEqualsInParameterDefault, Style::SpaceAroundOperators, Style::SpaceBeforeBlockBraces, Style::SpaceBeforeComma, Style::SpaceBeforeComment, Style::SpaceBeforeModifierKeyword, Style::SpaceBeforeSemicolon, Style::SpaceInsideBlockBraces, Style::SpaceInsideBrackets, Style::SpaceInsideHashLiteralBraces, Style::SpaceInsideParens, Style::SpaceInsideRangeLiteral, Style::SpecialGlobalVars, Style::StringLiterals, Style::StringLiteralsInInterpolation, Style::SymbolArray, Style::SymbolProc, Style::Tab, Style::TrailingBlankLines, Style::TrailingComma, Style::TrailingWhitespace, Style::TrivialAccessors, Style::UnlessElse, Style::UnneededCapitalW, Style::UnneededPercentQ, Style::UnneededPercentX, Style::VariableInterpolation, Style::VariableName, Style::WhenThen, Style::WhileUntilDo, Style::WhileUntilModifier, Style::WordArray

Constant Summary

Constants included from Util

Util::ASGN_NODES, Util::EQUALS_ASGN_NODES, Util::OPERATOR_METHODS, Util::PROC_NEW_NODE, Util::SHORTHAND_ASGN_NODES

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from IgnoredNode

#ignore_node, #ignored_node?, #part_of_ignored_node?

Methods included from Util

begins_its_line?, block_length, command?, comment_line?, const_name, first_part_of_call_chain, lambda?, lambda_or_proc?, line_range, numeric_range_size, on_node, operator?, parentheses?, proc?, range_with_surrounding_space, source_range, strip_quotes, within_node?

Methods included from PathUtil

issue_deprecation_warning, match_path?, relative_path

Constructor Details

#initialize(config = nil, options = nil) ⇒ Cop


106
107
108
109
110
111
112
# File 'lib/rubocop/cop/cop.rb', line 106

def initialize(config = nil, options = nil)
  @config = config || Config.new
  @options = options || { auto_correct: false, debug: false }

  @offenses = []
  @corrections = []
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config


51
52
53
# File 'lib/rubocop/cop/cop.rb', line 51

def config
  @config
end

#correctionsObject (readonly)

Returns the value of attribute corrections


51
52
53
# File 'lib/rubocop/cop/cop.rb', line 51

def corrections
  @corrections
end

#offensesObject (readonly)

Returns the value of attribute offenses


51
52
53
# File 'lib/rubocop/cop/cop.rb', line 51

def offenses
  @offenses
end

#processed_sourceObject

TODO: Bad design.


52
53
54
# File 'lib/rubocop/cop/cop.rb', line 52

def processed_source
  @processed_source
end

Class Method Details

.allObject


56
57
58
# File 'lib/rubocop/cop/cop.rb', line 56

def self.all
  @all.clone
end

.cop_nameObject


90
91
92
# File 'lib/rubocop/cop/cop.rb', line 90

def self.cop_name
  @cop_name ||= name.to_s.split('::').last(2).join('/')
end

.cop_name_with_namespace(name, origin, basename, found_ns) ⇒ Object


74
75
76
77
78
79
80
# File 'lib/rubocop/cop/cop.rb', line 74

def self.cop_name_with_namespace(name, origin, basename, found_ns)
  if name != basename && found_ns != File.dirname(name).to_sym
    warn "#{origin}: #{name} has the wrong namespace - should be " \
         "#{found_ns}"
  end
  "#{found_ns}/#{basename}"
end

.cop_typeObject


94
95
96
# File 'lib/rubocop/cop/cop.rb', line 94

def self.cop_type
  name.to_s.split('::')[-2].downcase.to_sym
end

.inherited(subclass) ⇒ Object


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

def self.inherited(subclass)
  @all << subclass
end

.lint?Boolean


98
99
100
# File 'lib/rubocop/cop/cop.rb', line 98

def self.lint?
  cop_type == :lint
end

.non_railsObject


82
83
84
# File 'lib/rubocop/cop/cop.rb', line 82

def self.non_rails
  @all.without_type(:rails)
end

.qualified_cop_name(name, origin) ⇒ Object


60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/rubocop/cop/cop.rb', line 60

def self.qualified_cop_name(name, origin)
  @cop_names ||= Set.new(@all.map(&:cop_name))
  basename = File.basename(name)
  found_ns = @all.types.map(&:capitalize).select do |ns|
    @cop_names.include?("#{ns}/#{basename}")
  end

  case found_ns.size
  when 0 then name # No namespace found. Deal with it later in caller.
  when 1 then cop_name_with_namespace(name, origin, basename, found_ns[0])
  else fail AmbiguousCopName, "`#{basename}` used in #{origin}"
  end
end

.rails?Boolean


102
103
104
# File 'lib/rubocop/cop/cop.rb', line 102

def self.rails?
  cop_type == :rails
end

Instance Method Details

#add_offense(node, loc, message = nil, severity = nil) ⇒ Object


142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/rubocop/cop/cop.rb', line 142

def add_offense(node, loc, message = nil, severity = nil)
  location = loc.is_a?(Symbol) ? node.loc.send(loc) : loc

  return unless enabled_line?(location.line)

  # Don't include the same location twice for one cop.
  return if @offenses.find { |o| o.location == location }

  severity = custom_severity || severity || default_severity

  message ||= message(node)
  message = display_cop_names? ? "#{name}: #{message}" : message

  corrected = begin
                autocorrect(node) if autocorrect?
                autocorrect?
              rescue CorrectionNotPossible
                false
              end
  @offenses << Offense.new(severity, location, message, name, corrected)
  yield if block_given?
end

#autocorrect?Boolean


122
123
124
# File 'lib/rubocop/cop/cop.rb', line 122

def autocorrect?
  @options[:auto_correct] && support_autocorrect?
end

#config_to_allow_offensesObject


165
166
167
# File 'lib/rubocop/cop/cop.rb', line 165

def config_to_allow_offenses
  Formatter::DisabledConfigFormatter.config_to_allow_offenses[cop_name]
end

#config_to_allow_offenses=(hash) ⇒ Object


169
170
171
172
# File 'lib/rubocop/cop/cop.rb', line 169

def config_to_allow_offenses=(hash)
  Formatter::DisabledConfigFormatter.config_to_allow_offenses[cop_name] =
    hash
end

#cop_configObject


118
119
120
# File 'lib/rubocop/cop/cop.rb', line 118

def cop_config
  @config.for_cop(self)
end

#cop_nameObject Also known as: name


174
175
176
# File 'lib/rubocop/cop/cop.rb', line 174

def cop_name
  self.class.cop_name
end

#debug?Boolean


126
127
128
# File 'lib/rubocop/cop/cop.rb', line 126

def debug?
  @options[:debug]
end

#display_cop_names?Boolean


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

def display_cop_names?
  debug? || @options[:display_cop_names]
end

#join_force?(_force_class) ⇒ Boolean


114
115
116
# File 'lib/rubocop/cop/cop.rb', line 114

def join_force?(_force_class)
  false
end

#message(_node = nil) ⇒ Object


134
135
136
# File 'lib/rubocop/cop/cop.rb', line 134

def message(_node = nil)
  self.class::MSG
end

#relevant_file?(file) ⇒ Boolean


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

def relevant_file?(file)
  file_name_matches_any?(file, 'Include', true) &&
    !file_name_matches_any?(file, 'Exclude', false)
end

#support_autocorrect?Boolean


138
139
140
# File 'lib/rubocop/cop/cop.rb', line 138

def support_autocorrect?
  respond_to?(:autocorrect, true)
end