Showing 54 of 54 total issues
Method resource_options
has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring. Open
def resource_options
headers = merge_headers(
'Version' => '3',
'Prefer' => 'persistent-auth',
)
- 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 paginate_resource_get
has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring. Open
def paginate_resource_get(path = nil, sort_by = :name, direction = :asc)
log_header = "#{self.class.name}#paginate_resource_get"
page = 1
full_xml = nil
loop do
- 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 parse_node_extended
has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring. Open
def self.parse_node_extended(node, hash)
parse_first_node(node, :status, hash, :node => [:state])
parse_first_node(node, :storage, hash, :node => [:type, :address, :path])
parse_first_node(node, :storage, hash, :attribute => [:id])
- 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 operation
has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. Open
def operation(method, *_args)
if @operations.key?(method.to_sym)
builder = Nokogiri::XML::Builder.new do |xml|
xml.action { yield xml if block_given? }
end
- 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 create_new_disks_from_template
has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. Open
def create_new_disks_from_template(vm, options)
disks.each do |disk_object|
disk_options = disk_object.attributes_for_new_disk
disk_options[:sparse] = options[:sparse] unless options[:sparse].nil?
disk_options[:storage] = options[:storage] unless options[:storage].blank?
- 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 start
has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. Open
def start
if block_given?
operation(:start) { |xml| yield xml }
else
operation(:start)
- 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 clone_to_vm
has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. Open
def clone_to_vm(options)
# Create a VM based on this template
REQUIRED_CLONE_PARAMETERS.each do |key|
raise ArgumentError, "#{key.inspect} cannot be blank" if options[key].blank?
end
- 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 has too many optional parameters. [4/3] Open
def standard_collection(uri_suffix, element_name = nil, paginate = false, sort_by = :name, direction = :asc)
if paginate
doc = paginate_resource_get(uri_suffix, sort_by, direction)
else
xml = resource_get(uri_suffix)
- Read upRead up
- Exclude checks
Checks for methods with too many parameters.
The maximum number of parameters is configurable. Keyword arguments can optionally be excluded from the total count, as they add less complexity than positional or optional parameters.
Any number of arguments for initialize
method inside a block of
Struct.new
and Data.define
like this is always allowed:
Struct.new(:one, :two, :three, :four, :five, keyword_init: true) do
def initialize(one:, two:, three:, four:, five:)
end
end
This is because checking the number of arguments of the initialize
method
does not make sense.
NOTE: Explicit block argument &block
is not counted to prevent
erroneous change that is avoided by making block argument implicit.
Example: Max: 3
# good
def foo(a, b, c = 1)
end
Example: Max: 2
# bad
def foo(a, b, c = 1)
end
Example: CountKeywordArgs: true (default)
# counts keyword args towards the maximum
# bad (assuming Max is 3)
def foo(a, b, c, d: 1)
end
# good (assuming Max is 3)
def foo(a, b, c: 1)
end
Example: CountKeywordArgs: false
# don't count keyword args towards the maximum
# good (assuming Max is 3)
def foo(a, b, c, d: 1)
end
This cop also checks for the maximum number of optional parameters.
This can be configured using the MaxOptionalParameters
config option.
Example: MaxOptionalParameters: 3 (default)
# good
def foo(a = 1, b = 2, c = 3)
end
Example: MaxOptionalParameters: 2
# bad
def foo(a = 1, b = 2, c = 3)
end
Method getCfg
has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. Open
def getCfg(_snap = nil)
# TODO: Remove the following MiqException and any others
raise MiqException::MiqVimError, "Failed to retrieve configuration information for VM" if attributes.nil?
cfg_hash = {}
- 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 relationship
has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. Open
def relationship(rel)
if @relationships.key?(rel.to_sym)
rel_str = rel.to_s
rel_str = 'storage_domains' if rel_str == 'storagedomains'
rel_str = 'data_centers' if rel_str == 'datacenters'
- 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
Similar blocks of code found in 2 locations. Consider refactoring. Open
destination = source.create_vm(
:name => VM_NAME,
:clone_type => :full,
:cluster => Ovirt::Cluster.find_by_id(rhevm, source[:cluster][:id]),
:sparse => :false,
- Read upRead up
Duplicated Code
Duplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
When you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).
Tuning
This issue has a mass of 28.
We set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.
The threshold configuration represents the minimum mass a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.
If the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.
See codeclimate-duplication
's documentation for more information about tuning the mass threshold in your .codeclimate.yml
.
Refactorings
- Extract Method
- Extract Class
- Form Template Method
- Introduce Null Object
- Pull Up Method
- Pull Up Field
- Substitute Algorithm
Further Reading
- Don't Repeat Yourself on the C2 Wiki
- Duplicated Code on SourceMaking
- Refactoring: Improving the Design of Existing Code by Martin Fowler. Duplicated Code, p76
Similar blocks of code found in 2 locations. Consider refactoring. Open
destination = source.create_vm(
:name => DESTINATION_VM_NAME,
:clone_type => :skeletal,
:cluster => Ovirt::Cluster.find_by_id(rhevm, source[:cluster][:id]),
:sparse => :false,
- Read upRead up
Duplicated Code
Duplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
When you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).
Tuning
This issue has a mass of 28.
We set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.
The threshold configuration represents the minimum mass a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.
If the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.
See codeclimate-duplication
's documentation for more information about tuning the mass threshold in your .codeclimate.yml
.
Refactorings
- Extract Method
- Extract Class
- Form Template Method
- Introduce Null Object
- Pull Up Method
- Pull Up Field
- Substitute Algorithm
Further Reading
- Don't Repeat Yourself on the C2 Wiki
- Duplicated Code on SourceMaking
- Refactoring: Improving the Design of Existing Code by Martin Fowler. Duplicated Code, p76
Use sort_by(&:to_s)
instead of sort { |a, b| a.to_s <=> b.to_s }
. Open
base.relationships.keys.sort { |a, b| a.to_s <=> b.to_s }.each do |rel|
- Read upRead up
- Exclude checks
This cop identifies places where sort { |a, b| a.foo <=> b.foo }
can be replaced by sort_by(&:foo)
.
This cop also checks max
and min
methods.
Example:
# bad
array.sort { |a, b| a.foo <=> b.foo }
array.max { |a, b| a.foo <=> b.foo }
array.min { |a, b| a.foo <=> b.foo }
array.sort { |a, b| a[:foo] <=> b[:foo] }
# good
array.sort_by(&:foo)
array.sort_by { |v| v.foo }
array.sort_by do |var|
var.foo
end
array.max_by(&:foo)
array.min_by(&:foo)
array.sort_by { |a| a[:foo] }
Duplicate branch body detected. Open
when :linked then clone_to_vm(options)
- Read upRead up
- Exclude checks
Checks that there are no repeated bodies
within if/unless
, case-when
, case-in
and rescue
constructs.
With IgnoreLiteralBranches: true
, branches are not registered
as offenses if they return a basic literal value (string, symbol,
integer, float, rational, complex, true
, false
, or nil
), or
return an array, hash, regexp or range that only contains one of
the above basic literal values.
With IgnoreConstantBranches: true
, branches are not registered
as offenses if they return a constant value.
Example:
# bad
if foo
do_foo
do_something_else
elsif bar
do_foo
do_something_else
end
# good
if foo || bar
do_foo
do_something_else
end
# bad
case x
when foo
do_foo
when bar
do_foo
else
do_something_else
end
# good
case x
when foo, bar
do_foo
else
do_something_else
end
# bad
begin
do_something
rescue FooError
handle_error
rescue BarError
handle_error
end
# good
begin
do_something
rescue FooError, BarError
handle_error
end
Example: IgnoreLiteralBranches: true
# good
case size
when "small" then 100
when "medium" then 250
when "large" then 1000
else 250
end
Example: IgnoreConstantBranches: true
# good
case size
when "small" then SMALL_SIZE
when "medium" then MEDIUM_SIZE
when "large" then LARGE_SIZE
else MEDIUM_SIZE
end
Prefer using YAML.safe_load
over YAML.load
. Open
raw_content = YAML.load(content)
- Read upRead up
- Exclude checks
Checks for the use of YAML class methods which have potential security issues leading to remote code execution when loading from an untrusted source.
NOTE: Ruby 3.1+ (Psych 4) uses Psych.load
as Psych.safe_load
by default.
Safety:
The behavior of the code might change depending on what was
in the YAML payload, since YAML.safe_load
is more restrictive.
Example:
# bad
YAML.load("--- !ruby/object:Foo {}") # Psych 3 is unsafe by default
# good
YAML.safe_load("--- !ruby/object:Foo {}", [Foo]) # Ruby 2.5 (Psych 3)
YAML.safe_load("--- !ruby/object:Foo {}", permitted_classes: [Foo]) # Ruby 3.0- (Psych 3)
YAML.load("--- !ruby/object:Foo {}", permitted_classes: [Foo]) # Ruby 3.1+ (Psych 4)
YAML.dump(foo)
Use match?
instead of =~
when MatchData
is not used. Open
raise VmNotReadyToBoot, [err.message, err] if err.message =~ /disks .+ are locked/
- Read upRead up
- Exclude checks
In Ruby 2.4, String#match?
, Regexp#match?
and Symbol#match?
have been added. The methods are faster than match
.
Because the methods avoid creating a MatchData
object or saving
backref.
So, when MatchData
is not used, use match?
instead of match
.
Example:
# bad
def foo
if x =~ /re/
do_something
end
end
# bad
def foo
if x.match(/re/)
do_something
end
end
# bad
def foo
if /re/ === x
do_something
end
end
# good
def foo
if x.match?(/re/)
do_something
end
end
# good
def foo
if x =~ /re/
do_something(Regexp.last_match)
end
end
# good
def foo
if x.match(/re/)
do_something($~)
end
end
# good
def foo
if /re/ === x
do_something($~)
end
end
Avoid hard coding large quantities of data in code. Prefer reading the data from an external source. Open
EVENT_CODES = {
# Code Description
0 => "UNASSIGNED",
1 => "VDC_START",
2 => "VDC_STOP",
- Read upRead up
- Exclude checks
Checks for literals with extremely many entries. This is indicative of configuration or data that may be better extracted somewhere else, like a database, fetched from an API, or read from a non-code file (CSV, JSON, YAML, etc.).
Example:
# bad
# Huge Array literal
[1, 2, '...', 999_999_999]
# bad
# Huge Hash literal
{ 1 => 1, 2 => 2, '...' => '...', 999_999_999 => 999_999_999}
# bad
# Huge Set "literal"
Set[1, 2, '...', 999_999_999]
# good
# Reasonably sized Array literal
[1, 2, '...', 10]
# good
# Reading huge Array from external data source
# File.readlines('numbers.txt', chomp: true).map!(&:to_i)
# good
# Reasonably sized Hash literal
{ 1 => 1, 2 => 2, '...' => '...', 10 => 10}
# good
# Reading huge Hash from external data source
CSV.foreach('numbers.csv', headers: true).each_with_object({}) do |row, hash|
hash[row["key"].to_i] = row["value"].to_i
end
# good
# Reasonably sized Set "literal"
Set[1, 2, '...', 10]
# good
# Reading huge Set from external data source
SomeFramework.config_for(:something)[:numbers].to_set
Call super
to initialize state of the parent class. Open
def initialize(*_args)
end
- Read upRead up
- Exclude checks
Checks for the presence of constructors and lifecycle callbacks
without calls to super
.
This cop does not consider method_missing
(and respond_to_missing?
)
because in some cases it makes sense to overtake what is considered a
missing method. In other cases, the theoretical ideal handling could be
challenging or verbose for no actual gain.
Autocorrection is not supported because the position of super
cannot be
determined automatically.
Object
and BasicObject
are allowed by this cop because of their
stateless nature. However, sometimes you might want to allow other parent
classes from this cop, for example in the case of an abstract class that is
not meant to be called with super
. In those cases, you can use the
AllowedParentClasses
option to specify which classes should be allowed
in addition to Object
and BasicObject
.
Example:
# bad
class Employee < Person
def initialize(name, salary)
@salary = salary
end
end
# good
class Employee < Person
def initialize(name, salary)
super(name)
@salary = salary
end
end
# bad
Employee = Class.new(Person) do
def initialize(name, salary)
@salary = salary
end
end
# good
Employee = Class.new(Person) do
def initialize(name, salary)
super(name)
@salary = salary
end
end
# bad
class Parent
def self.inherited(base)
do_something
end
end
# good
class Parent
def self.inherited(base)
super
do_something
end
end
# good
class ClassWithNoParent
def initialize
do_something
end
end
Example: AllowedParentClasses: [MyAbstractClass]
# good
class MyConcreteClass < MyAbstractClass
def initialize
do_something
end
end
Do not suppress exceptions. Open
rescue VmIsNotRunning
- Read upRead up
- Exclude checks
Checks for rescue
blocks with no body.
Example:
# bad
def some_method
do_something
rescue
end
# bad
begin
do_something
rescue
end
# good
def some_method
do_something
rescue
handle_exception
end
# good
begin
do_something
rescue
handle_exception
end
Example: AllowComments: true (default)
# good
def some_method
do_something
rescue
# do nothing
end
# good
begin
do_something
rescue
# do nothing
end
Example: AllowComments: false
# bad
def some_method
do_something
rescue
# do nothing
end
# bad
begin
do_something
rescue
# do nothing
end
Example: AllowNil: true (default)
# good
def some_method
do_something
rescue
nil
end
# good
begin
do_something
rescue
# do nothing
end
# good
do_something rescue nil
Example: AllowNil: false
# bad
def some_method
do_something
rescue
nil
end
# bad
begin
do_something
rescue
nil
end
# bad
do_something rescue nil
Remove unnecessary require
statement. Open
require 'pp'
- Read upRead up
- Exclude checks
Checks for unnecessary require
statement.
The following features are unnecessary require
statement because
they are already loaded. e.g. Ruby 2.2:
ruby -ve 'p $LOADED_FEATURES.reject { |feature| %r|/| =~ feature }'
ruby 2.2.8p477 (2017-09-14 revision 59906) [x86_64-darwin13]
["enumerator.so", "rational.so", "complex.so", "thread.rb"]
Below are the features that each TargetRubyVersion
targets.
* 2.0+ ... `enumerator`
* 2.1+ ... `thread`
* 2.2+ ... Add `rational` and `complex` above
* 2.5+ ... Add `pp` above
* 2.7+ ... Add `ruby2_keywords` above
* 3.1+ ... Add `fiber` above
* 3.2+ ... `set`
This cop target those features.
Example:
# bad
require 'unloaded_feature'
require 'thread'
# good
require 'unloaded_feature'