daddyz/phonelib

View on GitHub
lib/phonelib/phone_analyzer.rb

Summary

Maintainability
A
1 hr
Test Coverage
A
98%

Module has too many lines. [133/100]
Open

  module PhoneAnalyzer
    # extending with helper methods for analyze
    include Phonelib::PhoneAnalyzerHelper

    # array of types not included for validation check in cycle
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop checks if the length a module exceeds some maximum value. Comment lines can optionally be ignored. The maximum allowed length is configurable.

Assignment Branch Condition size for detect_and_parse is too high. [18.47/15]
Open

    def detect_and_parse(phone, country)
      countries_data = country_code_candidates_for(phone).flat_map { |code|
        Phonelib.data_by_country_codes[code] || []
      }
      countries_data.each_with_object({}) do |data, result|
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

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

Assignment Branch Condition size for convert_to_e164 is too high. [17.49/15]
Open

    def convert_to_e164(phone, data)
      match = phone.match full_regex_for_data(data, Core::VALID_PATTERN, !original_starts_with_plus?)
      case
      when match
        "#{data[Core::COUNTRY_CODE]}#{match.to_a.last}"
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

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. [11/10]
Open

    def detect_and_parse(phone, country)
      countries_data = country_code_candidates_for(phone).flat_map { |code|
        Phonelib.data_by_country_codes[code] || []
      }
      countries_data.each_with_object({}) do |data, result|
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

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.

Cyclomatic complexity for detect_and_parse is too high. [7/6]
Open

    def detect_and_parse(phone, country)
      countries_data = country_code_candidates_for(phone).flat_map { |code|
        Phonelib.data_by_country_codes[code] || []
      }
      countries_data.each_with_object({}) do |data, result|
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

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.

Method has too many lines. [11/10]
Open

    def convert_to_e164(phone, data)
      match = phone.match full_regex_for_data(data, Core::VALID_PATTERN, !original_starts_with_plus?)
      case
      when match
        "#{data[Core::COUNTRY_CODE]}#{match.to_a.last}"
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

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 detect_and_parse has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
Open

    def detect_and_parse(phone, country)
      countries_data = country_code_candidates_for(phone).flat_map { |code|
        Phonelib.data_by_country_codes[code] || []
      }
      countries_data.each_with_object({}) do |data, result|
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb - About 35 mins to fix

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 better_result has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.
Open

    def better_result(base_result, result = nil)
      base_result ||= {}
      return base_result unless result

      return result unless base_result.values.find { |e| e[:possible].any? }
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb - About 25 mins to fix

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 match? instead of match when MatchData is not used.
Open

      when phone.match(cr("^#{data[Core::INTERNATIONAL_PREFIX]}"))
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

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

Line is too long. [98/80]
Open

      return analyze_single_country(phone, countries.first, passed_country) if countries.size == 1
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

Line is too long. [84/80]
Open

      when original_starts_with_plus? && phone.start_with?(data[Core::COUNTRY_CODE])
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

Avoid when branches without a body.
Open

                 when result && result.values.find { |e| e[:valid].any? }
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop checks for the presence of when branches without a body.

Example:

# bad

case foo
when bar then 1
when baz then # nothing
end

Example:

# good

case foo
when bar then 1
when baz then 2
end

Line is too long. [129/80]
Open

        if (!Phonelib.strict_double_prefix_check || key == country) && double_prefix_allowed?(data, phone, parsed && parsed[key])
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

Line is too long. [101/80]
Open

      match = phone.match full_regex_for_data(data, Core::VALID_PATTERN, !original_starts_with_plus?)
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

Indent the first line of the right-hand-side of a multi-line assignment.
Open

            number_valid_and_possible?(phone, possible, valid, not_valid)
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop checks the indentation of the first line of the right-hand-side of a multi-line assignment.

Example:

# bad
value =
if foo
  'bar'
end

# good
value =
  if foo
    'bar'
  end

The indentation of the remaining lines can be corrected with other cops such as IndentationConsistency and EndAlignment.

Line is too long. [105/80]
Open

      ((1..3).map { |length| phone[0, length] } + (1..3).map { |length| stripped_phone[0, length] }).uniq
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

Use !empty? instead of size > 0.
Open

      if match && match.captures.compact.size > 0
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop checks for numeric comparisons that can be replaced by a predicate method, such as receiver.length == 0, receiver.length > 0, receiver.length != 0, receiver.length < 1 and receiver.size == 0 that can be replaced by receiver.empty? and !receiver.empty.

Example:

# bad
[1, 2, 3].length == 0
0 == "foobar".length
array.length < 1
{a: 1, b: 2}.length != 0
string.length > 0
hash.size > 0

