Assignment Branch Condition size for << is too high. [18.63/15] Open
def <<(entity)
url_chunk, options = setup_entity_post_request(entity)
result = execute_entity_post_request(options, url_chunk)
if entity.is_new?
doc = ::Nokogiri::XML(result.body).remove_namespaces!
- 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 has too many lines. [12/10] Open
def execute_entity_post_request(options, url_chunk)
result = service.execute(url_chunk, options)
unless result.code.to_s =~ /^2[0-9][0-9]$/
service.logger.debug <<-EOS
[ODATA: #{service_name}]
- Read upRead up
- Exclude checks
This cop checks if the length of a method exceeds some maximum value. Comment lines can optionally be ignored. The maximum allowed length is configurable.
Method has too many lines. [11/10] Open
def setup_entity_post_request(entity)
primary_key = entity.get_property(entity.primary_key).url_value
chunk = entity.is_new? ? name : "#{name}(#{primary_key})"
options = {
method: :post,
- Read upRead up
- Exclude checks
This cop checks if the length of a method exceeds some maximum value. Comment lines can optionally be ignored. The maximum allowed length is configurable.
Method has too many lines. [11/10] Open
def <<(entity)
url_chunk, options = setup_entity_post_request(entity)
result = execute_entity_post_request(options, url_chunk)
if entity.is_new?
doc = ::Nokogiri::XML(result.body).remove_namespaces!
- Read upRead up
- Exclude checks
This cop checks if the length of a method exceeds some maximum value. Comment lines can optionally be ignored. The maximum allowed length is configurable.
Assignment Branch Condition size for execute_entity_post_request is too high. [15.07/15] Open
def execute_entity_post_request(options, url_chunk)
result = service.execute(url_chunk, options)
unless result.code.to_s =~ /^2[0-9][0-9]$/
service.logger.debug <<-EOS
[ODATA: #{service_name}]
- 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
FrOData::EntitySet#<< refers to 'entity' more than self (maybe move it to another class?) Open
if entity.is_new?
doc = ::Nokogiri::XML(result.body).remove_namespaces!
primary_key_node = doc.xpath("//content/properties/#{entity.primary_key}").first
entity[entity.primary_key] = primary_key_node.content unless primary_key_node.nil?
end
- Read upRead up
- Exclude checks
Feature Envy occurs when a code fragment references another object more often than it references itself, or when several clients do the same series of manipulations on a particular type of object.
Feature Envy reduces the code's ability to communicate intent: code that "belongs" on one class but which is located in another can be hard to find, and may upset the "System of Names" in the host class.
Feature Envy also affects the design's flexibility: A code fragment that is in the wrong class creates couplings that may not be natural within the application's domain, and creates a loss of cohesion in the unwilling host class.
Feature Envy often arises because it must manipulate other objects (usually its arguments) to get them into a useful form, and one force preventing them (the arguments) doing this themselves is that the common knowledge lives outside the arguments, or the arguments are of too basic a type to justify extending that type. Therefore there must be something which 'knows' about the contents or purposes of the arguments. That thing would have to be more than just a basic type, because the basic types are either containers which don't know about their contents, or they are single objects which can't capture their relationship with their fellows of the same type. So, this thing with the extra knowledge should be reified into a class, and the utility method will most likely belong there.
Example
Running Reek on:
class Warehouse
def sale_price(item)
(item.price - item.rebate) * @vat
end
end
would report:
Warehouse#total_price refers to item more than self (FeatureEnvy)
since this:
(item.price - item.rebate)
belongs to the Item class, not the Warehouse.
FrOData::EntitySet#setup_entity_post_request refers to 'entity' more than self (maybe move it to another class?) Open
primary_key = entity.get_property(entity.primary_key).url_value
chunk = entity.is_new? ? name : "#{name}(#{primary_key})"
options = {
method: :post,
body: entity.to_xml.gsub(/\n\s+/, ''),
- Read upRead up
- Exclude checks
Feature Envy occurs when a code fragment references another object more often than it references itself, or when several clients do the same series of manipulations on a particular type of object.
Feature Envy reduces the code's ability to communicate intent: code that "belongs" on one class but which is located in another can be hard to find, and may upset the "System of Names" in the host class.
Feature Envy also affects the design's flexibility: A code fragment that is in the wrong class creates couplings that may not be natural within the application's domain, and creates a loss of cohesion in the unwilling host class.
Feature Envy often arises because it must manipulate other objects (usually its arguments) to get them into a useful form, and one force preventing them (the arguments) doing this themselves is that the common knowledge lives outside the arguments, or the arguments are of too basic a type to justify extending that type. Therefore there must be something which 'knows' about the contents or purposes of the arguments. That thing would have to be more than just a basic type, because the basic types are either containers which don't know about their contents, or they are single objects which can't capture their relationship with their fellows of the same type. So, this thing with the extra knowledge should be reified into a class, and the utility method will most likely belong there.
Example
Running Reek on:
class Warehouse
def sale_price(item)
(item.price - item.rebate) * @vat
end
end
would report:
Warehouse#total_price refers to item more than self (FeatureEnvy)
since this:
(item.price - item.rebate)
belongs to the Item class, not the Warehouse.
FrOData::EntitySet#first refers to 'result' more than self (maybe move it to another class?) Open
count == 1 ? result.first : result.to_a
- Read upRead up
- Exclude checks
Feature Envy occurs when a code fragment references another object more often than it references itself, or when several clients do the same series of manipulations on a particular type of object.
Feature Envy reduces the code's ability to communicate intent: code that "belongs" on one class but which is located in another can be hard to find, and may upset the "System of Names" in the host class.
Feature Envy also affects the design's flexibility: A code fragment that is in the wrong class creates couplings that may not be natural within the application's domain, and creates a loss of cohesion in the unwilling host class.
Feature Envy often arises because it must manipulate other objects (usually its arguments) to get them into a useful form, and one force preventing them (the arguments) doing this themselves is that the common knowledge lives outside the arguments, or the arguments are of too basic a type to justify extending that type. Therefore there must be something which 'knows' about the contents or purposes of the arguments. That thing would have to be more than just a basic type, because the basic types are either containers which don't know about their contents, or they are single objects which can't capture their relationship with their fellows of the same type. So, this thing with the extra knowledge should be reified into a class, and the utility method will most likely belong there.
Example
Running Reek on:
class Warehouse
def sale_price(item)
(item.price - item.rebate) * @vat
end
end
would report:
Warehouse#total_price refers to item more than self (FeatureEnvy)
since this:
(item.price - item.rebate)
belongs to the Item class, not the Warehouse.
FrOData::EntitySet has at least 5 instance variables Open
class EntitySet
- Read upRead up
- Exclude checks
Too Many Instance Variables
is a special case of LargeClass
.
Example
Given this configuration
TooManyInstanceVariables:
max_instance_variables: 3
and this code:
class TooManyInstanceVariables
def initialize
@arg_1 = :dummy
@arg_2 = :dummy
@arg_3 = :dummy
@arg_4 = :dummy
end
end
Reek would emit the following warning:
test.rb -- 5 warnings:
[1]:TooManyInstanceVariables has at least 4 instance variables (TooManyInstanceVariables)
FrOData::EntitySet#<< has approx 7 statements Open
def <<(entity)
- Read upRead up
- Exclude checks
A method with Too Many Statements
is any method that has a large number of lines.
Too Many Statements
warns about any method that has more than 5 statements. Reek's smell detector for Too Many Statements
counts +1 for every simple statement in a method and +1 for every statement within a control structure (if
, else
, case
, when
, for
, while
, until
, begin
, rescue
) but it doesn't count the control structure itself.
So the following method would score +6 in Reek's statement-counting algorithm:
def parse(arg, argv, &error)
if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
return nil, block, nil # +1
end
opt = (val = parse_arg(val, &error))[1] # +2
val = conv_arg(*val) # +3
if opt and !arg
argv.shift # +4
else
val[0] = nil # +5
end
val # +6
end
(You might argue that the two assigments within the first @if@ should count as statements, and that perhaps the nested assignment should count as +2.)
FrOData::EntitySet#[] calls 'options[:expand]' 2 times Open
properties_to_expand = if options[:expand] == :all
new_entity.navigation_property_names
else
[ options[:expand] ].compact.flatten
- Read upRead up
- Exclude checks
Duplication occurs when two fragments of code look nearly identical, or when two fragments of code have nearly identical effects at some conceptual level.
Reek implements a check for Duplicate Method Call.
Example
Here's a very much simplified and contrived example. The following method will report a warning:
def double_thing()
@other.thing + @other.thing
end
One quick approach to silence Reek would be to refactor the code thus:
def double_thing()
thing = @other.thing
thing + thing
end
A slightly different approach would be to replace all calls of double_thing
by calls to @other.double_thing
:
class Other
def double_thing()
thing + thing
end
end
The approach you take will depend on balancing other factors in your code.
FrOData::EntitySet#<< calls 'entity.primary_key' 2 times Open
primary_key_node = doc.xpath("//content/properties/#{entity.primary_key}").first
entity[entity.primary_key] = primary_key_node.content unless primary_key_node.nil?
- Read upRead up
- Exclude checks
Duplication occurs when two fragments of code look nearly identical, or when two fragments of code have nearly identical effects at some conceptual level.
Reek implements a check for Duplicate Method Call.
Example
Here's a very much simplified and contrived example. The following method will report a warning:
def double_thing()
@other.thing + @other.thing
end
One quick approach to silence Reek would be to refactor the code thus:
def double_thing()
thing = @other.thing
thing + thing
end
A slightly different approach would be to replace all calls of double_thing
by calls to @other.double_thing
:
class Other
def double_thing()
thing + thing
end
end
The approach you take will depend on balancing other factors in your code.
FrOData::EntitySet#execute_entity_post_request calls 'service.logger' 2 times Open
service.logger.debug <<-EOS
[ODATA: #{service_name}]
An error was encountered committing your entity:
POSTed URL:
- Read upRead up
- Exclude checks
Duplication occurs when two fragments of code look nearly identical, or when two fragments of code have nearly identical effects at some conceptual level.
Reek implements a check for Duplicate Method Call.
Example
Here's a very much simplified and contrived example. The following method will report a warning:
def double_thing()
@other.thing + @other.thing
end
One quick approach to silence Reek would be to refactor the code thus:
def double_thing()
thing = @other.thing
thing + thing
end
A slightly different approach would be to replace all calls of double_thing
by calls to @other.double_thing
:
class Other
def double_thing()
thing + thing
end
end
The approach you take will depend on balancing other factors in your code.
Complex method FrOData::EntitySet#<< (21.5) Open
def <<(entity)
url_chunk, options = setup_entity_post_request(entity)
result = execute_entity_post_request(options, url_chunk)
if entity.is_new?
doc = ::Nokogiri::XML(result.body).remove_namespaces!
- Read upRead up
- Exclude checks
Flog calculates the ABC score for methods. The ABC score is based on assignments, branches (method calls), and conditions.
You can read more about ABC metrics or the flog tool
FrOData::EntitySet#<< performs a nil-check Open
entity[entity.primary_key] = primary_key_node.content unless primary_key_node.nil?
- Read upRead up
- Exclude checks
A NilCheck
is a type check. Failures of NilCheck
violate the "tell, don't ask" principle.
Additionally, type checks often mask bigger problems in your source code like not using OOP and / or polymorphism when you should.
Example
Given
class Klass
def nil_checker(argument)
if argument.nil?
puts "argument isn't nil!"
end
end
end
Reek would emit the following warning:
test.rb -- 1 warning:
[3]:Klass#nil_checker performs a nil-check. (NilCheck)
Method <<
has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. Open
def <<(entity)
url_chunk, options = setup_entity_post_request(entity)
result = execute_entity_post_request(options, url_chunk)
if entity.is_new?
doc = ::Nokogiri::XML(result.body).remove_namespaces!
- 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
Use meaningful heredoc delimiters. Open
EOS
- Read upRead up
- Exclude checks
This cop checks that your heredocs are using meaningful delimiters.
By default it disallows END
and EO*
, and can be configured through
blacklisting additional delimiters.
Example:
# good
<<-SQL
SELECT * FROM foo
SQL
# bad
<<-END
SELECT * FROM foo
END
# bad
<<-EOS
SELECT * FROM foo
EOS
Line is too long. [81/80] Open
# FrOData::Service#[] method call. It also provides Enumerable behavior so that
- Exclude checks
end
at 81, 6 is not aligned with if
at 77, 29. Open
end
- Read upRead up
- Exclude checks
This cop checks whether the end keywords are aligned properly.
Three modes are supported through the EnforcedStyleAlignWith
configuration parameter:
If it's set to keyword
(which is the default), the end
shall be aligned with the start of the keyword (if, class, etc.).
If it's set to variable
the end
shall be aligned with the
left-hand-side of the variable assignment, if there is one.
If it's set to start_of_line
, the end
shall be aligned with the
start of the line where the matching keyword appears.
Example: EnforcedStyleAlignWith: keyword (default)
# bad
variable = if true
end
# good
variable = if true
end
Example: EnforcedStyleAlignWith: variable
# bad
variable = if true
end
# good
variable = if true
end
Example: EnforcedStyleAlignWith: startofline
# bad
variable = if true
end
# good
puts(if true
end)
Use 2 spaces for indentation in a hash, relative to the start of the line where the left curly brace is. Open
'Accept' => 'application/atom+xml',
- Read upRead up
- Exclude checks
This cops checks the indentation of the first key in a hash literal where the opening brace and the first key are on separate lines. The other keys' indentations are handled by the AlignHash cop.
By default, Hash literals that are arguments in a method call with parentheses, and where the opening curly brace of the hash is on the same line as the opening parenthesis of the method call, shall have their first key indented one step (two spaces) more than the position inside the opening parenthesis.
Other hash literals shall have their first key indented one step more than the start of the line where the opening curly brace is.
This default style is called 'specialinsideparentheses'. Alternative styles are 'consistent' and 'align_braces'. Here are examples:
Example: EnforcedStyle: specialinsideparentheses (default)
# The `special_inside_parentheses` style enforces that the first key
# in a hash literal where the opening brace and the first key are on
# separate lines is indented one step (two spaces) more than the
# position inside the opening parentheses.
# bad
hash = {
key: :value
}
and_in_a_method_call({
no: :difference
})
# good
special_inside_parentheses
hash = {
key: :value
}
but_in_a_method_call({
its_like: :this
})
Example: EnforcedStyle: consistent
# The `consistent` style enforces that the first key in a hash
# literal where the opening brace and the first key are on
# seprate lines is indented the same as a hash literal which is not
# defined inside a method call.
# bad
hash = {
key: :value
}
but_in_a_method_call({
its_like: :this
})
# good
hash = {
key: :value
}
and_in_a_method_call({
no: :difference
})
Example: EnforcedStyle: align_braces
# The `align_brackets` style enforces that the opening and closing
# braces are indented to the same position.
# bad
and_now_for_something = {
completely: :different
}
# good
and_now_for_something = {
completely: :different
}
Line is too long. [84/80] Open
# If count is 1 it returns the single entity, otherwise its an array of entities
- Exclude checks
Align else
with if
. Open
else
- Read upRead up
- Exclude checks
This cops checks the alignment of else keywords. Normally they should be aligned with an if/unless/while/until/begin/def keyword, but there are special cases when they should follow the same rules as the alignment of end.
Example:
# bad
if something
code
else
code
end
# bad
if something
code
elsif something
code
end
# good
if something
code
else
code
end
Surrounding space missing in default value assignment. Open
def [](key, options={})
- Read upRead up
- Exclude checks
Checks that the equals signs in parameter default assignments have or don't have surrounding space depending on configuration.
Example:
# bad
def some_method(arg1=:default, arg2=nil, arg3=[])
# do something...
end
# good
def some_method(arg1 = :default, arg2 = nil, arg3 = [])
# do something...
end
Use 2 spaces for indentation in a hash, relative to the start of the line where the left curly brace is. Open
method: :post,
- Read upRead up
- Exclude checks
This cops checks the indentation of the first key in a hash literal where the opening brace and the first key are on separate lines. The other keys' indentations are handled by the AlignHash cop.
By default, Hash literals that are arguments in a method call with parentheses, and where the opening curly brace of the hash is on the same line as the opening parenthesis of the method call, shall have their first key indented one step (two spaces) more than the position inside the opening parenthesis.
Other hash literals shall have their first key indented one step more than the start of the line where the opening curly brace is.
This default style is called 'specialinsideparentheses'. Alternative styles are 'consistent' and 'align_braces'. Here are examples:
Example: EnforcedStyle: specialinsideparentheses (default)
# The `special_inside_parentheses` style enforces that the first key
# in a hash literal where the opening brace and the first key are on
# separate lines is indented one step (two spaces) more than the
# position inside the opening parentheses.
# bad
hash = {
key: :value
}
and_in_a_method_call({
no: :difference
})
# good
special_inside_parentheses
hash = {
key: :value
}
but_in_a_method_call({
its_like: :this
})
Example: EnforcedStyle: consistent
# The `consistent` style enforces that the first key in a hash
# literal where the opening brace and the first key are on
# seprate lines is indented the same as a hash literal which is not
# defined inside a method call.
# bad
hash = {
key: :value
}
but_in_a_method_call({
its_like: :this
})
# good
hash = {
key: :value
}
and_in_a_method_call({
no: :difference
})
Example: EnforcedStyle: align_braces
# The `align_brackets` style enforces that the opening and closing
# braces are indented to the same position.
# bad
and_now_for_something = {
completely: :different
}
# good
and_now_for_something = {
completely: :different
}
Line is too long. [88/80] Open
primary_key_node = doc.xpath("//content/properties/#{entity.primary_key}").first
- Exclude checks
Do not use space inside array brackets. Open
[ options[:expand] ].compact.flatten
- Read upRead up
- Exclude checks
Checks that brackets used for array literals have or don't have surrounding space depending on configuration.
Example: EnforcedStyle: space
# The `space` style enforces that array literals have
# surrounding space.
# bad
array = [a, b, c, d]
# good
array = [ a, b, c, d ]
Example: EnforcedStyle: no_space
# The `no_space` style enforces that array literals have
# no surrounding space.
# bad
array = [ a, b, c, d ]
# good
array = [a, b, c, d]
Example: EnforcedStyle: compact
# The `compact` style normally requires a space inside
# array brackets, with the exception that successive left
# or right brackets are collapsed together in nested arrays.
# bad
array = [ a, [ b, c ] ]
# good
array = [ a, [ b, c ]]
Line is too long. [92/80] Open
service.logger.info "[ODATA: #{service_name}] Unable to commit data to #{url_chunk}"
- Exclude checks
Do not use space inside array brackets. Open
[ options[:expand] ].compact.flatten
- Read upRead up
- Exclude checks
Checks that brackets used for array literals have or don't have surrounding space depending on configuration.
Example: EnforcedStyle: space
# The `space` style enforces that array literals have
# surrounding space.
# bad
array = [a, b, c, d]
# good
array = [ a, b, c, d ]
Example: EnforcedStyle: no_space
# The `no_space` style enforces that array literals have
# no surrounding space.
# bad
array = [ a, b, c, d ]
# good
array = [a, b, c, d]
Example: EnforcedStyle: compact
# The `compact` style normally requires a space inside
# array brackets, with the exception that successive left
# or right brackets are collapsed together in nested arrays.
# bad
array = [ a, [ b, c ] ]
# good
array = [ a, [ b, c ]]
Redundant return
detected. To return multiple values, use an array. Open
return chunk, options
- Read upRead up
- Exclude checks
This cop checks for redundant return
expressions.
Example:
def test
return something
end
def test
one
two
three
return something
end
It should be extended to handle methods whose body is if/else or a case expression with a default branch.
Use 2 (not -21) spaces for indentation. Open
new_entity.navigation_property_names
- Read upRead up
- Exclude checks
This cops checks for indentation that doesn't use the specified number of spaces.
See also the IndentationConsistency cop which is the companion to this one.
Example:
# bad
class A
def test
puts 'hello'
end
end
# good
class A
def test
puts 'hello'
end
end
Example: IgnoredPatterns: ['^\s*module']
# bad
module A
class B
def test
puts 'hello'
end
end
end
# good
module A
class B
def test
puts 'hello'
end
end
end
Line is too long. [90/80] Open
entity[entity.primary_key] = primary_key_node.content unless primary_key_node.nil?
- Exclude checks