Cyclomatic complexity for fudge_error is too high. [8/6] Open
def fudge_error(exitstatus, stderr)
if exitstatus == 0 && stderr.index("WARNING: Creating rsc_location constraint") && !stderr.index("ERROR")
# Special case for "crm resource migrate" with no node specified, to squash
# warning about persistent location constraint (remember my *sigh* in the
# comment above?)
- Read upRead up
- Exclude checks
This cop checks that the cyclomatic complexity of methods is not higher than the configured maximum. The cyclomatic complexity is the number of linearly independent paths through a method. The algorithm counts decision points and adds one.
An if statement (or unless or ?:) increases the complexity by one. An else branch does not, since it doesn't add a decision point. The && operator (or keyword and) can be converted to a nested if statement, and ||/or is shorthand for a sequence of ifs, so they also add one. Loops can be said to have an exit condition, so they add one.
Perceived complexity for fudge_error is too high. [9/7] Open
def fudge_error(exitstatus, stderr)
if exitstatus == 0 && stderr.index("WARNING: Creating rsc_location constraint") && !stderr.index("ERROR")
# Special case for "crm resource migrate" with no node specified, to squash
# warning about persistent location constraint (remember my *sigh* in the
# comment above?)
- Read upRead up
- Exclude checks
This cop tries to produce a complexity score that's a measure of the
complexity the reader experiences when looking at a method. For that
reason it considers when
nodes as something that doesn't add as much
complexity as an if
or a &&
. Except if it's one of those special
case
/when
constructs where there's no expression after case
. Then
the cop treats it as an if
/elsif
/elsif
... and lets all the when
nodes count. In contrast to the CyclomaticComplexity cop, this cop
considers else
nodes as adding complexity.
Example:
def my_method # 1
if cond # 1
case var # 2 (0.8 + 4 * 0.2, rounded)
when 1 then func_one
when 2 then func_two
when 3 then func_three
when 4..10 then func_other
end
else # 1
do_something until a && b # 2
end # ===
end # 7 complexity points
Assignment Branch Condition size for cibadmin is too high. [16.76/15] Open
def cibadmin(*cmd)
out, err, status = Util.run_as(current_user, current_pass, 'cibadmin', *cmd)
case status.exitstatus
when 0
return out
- Read upRead up
- Exclude checks
This cop checks that the ABC size of methods is not higher than the configured maximum. The ABC size is based on assignments, branches (method calls), and conditions. See http://c2.com/cgi/wiki?AbcMetric
Method ignore_command
has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring. Open
def ignore_command(input, cmd)
return true if cmd[0] == 'cluster'
if cmd[0] == 'configure'
return true if input == 'show'
return true if cmd[1] == 'graph'
- Read upRead up
Cognitive Complexity
Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.
A method's cognitive complexity is based on a few simple rules:
- Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
- Code is considered more complex for each "break in the linear flow of the code"
- Code is considered more complex when "flow breaking structures are nested"
Further reading
Method fudge_error
has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. Open
def fudge_error(exitstatus, stderr)
if exitstatus == 0 && stderr.index("WARNING: Creating rsc_location constraint") && !stderr.index("ERROR")
# Special case for "crm resource migrate" with no node specified, to squash
# warning about persistent location constraint (remember my *sigh* in the
# comment above?)
- Read upRead up
Cognitive Complexity
Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.
A method's cognitive complexity is based on a few simple rules:
- Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
- Code is considered more complex for each "break in the linear flow of the code"
- Code is considered more complex when "flow breaking structures are nested"
Further reading
Favor format
over String#%
. Open
fail(SecurityError, _('Permission denied for user %{user}') % { user: current_user })
- Read upRead up
- Exclude checks
This cop enforces the use of a single string formatting utility. Valid options include Kernel#format, Kernel#sprintf and String#%.
The detection of String#% cannot be implemented in a reliable manner for all cases, so only two scenarios are considered - if the first argument is a string literal and if the second argument is an array literal.
Example: EnforcedStyle: format(default)
# bad
puts sprintf('%10s', 'hoge')
puts '%10s' % 'hoge'
# good
puts format('%10s', 'hoge')
Example: EnforcedStyle: sprintf
# bad
puts format('%10s', 'hoge')
puts '%10s' % 'hoge'
# good
puts sprintf('%10s', 'hoge')
Example: EnforcedStyle: percent
# bad
puts format('%10s', 'hoge')
puts sprintf('%10s', 'hoge')
# good
puts '%10s' % 'hoge'
Always use raise
to signal exceptions. Open
fail(SecurityError, _('Permission denied for user %{user}') % { user: current_user })
- Read upRead up
- Exclude checks
This cop checks for uses of fail
and raise
.
Example: EnforcedStyle: only_raise (default)
# The `only_raise` style enforces the sole use of `raise`.
# bad
begin
fail
rescue Exception
# handle it
end
def watch_out
fail
rescue Exception
# handle it
end
Kernel.fail
# good
begin
raise
rescue Exception
# handle it
end
def watch_out
raise
rescue Exception
# handle it
end
Kernel.raise
Example: EnforcedStyle: only_fail
# The `only_fail` style enforces the sole use of `fail`.
# bad
begin
raise
rescue Exception
# handle it
end
def watch_out
raise
rescue Exception
# handle it
end
Kernel.raise
# good
begin
fail
rescue Exception
# handle it
end
def watch_out
fail
rescue Exception
# handle it
end
Kernel.fail
Example: EnforcedStyle: semantic
# The `semantic` style enforces the use of `fail` to signal an
# exception, then will use `raise` to trigger an offense after
# it has been rescued.
# bad
begin
raise
rescue Exception
# handle it
end
def watch_out
# Error thrown
rescue Exception
fail
end
Kernel.fail
Kernel.raise
# good
begin
fail
rescue Exception
# handle it
end
def watch_out
fail
rescue Exception
raise 'Preferably with descriptive message'
end
explicit_receiver.fail
explicit_receiver.raise
Avoid using {...}
for multi-line blocks. Open
@mutex.synchronize {
- Read upRead up
- Exclude checks
Check for uses of braces or do/end around single line or multi-line blocks.
Example: EnforcedStyle: linecountbased (default)
# bad - single line block
items.each do |item| item / 5 end
# good - single line block
items.each { |item| item / 5 }
# bad - multi-line block
things.map { |thing|
something = thing.some_method
process(something)
}
# good - multi-line block
things.map do |thing|
something = thing.some_method
process(something)
end
Example: EnforcedStyle: semantic
# Prefer `do...end` over `{...}` for procedural blocks.
# return value is used/assigned
# bad
foo = map do |x|
x
end
puts (map do |x|
x
end)
# return value is not used out of scope
# good
map do |x|
x
end
# Prefer `{...}` over `do...end` for functional blocks.
# return value is not used out of scope
# bad
each { |x|
x
}
# return value is used/assigned
# good
foo = map { |x|
x
}
map { |x|
x
}.inspect
Example: EnforcedStyle: bracesforchaining
# bad
words.each do |word|
word.flip.flop
end.join("-")
# good
words.each { |word|
word.flip.flop
}.join("-")
Prefer annotated tokens (like %<foo>s</foo>
) over template tokens (like %{foo}
). Open
fail(NotFoundError, _('The object/attribute does not exist (cibadmin %{cmd})') % { cmd: cmd.join(" ") })
- Read upRead up
- Exclude checks
Use a consistent style for named format string tokens.
Note:
unannotated
style cop only works for strings
which are passed as arguments to those methods:
sprintf
, format
, %
.
The reason is that unannotated format is very similar
to encoded URLs or Date/Time formatting strings.
Example: EnforcedStyle: annotated (default)
# bad
format('%{greeting}', greeting: 'Hello')
format('%s', 'Hello')
# good
format('%<greeting>s', greeting: 'Hello')</greeting>
Example: EnforcedStyle: template
# bad
format('%<greeting>s', greeting: 'Hello')
format('%s', 'Hello')
# good
format('%{greeting}', greeting: 'Hello')</greeting>
Example: EnforcedStyle: unannotated
# bad
format('%<greeting>s', greeting: 'Hello')
format('%{greeting}', 'Hello')
# good
format('%s', 'Hello')</greeting>
Favor format
over String#%
. Open
fail(NotFoundError, _('The object/attribute does not exist (cibadmin %{cmd})') % { cmd: cmd.join(" ") })
- Read upRead up
- Exclude checks
This cop enforces the use of a single string formatting utility. Valid options include Kernel#format, Kernel#sprintf and String#%.
The detection of String#% cannot be implemented in a reliable manner for all cases, so only two scenarios are considered - if the first argument is a string literal and if the second argument is an array literal.
Example: EnforcedStyle: format(default)
# bad
puts sprintf('%10s', 'hoge')
puts '%10s' % 'hoge'
# good
puts format('%10s', 'hoge')
Example: EnforcedStyle: sprintf
# bad
puts format('%10s', 'hoge')
puts '%10s' % 'hoge'
# good
puts sprintf('%10s', 'hoge')
Example: EnforcedStyle: percent
# bad
puts format('%10s', 'hoge')
puts sprintf('%10s', 'hoge')
# good
puts '%10s' % 'hoge'
Favor format
over String#%
. Open
fail(_('Error invoking cibadmin %{cmd}: %{msg}') % { cmd: cmd.join(" "), msg: err })
- Read upRead up
- Exclude checks
This cop enforces the use of a single string formatting utility. Valid options include Kernel#format, Kernel#sprintf and String#%.
The detection of String#% cannot be implemented in a reliable manner for all cases, so only two scenarios are considered - if the first argument is a string literal and if the second argument is an array literal.
Example: EnforcedStyle: format(default)
# bad
puts sprintf('%10s', 'hoge')
puts '%10s' % 'hoge'
# good
puts format('%10s', 'hoge')
Example: EnforcedStyle: sprintf
# bad
puts format('%10s', 'hoge')
puts '%10s' % 'hoge'
# good
puts sprintf('%10s', 'hoge')
Example: EnforcedStyle: percent
# bad
puts format('%10s', 'hoge')
puts sprintf('%10s', 'hoge')
# good
puts '%10s' % 'hoge'
Prefer annotated tokens (like %<foo>s</foo>
) over template tokens (like %{foo}
). Open
fail(_('Error invoking cibadmin %{cmd}: %{msg}') % { cmd: cmd.join(" "), msg: err })
- Read upRead up
- Exclude checks
Use a consistent style for named format string tokens.
Note:
unannotated
style cop only works for strings
which are passed as arguments to those methods:
sprintf
, format
, %
.
The reason is that unannotated format is very similar
to encoded URLs or Date/Time formatting strings.
Example: EnforcedStyle: annotated (default)
# bad
format('%{greeting}', greeting: 'Hello')
format('%s', 'Hello')
# good
format('%<greeting>s', greeting: 'Hello')</greeting>
Example: EnforcedStyle: template
# bad
format('%<greeting>s', greeting: 'Hello')
format('%s', 'Hello')
# good
format('%{greeting}', greeting: 'Hello')</greeting>
Example: EnforcedStyle: unannotated
# bad
format('%<greeting>s', greeting: 'Hello')
format('%{greeting}', 'Hello')
# good
format('%s', 'Hello')</greeting>
Always use raise
to signal exceptions. Open
fail(NotFoundError, _('The object/attribute does not exist (cibadmin %{cmd})') % { cmd: cmd.join(" ") })
- Read upRead up
- Exclude checks
This cop checks for uses of fail
and raise
.
Example: EnforcedStyle: only_raise (default)
# The `only_raise` style enforces the sole use of `raise`.
# bad
begin
fail
rescue Exception
# handle it
end
def watch_out
fail
rescue Exception
# handle it
end
Kernel.fail
# good
begin
raise
rescue Exception
# handle it
end
def watch_out
raise
rescue Exception
# handle it
end
Kernel.raise
Example: EnforcedStyle: only_fail
# The `only_fail` style enforces the sole use of `fail`.
# bad
begin
raise
rescue Exception
# handle it
end
def watch_out
raise
rescue Exception
# handle it
end
Kernel.raise
# good
begin
fail
rescue Exception
# handle it
end
def watch_out
fail
rescue Exception
# handle it
end
Kernel.fail
Example: EnforcedStyle: semantic
# The `semantic` style enforces the use of `fail` to signal an
# exception, then will use `raise` to trigger an offense after
# it has been rescued.
# bad
begin
raise
rescue Exception
# handle it
end
def watch_out
# Error thrown
rescue Exception
fail
end
Kernel.fail
Kernel.raise
# good
begin
fail
rescue Exception
# handle it
end
def watch_out
fail
rescue Exception
raise 'Preferably with descriptive message'
end
explicit_receiver.fail
explicit_receiver.raise
Prefer double-quoted strings inside interpolations. Open
CrmEvents.instance.push "crm #{cmd.join(' ')}\n#{input}"
- Read upRead up
- Exclude checks
This cop checks that quotes inside the string interpolation match the configured preference.
Example: EnforcedStyle: single_quotes (default)
# bad
result = "Tests #{success ? "PASS" : "FAIL"}"
# good
result = "Tests #{success ? 'PASS' : 'FAIL'}"
Example: EnforcedStyle: double_quotes
# bad
result = "Tests #{success ? 'PASS' : 'FAIL'}"
# good
result = "Tests #{success ? "PASS" : "FAIL"}"
Prefer annotated tokens (like %<foo>s</foo>
) over template tokens (like %{foo}
). Open
fail(SecurityError, _('Permission denied for user %{user}') % { user: current_user })
- Read upRead up
- Exclude checks
Use a consistent style for named format string tokens.
Note:
unannotated
style cop only works for strings
which are passed as arguments to those methods:
sprintf
, format
, %
.
The reason is that unannotated format is very similar
to encoded URLs or Date/Time formatting strings.
Example: EnforcedStyle: annotated (default)
# bad
format('%{greeting}', greeting: 'Hello')
format('%s', 'Hello')
# good
format('%<greeting>s', greeting: 'Hello')</greeting>
Example: EnforcedStyle: template
# bad
format('%<greeting>s', greeting: 'Hello')
format('%s', 'Hello')
# good
format('%{greeting}', greeting: 'Hello')</greeting>
Example: EnforcedStyle: unannotated
# bad
format('%<greeting>s', greeting: 'Hello')
format('%{greeting}', 'Hello')
# good
format('%s', 'Hello')</greeting>
Prefer annotated tokens (like %<foo>s</foo>
) over template tokens (like %{foo}
). Open
fail(_('Error invoking cibadmin %{cmd}: %{msg}') % { cmd: cmd.join(" "), msg: err })
- Read upRead up
- Exclude checks
Use a consistent style for named format string tokens.
Note:
unannotated
style cop only works for strings
which are passed as arguments to those methods:
sprintf
, format
, %
.
The reason is that unannotated format is very similar
to encoded URLs or Date/Time formatting strings.
Example: EnforcedStyle: annotated (default)
# bad
format('%{greeting}', greeting: 'Hello')
format('%s', 'Hello')
# good
format('%<greeting>s', greeting: 'Hello')</greeting>
Example: EnforcedStyle: template
# bad
format('%<greeting>s', greeting: 'Hello')
format('%s', 'Hello')
# good
format('%{greeting}', greeting: 'Hello')</greeting>
Example: EnforcedStyle: unannotated
# bad
format('%<greeting>s', greeting: 'Hello')
format('%{greeting}', 'Hello')
# good
format('%s', 'Hello')</greeting>
Always use raise
to signal exceptions. Open
fail(_('Error invoking cibadmin %{cmd}: %{msg}') % { cmd: cmd.join(" "), msg: err })
- Read upRead up
- Exclude checks
This cop checks for uses of fail
and raise
.
Example: EnforcedStyle: only_raise (default)
# The `only_raise` style enforces the sole use of `raise`.
# bad
begin
fail
rescue Exception
# handle it
end
def watch_out
fail
rescue Exception
# handle it
end
Kernel.fail
# good
begin
raise
rescue Exception
# handle it
end
def watch_out
raise
rescue Exception
# handle it
end
Kernel.raise
Example: EnforcedStyle: only_fail
# The `only_fail` style enforces the sole use of `fail`.
# bad
begin
raise
rescue Exception
# handle it
end
def watch_out
raise
rescue Exception
# handle it
end
Kernel.raise
# good
begin
fail
rescue Exception
# handle it
end
def watch_out
fail
rescue Exception
# handle it
end
Kernel.fail
Example: EnforcedStyle: semantic
# The `semantic` style enforces the use of `fail` to signal an
# exception, then will use `raise` to trigger an offense after
# it has been rescued.
# bad
begin
raise
rescue Exception
# handle it
end
def watch_out
# Error thrown
rescue Exception
fail
end
Kernel.fail
Kernel.raise
# good
begin
fail
rescue Exception
# handle it
end
def watch_out
fail
rescue Exception
raise 'Preferably with descriptive message'
end
explicit_receiver.fail
explicit_receiver.raise
Favor modifier if
usage when having a single-line body. Another good alternative is the usage of control flow &&
/||
. Open
if stderr.match(/-54.*permission denied/i) || stderr.match(/-13.*permission denied/i)
- Read upRead up
- Exclude checks
Checks for if and unless statements that would fit on one line
if written as a modifier if/unless. The maximum line length is
configured in the Metrics/LineLength
cop.
Example:
# bad
if condition
do_stuff(bar)
end
unless qux.empty?
Foo.do_something
end
# good
do_stuff(bar) if condition
Foo.do_something unless qux.empty?
Prefer annotated tokens (like %<foo>s</foo>
) over template tokens (like %{foo}
). Open
stderr = _('Permission denied for user %{user}') % {:user => current_user}
- Read upRead up
- Exclude checks
Use a consistent style for named format string tokens.
Note:
unannotated
style cop only works for strings
which are passed as arguments to those methods:
sprintf
, format
, %
.
The reason is that unannotated format is very similar
to encoded URLs or Date/Time formatting strings.
Example: EnforcedStyle: annotated (default)
# bad
format('%{greeting}', greeting: 'Hello')
format('%s', 'Hello')
# good
format('%<greeting>s', greeting: 'Hello')</greeting>
Example: EnforcedStyle: template
# bad
format('%<greeting>s', greeting: 'Hello')
format('%s', 'Hello')
# good
format('%{greeting}', greeting: 'Hello')</greeting>
Example: EnforcedStyle: unannotated
# bad
format('%<greeting>s', greeting: 'Hello')
format('%{greeting}', 'Hello')
# good
format('%s', 'Hello')</greeting>
Use the new Ruby 1.9 hash syntax. Open
stderr = _('Permission denied for user %{user}') % {:user => current_user}
- Read upRead up
- Exclude checks
This cop checks hash literal syntax.
It can enforce either the use of the class hash rocket syntax or the use of the newer Ruby 1.9 syntax (when applicable).
A separate offense is registered for each problematic pair.
The supported styles are:
- ruby19 - forces use of the 1.9 syntax (e.g.
{a: 1}
) when hashes have all symbols for keys - hash_rockets - forces use of hash rockets for all hashes
- nomixedkeys - simply checks for hashes with mixed syntaxes
- ruby19nomixed_keys - forces use of ruby 1.9 syntax and forbids mixed syntax hashes
Example: EnforcedStyle: ruby19 (default)
# bad
{:a => 2}
{b: 1, :c => 2}
# good
{a: 2, b: 1}
{:c => 2, 'd' => 2} # acceptable since 'd' isn't a symbol
{d: 1, 'e' => 2} # technically not forbidden
Example: EnforcedStyle: hash_rockets
# bad
{a: 1, b: 2}
{c: 1, 'd' => 5}
# good
{:a => 1, :b => 2}
Example: EnforcedStyle: nomixedkeys
# bad
{:a => 1, b: 2}
{c: 1, 'd' => 2}
# good
{:a => 1, :b => 2}
{c: 1, d: 2}
Example: EnforcedStyle: ruby19nomixed_keys
# bad
{:a => 1, :b => 2}
{c: 2, 'd' => 3} # should just use hash rockets
# good
{a: 1, b: 2}
{:c => 3, 'd' => 4}
Use exitstatus.zero?
instead of exitstatus == 0
. Open
if exitstatus == 0 && stderr.index("WARNING: Creating rsc_location constraint") && !stderr.index("ERROR")
- Read upRead up
- Exclude checks
This cop checks for usage of comparison operators (==
,
>
, <
) to test numbers as zero, positive, or negative.
These can be replaced by their respective predicate methods.
The cop can also be configured to do the reverse.
The cop disregards #nonzero?
as it its value is truthy or falsey,
but not true
and false
, and thus not always interchangeable with
!= 0
.
The cop ignores comparisons to global variables, since they are often
populated with objects which can be compared with integers, but are
not themselves Interger
polymorphic.
Example: EnforcedStyle: predicate (default)
# bad
foo == 0
0 > foo
bar.baz > 0
# good
foo.zero?
foo.negative?
bar.baz.positive?
Example: EnforcedStyle: comparison
# bad
foo.zero?
foo.negative?
bar.baz.positive?
# good
foo == 0
0 > foo
bar.baz > 0
Space inside } missing. Open
stderr = _('Permission denied for user %{user}') % {:user => current_user}
- Read upRead up
- Exclude checks
Checks that braces used for hash literals have or don't have surrounding space depending on configuration.
Example: EnforcedStyle: space
# The `space` style enforces that hash literals have
# surrounding space.
# bad
h = {a: 1, b: 2}
# good
h = { a: 1, b: 2 }
Example: EnforcedStyle: no_space
# The `no_space` style enforces that hash literals have
# no surrounding space.
# bad
h = { a: 1, b: 2 }
# good
h = {a: 1, b: 2}
Example: EnforcedStyle: compact
# The `compact` style normally requires a space inside
# hash braces, with the exception that successive left
# braces or right braces are collapsed together in nested hashes.
# bad
h = { a: { b: 2 } }
# good
h = { a: { b: 2 }}
Prefer double-quoted strings inside interpolations. Open
CrmEvents.instance.push "crm #{cmd.join(' ')}"
- Read upRead up
- Exclude checks
This cop checks that quotes inside the string interpolation match the configured preference.
Example: EnforcedStyle: single_quotes (default)
# bad
result = "Tests #{success ? "PASS" : "FAIL"}"
# good
result = "Tests #{success ? 'PASS' : 'FAIL'}"
Example: EnforcedStyle: double_quotes
# bad
result = "Tests #{success ? 'PASS' : 'FAIL'}"
# good
result = "Tests #{success ? "PASS" : "FAIL"}"
Space inside { missing. Open
stderr = _('Permission denied for user %{user}') % {:user => current_user}
- Read upRead up
- Exclude checks
Checks that braces used for hash literals have or don't have surrounding space depending on configuration.
Example: EnforcedStyle: space
# The `space` style enforces that hash literals have
# surrounding space.
# bad
h = {a: 1, b: 2}
# good
h = { a: 1, b: 2 }
Example: EnforcedStyle: no_space
# The `no_space` style enforces that hash literals have
# no surrounding space.
# bad
h = { a: 1, b: 2 }
# good
h = {a: 1, b: 2}
Example: EnforcedStyle: compact
# The `compact` style normally requires a space inside
# hash braces, with the exception that successive left
# braces or right braces are collapsed together in nested hashes.
# bad
h = { a: { b: 2 } }
# good
h = { a: { b: 2 }}
Favor format
over String#%
. Open
stderr = _('Permission denied for user %{user}') % {:user => current_user}
- Read upRead up
- Exclude checks
This cop enforces the use of a single string formatting utility. Valid options include Kernel#format, Kernel#sprintf and String#%.
The detection of String#% cannot be implemented in a reliable manner for all cases, so only two scenarios are considered - if the first argument is a string literal and if the second argument is an array literal.
Example: EnforcedStyle: format(default)
# bad
puts sprintf('%10s', 'hoge')
puts '%10s' % 'hoge'
# good
puts format('%10s', 'hoge')
Example: EnforcedStyle: sprintf
# bad
puts format('%10s', 'hoge')
puts '%10s' % 'hoge'
# good
puts sprintf('%10s', 'hoge')
Example: EnforcedStyle: percent
# bad
puts format('%10s', 'hoge')
puts sprintf('%10s', 'hoge')
# good
puts '%10s' % 'hoge'