# good
[1, 2, 3].empty?
"foobar".empty?
array.empty?
!{a: 1, b: 2}.empty?
!string.empty?
!hash.empty?

Avoid using {...} for multi-line blocks.
Open

      countries_data = country_code_candidates_for(phone).flat_map { |code|
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

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("-")

Missing magic comment # frozen_string_literal: true.
Open

module Phonelib
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop is designed to help upgrade to Ruby 3.0. It will add the comment # frozen_string_literal: true to the top of files to enable frozen string literals. Frozen string literals may be default in Ruby 3.0. The comment will be added below a shebang and encoding comment. The frozen string literal comment is only valid in Ruby 2.3+.

Example: EnforcedStyle: when_needed (default)

# The `when_needed` style will add the frozen string literal comment
# to files only when the `TargetRubyVersion` is set to 2.3+.
# bad
module Foo
  # ...
end

# good
# frozen_string_literal: true

module Foo
  # ...
end

Example: EnforcedStyle: always

# The `always` style will always add the frozen string literal comment
# to a file, regardless of the Ruby version or if `freeze` or `<<` are
# called on a string literal.
# bad
module Bar
  # ...
end

# good
# frozen_string_literal: true

module Bar
  # ...
end

Example: EnforcedStyle: never

# The `never` will enforce that the frozen string literal comment does
# not exist in a file.
# bad
# frozen_string_literal: true

module Baz
  # ...
end

# good
module Baz
  # ...
end

Use final.size.positive? instead of final.size > 0.
Open

        return decorate_analyze_result(final) if final.size > 0
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

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

Do not use empty case condition, instead use an if expression.
Open

      case
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop checks for case statements with an empty condition.

Example:

# bad:
case
when x == 0
  puts 'x is 0'
when y == 0
  puts 'y is 0'
else
  puts 'neither is 0'
end

# good:
if x == 0
  puts 'x is 0'
elsif y == 0
  puts 'y is 0'
else
  puts 'neither is 0'
end

# good: (the case condition node is not empty)
case n
when 0
  puts 'zero'
when 1
  puts 'one'
else
  puts 'more'
end

Use safe navigation (&.) instead of checking if an object exists before calling the method.
Open

                 when result && result.values.find { |e| e[:valid].any? }
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop transforms usages of a method call safeguarded by a non nil check for the variable whose method is being called to safe navigation (&.).

Configuration option: ConvertCodeThatCanStartToReturnNil The default for this is false. When configured to true, this will check for code in the format !foo.nil? && foo.bar. As it is written, the return of this code is limited to false and whatever the return of the method is. If this is converted to safe navigation, foo&.bar can start returning nil as well as what the method returns.

Example:

# bad
foo.bar if foo
foo.bar(param1, param2) if foo
foo.bar { |e| e.something } if foo
foo.bar(param) { |e| e.something } if foo

foo.bar if !foo.nil?
foo.bar unless !foo
foo.bar unless foo.nil?

foo && foo.bar
foo && foo.bar(param1, param2)
foo && foo.bar { |e| e.something }
foo && foo.bar(param) { |e| e.something }

# good
foo&.bar
foo&.bar(param1, param2)
foo&.bar { |e| e.something }
foo&.bar(param) { |e| e.something }

foo.nil? || foo.bar
!foo || foo.bar

# Methods that `nil` will `respond_to?` should not be converted to
# use safe navigation
foo.to_i if foo

Freeze mutable objects assigned to constants.
Open

    NOT_FOR_CHECK = [:general_desc, :fixed_line, :mobile, :fixed_or_mobile]
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop checks whether some constant value isn't a mutable literal (e.g. array or hash).

Example:

# bad
CONST = [1, 2, 3]

# good
CONST = [1, 2, 3].freeze

Use !empty? instead of size > 0.
Open

        return decorate_analyze_result(final) if final.size > 0
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop checks for numeric comparisons that can be replaced by a predicate method, such as receiver.length == 0, receiver.length > 0, receiver.length != 0, receiver.length < 1 and receiver.size == 0 that can be replaced by receiver.empty? and !receiver.empty.

Example:

# bad
[1, 2, 3].length == 0
0 == "foobar".length
array.length < 1
{a: 1, b: 2}.length != 0
string.length > 0
hash.size > 0

# good
[1, 2, 3].empty?
"foobar".empty?
array.empty?
!{a: 1, b: 2}.empty?
!string.empty?
!hash.empty?

Use safe navigation (&.) instead of checking if an object exists before calling the method.
Open

      if match && match.captures.compact.size > 0
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop transforms usages of a method call safeguarded by a non nil check for the variable whose method is being called to safe navigation (&.).

Configuration option: ConvertCodeThatCanStartToReturnNil The default for this is false. When configured to true, this will check for code in the format !foo.nil? && foo.bar. As it is written, the return of this code is limited to false and whatever the return of the method is. If this is converted to safe navigation, foo&.bar can start returning nil as well as what the method returns.

Example:

# bad
foo.bar if foo
foo.bar(param1, param2) if foo
foo.bar { |e| e.something } if foo
foo.bar(param) { |e| e.something } if foo

foo.bar if !foo.nil?
foo.bar unless !foo
foo.bar unless foo.nil?

foo && foo.bar
foo && foo.bar(param1, param2)
foo && foo.bar { |e| e.something }
foo && foo.bar(param) { |e| e.something }

# good
foo&.bar
foo&.bar(param1, param2)
foo&.bar { |e| e.something }
foo&.bar(param) { |e| e.something }

foo.nil? || foo.bar
!foo || foo.bar

# Methods that `nil` will `respond_to?` should not be converted to
# use safe navigation
foo.to_i if foo

Do not use empty case condition, instead use an if expression.
Open

      d_result = case
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop checks for case statements with an empty condition.

Example:

# bad:
case
when x == 0
  puts 'x is 0'
when y == 0
  puts 'y is 0'
else
  puts 'neither is 0'
end

# good:
if x == 0
  puts 'x is 0'
elsif y == 0
  puts 'y is 0'
else
  puts 'neither is 0'
end

# good: (the case condition node is not empty)
case n
when 0
  puts 'zero'
when 1
  puts 'one'
else
  puts 'more'
end

Use %i or %I for an array of symbols.
Open

      [:valid, :possible].each do |key|
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop can check for array literals made up of symbols that are not using the %i() syntax.

Alternatively, it checks for symbol arrays using the %i() syntax on projects which do not want to use that syntax.

Configuration option: MinSize If set, arrays with fewer elements than this value will not trigger the cop. For example, a MinSize of3` will not enforce a style on an array of 2 or fewer elements.

Example: EnforcedStyle: percent (default)

# good
%i[foo bar baz]

# bad
[:foo, :bar, :baz]

Example: EnforcedStyle: brackets

# good
[:foo, :bar, :baz]

# bad
%i[foo bar baz]

Use safe navigation (&.) instead of checking if an object exists before calling the method.
Open

      format_data && format_data.find do |format|
        (format[Core::LEADING_DIGITS].nil? || \
            national.match(cr("^(#{format[Core::LEADING_DIGITS]})"))) && \
          national.match(cr("^(#{format[Core::PATTERN]})$"))
      end || Core::DEFAULT_NUMBER_FORMAT
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop transforms usages of a method call safeguarded by a non nil check for the variable whose method is being called to safe navigation (&.).

Configuration option: ConvertCodeThatCanStartToReturnNil The default for this is false. When configured to true, this will check for code in the format !foo.nil? && foo.bar. As it is written, the return of this code is limited to false and whatever the return of the method is. If this is converted to safe navigation, foo&.bar can start returning nil as well as what the method returns.

Example:

# bad
foo.bar if foo
foo.bar(param1, param2) if foo
foo.bar { |e| e.something } if foo
foo.bar(param) { |e| e.something } if foo

foo.bar if !foo.nil?
foo.bar unless !foo
foo.bar unless foo.nil?

foo && foo.bar
foo && foo.bar(param1, param2)
foo && foo.bar { |e| e.something }
foo && foo.bar(param) { |e| e.something }

# good
foo&.bar
foo&.bar(param1, param2)
foo&.bar { |e| e.something }
foo&.bar(param) { |e| e.something }

foo.nil? || foo.bar
!foo || foo.bar

# Methods that `nil` will `respond_to?` should not be converted to
# use safe navigation
foo.to_i if foo

Use match.captures.compact.size.positive? instead of match.captures.compact.size > 0.
Open

      if match && match.captures.compact.size > 0
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

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

Use %i or %I for an array of symbols.
Open

    NOT_FOR_CHECK = [:general_desc, :fixed_line, :mobile, :fixed_or_mobile]
Severity: Minor
Found in lib/phonelib/phone_analyzer.rb by rubocop

This cop can check for array literals made up of symbols that are not using the %i() syntax.

Alternatively, it checks for symbol arrays using the %i() syntax on projects which do not want to use that syntax.

Configuration option: MinSize If set, arrays with fewer elements than this value will not trigger the cop. For example, a MinSize of3` will not enforce a style on an array of 2 or fewer elements.

Example: EnforcedStyle: percent (default)

# good
%i[foo bar baz]

# bad
[:foo, :bar, :baz]

Example: EnforcedStyle: brackets

# good
[:foo, :bar, :baz]

# bad
%i[foo bar baz]

There are no issues that match your filters.

Category
Status