class Ameba::Rule::Lint::DuplicateBranch

Overview

Checks that there are no repeated bodies within if/unless, case-when, case-in and rescue constructs.

This is considered invalid:

if foo
  do_foo
  do_something_else
elsif bar
  do_foo
  do_something_else
end

And this is valid:

if foo || bar
  do_foo
  do_something_else
end

With IgnoreLiteralBranches: true, branches are not registered as offenses if they return a basic literal value (string, symbol, integer, float, 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.

With IgnoreDuplicateElseBranch: true, in conditionals with multiple branches, duplicate 'else' branches are not registered as offenses.

YAML configuration example:

Lint/DuplicateBranch:
  Enabled: true
  IgnoreLiteralBranches: false
  IgnoreConstantBranches: false
  IgnoreDuplicateElseBranch: false

Included Modules

Defined in:

ameba/rule/lint/duplicate_branch.cr

Constant Summary

MSG = "Duplicate branch body detected"

Constructors

Class Method Summary

Instance Method Summary

Instance methods inherited from module Ameba::AST::Util

abort?(node) abort?, control_exp_code(node : Crystal::ControlExpression, code_lines) control_exp_code, dynamic_literal?(node) : Bool dynamic_literal?, exit?(node) exit?, flow_command?(node, in_loop) flow_command?, flow_expression?(node, in_loop = false) flow_expression?, has_block?(node) : Bool has_block?, literal?(node) : Bool literal?, loop?(node) loop?, name_end_location(node) name_end_location, name_location(node) name_location, name_location_or(token : Crystal::Token, name, *, adjust_location_column_number = nil)
name_location_or(node : Crystal::ASTNode, *, adjust_location_column_number = nil)
name_location_or
, name_size(node) name_size, node_source(node, code_lines) node_source, nodoc?(node) nodoc?, operator_method?(node) operator_method?, operator_method_name?(name : String) operator_method_name?, path_named?(node, *names : String) : Bool path_named?, raise?(node) raise?, source_between(loc, end_loc, code_lines) : String | Nil source_between, static_literal?(node) : Bool static_literal?

Instance methods inherited from class Ameba::Rule::Base

==(other) ==, catch(source : Source) catch, excluded?(source) excluded?, group group, hash(hasher) hash, name name, special? special?, test(source : Source, node : Crystal::ASTNode, *opts)
test(source : Source)
test

Class methods inherited from class Ameba::Rule::Base

default_severity : Ameba::Severity default_severity

Macros inherited from class Ameba::Rule::Base

issue_for(*args, **kwargs, &block) issue_for

Macros inherited from module Ameba::Config::RuleConfig

properties(&block) properties

Constructor Detail

def self.new(ctx : YAML::ParseContext, node : YAML::Nodes::Node) #

def self.new(config = nil) #

Checks that there are no repeated bodies within if/unless, case-when, case-in and rescue constructs.

This is considered invalid:

if foo
  do_foo
  do_something_else
elsif bar
  do_foo
  do_something_else
end

And this is valid:

if foo || bar
  do_foo
  do_something_else
end

With IgnoreLiteralBranches: true, branches are not registered as offenses if they return a basic literal value (string, symbol, integer, float, 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.

With IgnoreDuplicateElseBranch: true, in conditionals with multiple branches, duplicate 'else' branches are not registered as offenses.

YAML configuration example:

Lint/DuplicateBranch:
  Enabled: true
  IgnoreLiteralBranches: false
  IgnoreConstantBranches: false
  IgnoreDuplicateElseBranch: false

[View source]
def self.new(*, __context_for_yaml_serializable ctx : YAML::ParseContext, __node_for_yaml_serializable node : YAML::Nodes::Node) #

Class Method Detail

def self.parsed_doc : String | Nil #

Returns documentation for this rule, if there is any.

module Ameba
  # This is a test rule.
  # Does nothing.
  class MyRule < Ameba::Rule::Base
    def test(source)
    end
  end
end

MyRule.parsed_doc # => "This is a test rule.\nDoes nothing."

def self.to_json_schema(builder : JSON::Builder) : Nil #

[View source]

Instance Method Detail

def description : String #

def description=(description : String) #

def enabled=(enabled : Bool) #

def enabled? : Bool #

def excluded : Array(String) | Nil #

def excluded=(excluded : Array(String) | Nil) #

def ignore_constant_branches=(ignore_constant_branches : Bool) #

def ignore_constant_branches? : Bool #

def ignore_duplicate_else_branch=(ignore_duplicate_else_branch : Bool) #

def ignore_duplicate_else_branch? : Bool #

def ignore_literal_branches=(ignore_literal_branches : Bool) #

def ignore_literal_branches? : Bool #

def severity : Ameba::Severity #

def severity=(severity : Ameba::Severity) #

def since_version : SemanticVersion | Nil #

[View source]
def since_version=(since_version : String) #

def test(source, node : Crystal::If | Crystal::Unless | Crystal::Case | Crystal::ExceptionHandler, ifs : Enumerable(Crystal::If) | Nil = nil) #

[View source]
def test(source) #

[View source]