tuxedo 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +41 -0
- data/README.md +5 -0
- data/Rakefile +30 -0
- data/bin/tuxedo +4 -0
- data/data/sample_cane_output.txt +32 -0
- data/data/sample_reek_output.yml +534 -0
- data/data/sample_reek_output_clean.yml +534 -0
- data/lib/tuxedo.rb +26 -0
- data/lib/tuxedo/cane_parser.rb +64 -0
- data/lib/tuxedo/cane_violation.rb +31 -0
- data/lib/tuxedo/cane_violation/abc_max_violation.rb +37 -0
- data/lib/tuxedo/cane_violation/style_violation.rb +40 -0
- data/lib/tuxedo/cane_violation/syntax_violation.rb +27 -0
- data/lib/tuxedo/cane_violation/threshold_violation.rb +33 -0
- data/lib/tuxedo/cane_violation/undocumented_class_violation.rb +35 -0
- data/lib/tuxedo/cli.rb +18 -0
- data/lib/tuxedo/error.rb +15 -0
- data/lib/tuxedo/formatters/base_formatter.rb +17 -0
- data/lib/tuxedo/formatters/base_text_formatter.rb +13 -0
- data/lib/tuxedo/formatters/cane_text_formatter.rb +68 -0
- data/lib/tuxedo/outputter.rb +16 -0
- data/lib/tuxedo/rake_task.rb +29 -0
- data/lib/tuxedo/reek_parser.rb +54 -0
- data/lib/tuxedo/runner.rb +64 -0
- data/lib/tuxedo/tty.rb +116 -0
- data/lib/tuxedo/version.rb +3 -0
- data/spec/fabricators/cane_output_fabricator.rb +0 -0
- data/spec/helpers/cane_output_helper.rb +42 -0
- data/spec/helpers/reek_output_helper.rb +613 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/tuxedo/cane_parser_spec.rb +63 -0
- data/spec/tuxedo/reek_parser_spec.rb +49 -0
- data/tuxedo.gemspec +32 -0
- metadata +173 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/tasklib'
|
3
|
+
require 'tuxedo'
|
4
|
+
|
5
|
+
module Tuxedo
|
6
|
+
class RakeTask < ::Rake::TaskLib
|
7
|
+
include ::Rake::DSL if defined?(::Rake::DSL)
|
8
|
+
|
9
|
+
attr_accessor :name
|
10
|
+
attr_accessor :fail_on_error
|
11
|
+
attr_accessor :cane_opts
|
12
|
+
|
13
|
+
def initialize(*args)
|
14
|
+
@name = args.shift || :style
|
15
|
+
@cane_opts = ["--style-glob", "**/*.rb"]
|
16
|
+
@fail_on_error = true
|
17
|
+
|
18
|
+
yield self if block_given?
|
19
|
+
|
20
|
+
unless ::Rake.application.last_comment
|
21
|
+
desc %(Check code quality metrics with Tuxedo)
|
22
|
+
end
|
23
|
+
|
24
|
+
task name do
|
25
|
+
Tuxedo.output_to_console
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Tuxedo
|
2
|
+
class ReekParser
|
3
|
+
attr_accessor :result
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
self.result = { }
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse_reek(reek_output)
|
10
|
+
reek_hash = YAML::load(clean_reek(reek_output))
|
11
|
+
unless reek_hash
|
12
|
+
puts "No reek errors found."
|
13
|
+
return self
|
14
|
+
end
|
15
|
+
|
16
|
+
reek_hash.each do |hash|
|
17
|
+
error = process_hash(hash)
|
18
|
+
push_error(error)
|
19
|
+
end
|
20
|
+
|
21
|
+
return self
|
22
|
+
end
|
23
|
+
|
24
|
+
def clean_reek(reek_output)
|
25
|
+
reek_output.gsub("- !ruby/object:Reek::SmellWarning","- smell_warning:")
|
26
|
+
end
|
27
|
+
|
28
|
+
def push_error(error)
|
29
|
+
if self.result[ error.name.to_sym ]
|
30
|
+
self.result[ error.name.to_sym ] << error
|
31
|
+
else
|
32
|
+
self.result[ error.name.to_sym ] = [ error ]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def process_hash(hash)
|
37
|
+
Tuxedo::Error.new( :name => get_error(hash),
|
38
|
+
:source => get_file(hash),
|
39
|
+
:line => get_lines(hash))
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_error(hash)
|
43
|
+
hash["smell"]["subclass"]
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_file(hash)
|
47
|
+
hash["location"]["source"]
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_lines(hash)
|
51
|
+
hash["location"]["lines"]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'cane'
|
2
|
+
require 'cane/cli'
|
3
|
+
|
4
|
+
require 'tuxedo/tty'
|
5
|
+
require 'tuxedo/cli'
|
6
|
+
require 'tuxedo/cane_violation'
|
7
|
+
|
8
|
+
module Tuxedo
|
9
|
+
module Runner
|
10
|
+
class << self
|
11
|
+
def run_cane(cane_opts=nil)
|
12
|
+
cane_opts ||= "--style-glob **/*.rb".split
|
13
|
+
opts = Cane::CLI::Spec.new.parse(cane_opts)
|
14
|
+
runner = Cane::Runner.new(opts)
|
15
|
+
def runner.outputter;
|
16
|
+
@outputter ||= StringIO.new
|
17
|
+
end
|
18
|
+
runner.run
|
19
|
+
violations = runner.send(:violations)
|
20
|
+
violations.map { |v| CaneViolation.from_cane(v)}
|
21
|
+
end
|
22
|
+
|
23
|
+
def run_reek
|
24
|
+
reek_result = Cli.sh("reek -qy .")
|
25
|
+
|
26
|
+
if reek_failed?(reek_result)
|
27
|
+
if need_mvz_reek?(reek_result.stderr)
|
28
|
+
print_use_mvz_reek
|
29
|
+
else
|
30
|
+
print_reek_failed
|
31
|
+
puts reek_result.stderr
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
reek_result.stdout
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def reek_failed?(result)
|
41
|
+
!result.stderr.empty?
|
42
|
+
end
|
43
|
+
|
44
|
+
def need_mvz_reek?(stderr)
|
45
|
+
RUBY_VERSION >= '1.9.2' &&
|
46
|
+
stderr.index("Error: undefined method `sexp_type'")
|
47
|
+
end
|
48
|
+
|
49
|
+
def print_use_mvz_reek
|
50
|
+
puts <<-MSG
|
51
|
+
Oh snap! Reek has a problem on 1.9.3.
|
52
|
+
Try putting this in your gemfile instead:
|
53
|
+
|
54
|
+
gem 'reek', :git => "git://github.com/mvz/reek.git", :branch => "ripper_ruby_parser-2"
|
55
|
+
|
56
|
+
MSG
|
57
|
+
end
|
58
|
+
|
59
|
+
def print_reek_failed
|
60
|
+
puts "Oh snap! Reek ran into a problem:"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/tuxedo/tty.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
module Tuxedo
|
2
|
+
module Tty extend self
|
3
|
+
class << self
|
4
|
+
def color_enabled?
|
5
|
+
@color_enabled
|
6
|
+
end
|
7
|
+
|
8
|
+
# Generates color methods.
|
9
|
+
#
|
10
|
+
# Fore each generated method:
|
11
|
+
# When called without an argument:
|
12
|
+
# Returns the terminal escape code.
|
13
|
+
# When called with an argument:
|
14
|
+
# Returns the argument#to_s, wrapped in both
|
15
|
+
# the color escape code and reset escape code.
|
16
|
+
#
|
17
|
+
# Examples:
|
18
|
+
# red #=> "\e[31m"
|
19
|
+
# red("Blah") #=> "\e[31mBlah\e[0m"
|
20
|
+
def def_color(name, code)
|
21
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
22
|
+
def #{name}(text=(default_arg=true;nil))
|
23
|
+
if Tty.color_enabled?
|
24
|
+
if default_arg
|
25
|
+
"#{escape(code)}"
|
26
|
+
else
|
27
|
+
"#{escape(code)}\#{text}#{escape(0)}"
|
28
|
+
end
|
29
|
+
else
|
30
|
+
text.to_s
|
31
|
+
end
|
32
|
+
end
|
33
|
+
CODE
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def color_enabled=(true_or_false)
|
39
|
+
@color_enabled = true_or_false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
self.color_enabled = true
|
44
|
+
|
45
|
+
def escape(code)
|
46
|
+
"\033[#{code}m" if Tty.color_enabled?
|
47
|
+
end
|
48
|
+
|
49
|
+
def_color :reset, 0
|
50
|
+
def_color :bold, 1
|
51
|
+
def_color :invert, 3
|
52
|
+
def_color :underline, 4
|
53
|
+
def_color :black, 30
|
54
|
+
def_color :red, 31
|
55
|
+
def_color :green, 32
|
56
|
+
def_color :yellow, 33
|
57
|
+
def_color :blue, 34
|
58
|
+
def_color :magenta, 35
|
59
|
+
def_color :cyan, 36
|
60
|
+
def_color :white, 37
|
61
|
+
|
62
|
+
def with_color(true_or_false=true)
|
63
|
+
old_color_enabled = Tty.color_enabled?
|
64
|
+
Tty.send(:color_enabled=, true_or_false)
|
65
|
+
yield
|
66
|
+
ensure
|
67
|
+
Tty.send(:color_enabled=, old_color_enabled)
|
68
|
+
end
|
69
|
+
|
70
|
+
def capture_stdout
|
71
|
+
out = StringIO.new
|
72
|
+
$stdout = out
|
73
|
+
yield
|
74
|
+
return out
|
75
|
+
ensure
|
76
|
+
$stdout = STDOUT
|
77
|
+
end
|
78
|
+
|
79
|
+
def capture_stderr
|
80
|
+
out = StringIO.new
|
81
|
+
$stderr = out
|
82
|
+
yield
|
83
|
+
return out
|
84
|
+
ensure
|
85
|
+
$stderr = STDERR
|
86
|
+
end
|
87
|
+
|
88
|
+
def terminal_size_available?
|
89
|
+
!!terminal_size
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns [width, height] of terminal when detected, nil if not detected.
|
93
|
+
# Think of this as a simpler version of Highline's Highline::SystemExtensions.terminal_size()
|
94
|
+
# https://github.com/cldwalker/hirb/blob/0df53628bd07845feed43030477b65106e75c7dd/lib/hirb/util.rb#L55-73
|
95
|
+
def terminal_size
|
96
|
+
if (ENV['COLUMNS'] =~ /^\d+$/) && (ENV['LINES'] =~ /^\d+$/)
|
97
|
+
[ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
|
98
|
+
elsif (RUBY_PLATFORM =~ /java/ || (!STDIN.tty? && ENV['TERM'])) && command_exists?('tput')
|
99
|
+
[`tput cols`.to_i, `tput lines`.to_i]
|
100
|
+
elsif STDIN.tty? && command_exists?('stty')
|
101
|
+
`stty size`.scan(/\d+/).map { |s| s.to_i }.reverse
|
102
|
+
else
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
rescue
|
106
|
+
nil
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
# Determines if a shell command exists by searching for it in ENV['PATH'].
|
112
|
+
def command_exists?(command)
|
113
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).any? {|d| File.exists? File.join(d, command) }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
File without changes
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Tuxedo
|
2
|
+
def generate_cane_output
|
3
|
+
"Methods exceeded maximum allowed ABC complexity (1):
|
4
|
+
|
5
|
+
app/controllers/orders_controller.rb OrdersController > create 23
|
6
|
+
|
7
|
+
Lines violated style requirements (2):
|
8
|
+
|
9
|
+
app/controllers/carts_controller.rb:4 Line contains trailing whitespaces
|
10
|
+
app/controllers/products_controller.rb:47 Line is >80 characters (89)"
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate_full_cane_output
|
14
|
+
"Lines violated style requirements (16):
|
15
|
+
|
16
|
+
app/controllers/carts_controller.rb:4 Line contains trailing whitespaces
|
17
|
+
app/controllers/products_controller.rb:47 Line is >80 characters (89)
|
18
|
+
app/controllers/products_controller.rb:48 Line is >80 characters (83)
|
19
|
+
app/controllers/products_controller.rb:51 Line is >80 characters (83)
|
20
|
+
app/controllers/products_controller.rb:63 Line is >80 characters (89)
|
21
|
+
app/controllers/products_controller.rb:67 Line is >80 characters (83)
|
22
|
+
spec/acceptance/public_user_views_products_spec.rb:9 Line contains trailing whitespaces
|
23
|
+
spec/controllers/products_controller_spec.rb:29 Line contains trailing whitespaces
|
24
|
+
spec/controllers/products_controller_spec.rb:113 Line is >80 characters (91)
|
25
|
+
spec/controllers/products_controller_spec.rb:114 Line is >80 characters (96)
|
26
|
+
spec/controllers/products_controller_spec.rb:119 Line is >80 characters (91)
|
27
|
+
spec/controllers/products_controller_spec.rb:125 Line is >80 characters (91)
|
28
|
+
spec/requests/products_spec.rb:6 Line is >80 characters (97)
|
29
|
+
spec/spec_helper.rb:12 Line contains trailing whitespaces
|
30
|
+
spec/support/example_data/products.rb:13 Line is >80 characters (126)
|
31
|
+
spec/support/example_data/projects.rb:12 Line is >80 characters (128)
|
32
|
+
|
33
|
+
Classes are not documented (6):
|
34
|
+
|
35
|
+
app/controllers/application_controller.rb:1 ApplicationController
|
36
|
+
app/controllers/carts_controller.rb:1 CartsController
|
37
|
+
app/controllers/products_controller.rb:1 ProductsController
|
38
|
+
app/models/cart.rb:1 Cart
|
39
|
+
app/models/cart_item.rb:1 CartItem
|
40
|
+
app/models/product.rb:1 Product"
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,613 @@
|
|
1
|
+
module Tuxedo
|
2
|
+
def generate_reek_output
|
3
|
+
"---
|
4
|
+
- !ruby/object:Reek::SmellWarning
|
5
|
+
smell:
|
6
|
+
class: IrresponsibleModule
|
7
|
+
subclass: IrresponsibleModule
|
8
|
+
message: has no descriptive comment
|
9
|
+
module_name: AddressesController
|
10
|
+
status:
|
11
|
+
is_active: true
|
12
|
+
location:
|
13
|
+
context: AddressesController
|
14
|
+
lines:
|
15
|
+
- 1
|
16
|
+
source: ./app/controllers/addresses_controller.rb
|
17
|
+
- !ruby/object:Reek::SmellWarning
|
18
|
+
smell:
|
19
|
+
class: Duplication
|
20
|
+
subclass: DuplicateMethodCall
|
21
|
+
message: calls address.id twice
|
22
|
+
call: address.id
|
23
|
+
occurrences: 2
|
24
|
+
status:
|
25
|
+
is_active: true
|
26
|
+
location:
|
27
|
+
context: AddressesController#create
|
28
|
+
lines:
|
29
|
+
- 8
|
30
|
+
- 10
|
31
|
+
source: ./app/controllers/addresses_controller.rb
|
32
|
+
- !ruby/object:Reek::SmellWarning
|
33
|
+
smell:
|
34
|
+
class: LongMethod
|
35
|
+
subclass: TooManyStatements
|
36
|
+
message: has approx 6 statements
|
37
|
+
statement_count: 6
|
38
|
+
status:
|
39
|
+
is_active: true
|
40
|
+
location:
|
41
|
+
context: AddressesController#create
|
42
|
+
lines:
|
43
|
+
- 2
|
44
|
+
source: ./app/controllers/addresses_controller.rb
|
45
|
+
- !ruby/object:Reek::SmellWarning
|
46
|
+
smell:
|
47
|
+
class: UncommunicativeName
|
48
|
+
subclass: UncommunicativeVariableName
|
49
|
+
message: has the variable name 'c'
|
50
|
+
variable_name: c
|
51
|
+
status:
|
52
|
+
is_active: true
|
53
|
+
location:
|
54
|
+
context: ApplicationController#find_or_create_cart
|
55
|
+
lines:
|
56
|
+
- 34
|
57
|
+
source: ./app/controllers/application_controller.rb
|
58
|
+
- !ruby/object:Reek::SmellWarning
|
59
|
+
smell:
|
60
|
+
class: Duplication
|
61
|
+
subclass: DuplicateMethodCall
|
62
|
+
message: calls session twice
|
63
|
+
call: session
|
64
|
+
occurrences: 2
|
65
|
+
status:
|
66
|
+
is_active: true
|
67
|
+
location:
|
68
|
+
context: ApplicationController#mobile_device?
|
69
|
+
lines:
|
70
|
+
- 10
|
71
|
+
- 11
|
72
|
+
source: ./app/controllers/application_controller.rb
|
73
|
+
"
|
74
|
+
end
|
75
|
+
|
76
|
+
def generate_full_reek_output
|
77
|
+
"---
|
78
|
+
- !ruby/object:Reek::SmellWarning
|
79
|
+
smell:
|
80
|
+
class: IrresponsibleModule
|
81
|
+
subclass: IrresponsibleModule
|
82
|
+
message: has no descriptive comment
|
83
|
+
module_name: Customer
|
84
|
+
status:
|
85
|
+
is_active: true
|
86
|
+
location:
|
87
|
+
context: SalesEngine::Customer
|
88
|
+
lines:
|
89
|
+
- 2
|
90
|
+
source: ./lib/sales_engine/customer.rb
|
91
|
+
- !ruby/object:Reek::SmellWarning
|
92
|
+
smell:
|
93
|
+
class: Duplication
|
94
|
+
subclass: DuplicateMethodCall
|
95
|
+
message: calls invoice.merchant 3 times
|
96
|
+
call: invoice.merchant
|
97
|
+
occurrences: 3
|
98
|
+
status:
|
99
|
+
is_active: true
|
100
|
+
location:
|
101
|
+
context: SalesEngine::Customer#favorite_merchant
|
102
|
+
lines:
|
103
|
+
- 26
|
104
|
+
- 27
|
105
|
+
- 29
|
106
|
+
source: ./lib/sales_engine/customer.rb
|
107
|
+
- !ruby/object:Reek::SmellWarning
|
108
|
+
smell:
|
109
|
+
class: LowCohesion
|
110
|
+
subclass: FeatureEnvy
|
111
|
+
message: refers to merchant_invoice_counter more than self
|
112
|
+
receiver: merchant_invoice_counter
|
113
|
+
references: 4
|
114
|
+
status:
|
115
|
+
is_active: true
|
116
|
+
location:
|
117
|
+
context: SalesEngine::Customer#favorite_merchant
|
118
|
+
lines:
|
119
|
+
- 23
|
120
|
+
source: ./lib/sales_engine/customer.rb
|
121
|
+
- !ruby/object:Reek::SmellWarning
|
122
|
+
smell:
|
123
|
+
class: NestedIterators
|
124
|
+
subclass: NestedIterators
|
125
|
+
message: contains iterators nested 2 deep
|
126
|
+
depth: 2
|
127
|
+
status:
|
128
|
+
is_active: true
|
129
|
+
location:
|
130
|
+
context: SalesEngine::Customer#transactions
|
131
|
+
lines:
|
132
|
+
- 18
|
133
|
+
source: ./lib/sales_engine/customer.rb
|
134
|
+
- !ruby/object:Reek::SmellWarning
|
135
|
+
smell:
|
136
|
+
class: LowCohesion
|
137
|
+
subclass: FeatureEnvy
|
138
|
+
message: refers to customer_transactions more than self
|
139
|
+
receiver: customer_transactions
|
140
|
+
references: 2
|
141
|
+
status:
|
142
|
+
is_active: true
|
143
|
+
location:
|
144
|
+
context: SalesEngine::Customer#transactions
|
145
|
+
lines:
|
146
|
+
- 15
|
147
|
+
source: ./lib/sales_engine/customer.rb
|
148
|
+
- !ruby/object:Reek::SmellWarning
|
149
|
+
smell:
|
150
|
+
class: LargeClass
|
151
|
+
subclass: TooManyMethods
|
152
|
+
message: has at least 26 methods
|
153
|
+
method_count: 26
|
154
|
+
status:
|
155
|
+
is_active: true
|
156
|
+
location:
|
157
|
+
context: SalesEngine::Database
|
158
|
+
lines:
|
159
|
+
- 2
|
160
|
+
source: ./lib/sales_engine/database.rb
|
161
|
+
- !ruby/object:Reek::SmellWarning
|
162
|
+
smell:
|
163
|
+
class: IrresponsibleModule
|
164
|
+
subclass: IrresponsibleModule
|
165
|
+
message: has no descriptive comment
|
166
|
+
module_name: Database
|
167
|
+
status:
|
168
|
+
is_active: true
|
169
|
+
location:
|
170
|
+
context: SalesEngine::Database
|
171
|
+
lines:
|
172
|
+
- 2
|
173
|
+
source: ./lib/sales_engine/database.rb
|
174
|
+
- !ruby/object:Reek::SmellWarning
|
175
|
+
smell:
|
176
|
+
class: LowCohesion
|
177
|
+
subclass: FeatureEnvy
|
178
|
+
message: refers to attribute_value more than self
|
179
|
+
receiver: attribute_value
|
180
|
+
references: 3
|
181
|
+
status:
|
182
|
+
is_active: true
|
183
|
+
location:
|
184
|
+
context: SalesEngine::Database#find_all_by
|
185
|
+
lines:
|
186
|
+
- 121
|
187
|
+
source: ./lib/sales_engine/database.rb
|
188
|
+
- !ruby/object:Reek::SmellWarning
|
189
|
+
smell:
|
190
|
+
class: Duplication
|
191
|
+
subclass: DuplicateMethodCall
|
192
|
+
message: calls Time.parse(record.created_at) twice
|
193
|
+
call: Time.parse(record.created_at)
|
194
|
+
occurrences: 2
|
195
|
+
status:
|
196
|
+
is_active: true
|
197
|
+
location:
|
198
|
+
context: SalesEngine::Database#find_all_created_on
|
199
|
+
lines:
|
200
|
+
- 155
|
201
|
+
- 156
|
202
|
+
source: ./lib/sales_engine/database.rb
|
203
|
+
- !ruby/object:Reek::SmellWarning
|
204
|
+
smell:
|
205
|
+
class: Duplication
|
206
|
+
subclass: DuplicateMethodCall
|
207
|
+
message: calls record.created_at twice
|
208
|
+
call: record.created_at
|
209
|
+
occurrences: 2
|
210
|
+
status:
|
211
|
+
is_active: true
|
212
|
+
location:
|
213
|
+
context: SalesEngine::Database#find_all_created_on
|
214
|
+
lines:
|
215
|
+
- 155
|
216
|
+
- 156
|
217
|
+
source: ./lib/sales_engine/database.rb
|
218
|
+
- !ruby/object:Reek::SmellWarning
|
219
|
+
smell:
|
220
|
+
class: Duplication
|
221
|
+
subclass: DuplicateMethodCall
|
222
|
+
message: calls invoice.merchant_id 3 times
|
223
|
+
call: invoice.merchant_id
|
224
|
+
occurrences: 3
|
225
|
+
status:
|
226
|
+
is_active: true
|
227
|
+
location:
|
228
|
+
context: SalesEngine::Database#find_all_invoices_by_merchant_id
|
229
|
+
lines:
|
230
|
+
- 144
|
231
|
+
- 144
|
232
|
+
- 148
|
233
|
+
source: ./lib/sales_engine/database.rb
|
234
|
+
- !ruby/object:Reek::SmellWarning
|
235
|
+
smell:
|
236
|
+
class: LowCohesion
|
237
|
+
subclass: FeatureEnvy
|
238
|
+
message: refers to invoice more than self
|
239
|
+
receiver: invoice
|
240
|
+
references: 3
|
241
|
+
status:
|
242
|
+
is_active: true
|
243
|
+
location:
|
244
|
+
context: SalesEngine::Database#find_all_invoices_by_merchant_id
|
245
|
+
lines:
|
246
|
+
- 141
|
247
|
+
source: ./lib/sales_engine/database.rb
|
248
|
+
- !ruby/object:Reek::SmellWarning
|
249
|
+
smell:
|
250
|
+
class: Duplication
|
251
|
+
subclass: DuplicateMethodCall
|
252
|
+
message: calls item.merchant_id 3 times
|
253
|
+
call: item.merchant_id
|
254
|
+
occurrences: 3
|
255
|
+
status:
|
256
|
+
is_active: true
|
257
|
+
location:
|
258
|
+
context: SalesEngine::Database#find_all_items_by_merchant_id
|
259
|
+
lines:
|
260
|
+
- 134
|
261
|
+
- 134
|
262
|
+
- 138
|
263
|
+
source: ./lib/sales_engine/database.rb
|
264
|
+
- !ruby/object:Reek::SmellWarning
|
265
|
+
smell:
|
266
|
+
class: LowCohesion
|
267
|
+
subclass: FeatureEnvy
|
268
|
+
message: refers to item more than self
|
269
|
+
receiver: item
|
270
|
+
references: 3
|
271
|
+
status:
|
272
|
+
is_active: true
|
273
|
+
location:
|
274
|
+
context: SalesEngine::Database#find_all_items_by_merchant_id
|
275
|
+
lines:
|
276
|
+
- 131
|
277
|
+
source: ./lib/sales_engine/database.rb
|
278
|
+
- !ruby/object:Reek::SmellWarning
|
279
|
+
smell:
|
280
|
+
class: LowCohesion
|
281
|
+
subclass: FeatureEnvy
|
282
|
+
message: refers to attribute_value more than self
|
283
|
+
receiver: attribute_value
|
284
|
+
references: 3
|
285
|
+
status:
|
286
|
+
is_active: true
|
287
|
+
location:
|
288
|
+
context: SalesEngine::Database#find_by
|
289
|
+
lines:
|
290
|
+
- 111
|
291
|
+
source: ./lib/sales_engine/database.rb
|
292
|
+
- !ruby/object:Reek::SmellWarning
|
293
|
+
smell:
|
294
|
+
class: Duplication
|
295
|
+
subclass: DuplicateMethodCall
|
296
|
+
message: calls self.send(class_name) twice
|
297
|
+
call: self.send(class_name)
|
298
|
+
occurrences: 2
|
299
|
+
status:
|
300
|
+
is_active: true
|
301
|
+
location:
|
302
|
+
context: SalesEngine::Database#get_random_record
|
303
|
+
lines:
|
304
|
+
- 55
|
305
|
+
- 55
|
306
|
+
source: ./lib/sales_engine/database.rb
|
307
|
+
- !ruby/object:Reek::SmellWarning
|
308
|
+
smell:
|
309
|
+
class: IrresponsibleModule
|
310
|
+
subclass: IrresponsibleModule
|
311
|
+
message: has no descriptive comment
|
312
|
+
module_name: Invoice
|
313
|
+
status:
|
314
|
+
is_active: true
|
315
|
+
location:
|
316
|
+
context: SalesEngine::Invoice
|
317
|
+
lines:
|
318
|
+
- 2
|
319
|
+
source: ./lib/sales_engine/invoice.rb
|
320
|
+
- !ruby/object:Reek::SmellWarning
|
321
|
+
smell:
|
322
|
+
class: LowCohesion
|
323
|
+
subclass: FeatureEnvy
|
324
|
+
message: refers to values more than self
|
325
|
+
receiver: values
|
326
|
+
references: 3
|
327
|
+
status:
|
328
|
+
is_active: true
|
329
|
+
location:
|
330
|
+
context: SalesEngine::Invoice#charge
|
331
|
+
lines:
|
332
|
+
- 37
|
333
|
+
source: ./lib/sales_engine/invoice.rb
|
334
|
+
- !ruby/object:Reek::SmellWarning
|
335
|
+
smell:
|
336
|
+
class: Duplication
|
337
|
+
subclass: DuplicateMethodCall
|
338
|
+
message: calls values[:transaction] twice
|
339
|
+
call: values[:transaction]
|
340
|
+
occurrences: 2
|
341
|
+
status:
|
342
|
+
is_active: true
|
343
|
+
location:
|
344
|
+
context: SalesEngine::Invoice#self.create
|
345
|
+
lines:
|
346
|
+
- 32
|
347
|
+
- 32
|
348
|
+
source: ./lib/sales_engine/invoice.rb
|
349
|
+
- !ruby/object:Reek::SmellWarning
|
350
|
+
smell:
|
351
|
+
class: IrresponsibleModule
|
352
|
+
subclass: IrresponsibleModule
|
353
|
+
message: has no descriptive comment
|
354
|
+
module_name: InvoiceItem
|
355
|
+
status:
|
356
|
+
is_active: true
|
357
|
+
location:
|
358
|
+
context: SalesEngine::InvoiceItem
|
359
|
+
lines:
|
360
|
+
- 2
|
361
|
+
source: ./lib/sales_engine/invoice_item.rb
|
362
|
+
- !ruby/object:Reek::SmellWarning
|
363
|
+
smell:
|
364
|
+
class: IrresponsibleModule
|
365
|
+
subclass: IrresponsibleModule
|
366
|
+
message: has no descriptive comment
|
367
|
+
module_name: Item
|
368
|
+
status:
|
369
|
+
is_active: true
|
370
|
+
location:
|
371
|
+
context: SalesEngine::Item
|
372
|
+
lines:
|
373
|
+
- 2
|
374
|
+
source: ./lib/sales_engine/item.rb
|
375
|
+
- !ruby/object:Reek::SmellWarning
|
376
|
+
smell:
|
377
|
+
class: Duplication
|
378
|
+
subclass: DuplicateMethodCall
|
379
|
+
message: calls inv_item.quantity twice
|
380
|
+
call: inv_item.quantity
|
381
|
+
occurrences: 2
|
382
|
+
status:
|
383
|
+
is_active: true
|
384
|
+
location:
|
385
|
+
context: SalesEngine::Item#add_quantity_to_date
|
386
|
+
lines:
|
387
|
+
- 41
|
388
|
+
- 43
|
389
|
+
source: ./lib/sales_engine/item.rb
|
390
|
+
- !ruby/object:Reek::SmellWarning
|
391
|
+
smell:
|
392
|
+
class: LowCohesion
|
393
|
+
subclass: UtilityFunction
|
394
|
+
message: doesn't depend on instance state
|
395
|
+
status:
|
396
|
+
is_active: true
|
397
|
+
location:
|
398
|
+
context: SalesEngine::Item#add_quantity_to_date
|
399
|
+
lines:
|
400
|
+
- 37
|
401
|
+
source: ./lib/sales_engine/item.rb
|
402
|
+
- !ruby/object:Reek::SmellWarning
|
403
|
+
smell:
|
404
|
+
class: LowCohesion
|
405
|
+
subclass: FeatureEnvy
|
406
|
+
message: refers to inv_item more than self
|
407
|
+
receiver: inv_item
|
408
|
+
references: 3
|
409
|
+
status:
|
410
|
+
is_active: true
|
411
|
+
location:
|
412
|
+
context: SalesEngine::Item#add_quantity_to_date
|
413
|
+
lines:
|
414
|
+
- 37
|
415
|
+
source: ./lib/sales_engine/item.rb
|
416
|
+
- !ruby/object:Reek::SmellWarning
|
417
|
+
smell:
|
418
|
+
class: LowCohesion
|
419
|
+
subclass: FeatureEnvy
|
420
|
+
message: refers to tracker_hash more than self
|
421
|
+
receiver: tracker_hash
|
422
|
+
references: 3
|
423
|
+
status:
|
424
|
+
is_active: true
|
425
|
+
location:
|
426
|
+
context: SalesEngine::Item#add_quantity_to_date
|
427
|
+
lines:
|
428
|
+
- 37
|
429
|
+
source: ./lib/sales_engine/item.rb
|
430
|
+
- !ruby/object:Reek::SmellWarning
|
431
|
+
smell:
|
432
|
+
class: IrresponsibleModule
|
433
|
+
subclass: IrresponsibleModule
|
434
|
+
message: has no descriptive comment
|
435
|
+
module_name: Merchant
|
436
|
+
status:
|
437
|
+
is_active: true
|
438
|
+
location:
|
439
|
+
context: SalesEngine::Merchant
|
440
|
+
lines:
|
441
|
+
- 2
|
442
|
+
source: ./lib/sales_engine/merchant.rb
|
443
|
+
- !ruby/object:Reek::SmellWarning
|
444
|
+
smell:
|
445
|
+
class: LowCohesion
|
446
|
+
subclass: FeatureEnvy
|
447
|
+
message: refers to invoice more than self
|
448
|
+
receiver: invoice
|
449
|
+
references: 2
|
450
|
+
status:
|
451
|
+
is_active: true
|
452
|
+
location:
|
453
|
+
context: SalesEngine::Merchant#customers_with_pending_invoices
|
454
|
+
lines:
|
455
|
+
- 56
|
456
|
+
source: ./lib/sales_engine/merchant.rb
|
457
|
+
- !ruby/object:Reek::SmellWarning
|
458
|
+
smell:
|
459
|
+
class: Duplication
|
460
|
+
subclass: DuplicateMethodCall
|
461
|
+
message: calls invoice.customer 3 times
|
462
|
+
call: invoice.customer
|
463
|
+
occurrences: 3
|
464
|
+
status:
|
465
|
+
is_active: true
|
466
|
+
location:
|
467
|
+
context: SalesEngine::Merchant#favorite_customer
|
468
|
+
lines:
|
469
|
+
- 47
|
470
|
+
- 48
|
471
|
+
- 50
|
472
|
+
source: ./lib/sales_engine/merchant.rb
|
473
|
+
- !ruby/object:Reek::SmellWarning
|
474
|
+
smell:
|
475
|
+
class: LowCohesion
|
476
|
+
subclass: FeatureEnvy
|
477
|
+
message: refers to customer_invoice_counter more than self
|
478
|
+
receiver: customer_invoice_counter
|
479
|
+
references: 4
|
480
|
+
status:
|
481
|
+
is_active: true
|
482
|
+
location:
|
483
|
+
context: SalesEngine::Merchant#favorite_customer
|
484
|
+
lines:
|
485
|
+
- 44
|
486
|
+
source: ./lib/sales_engine/merchant.rb
|
487
|
+
- !ruby/object:Reek::SmellWarning
|
488
|
+
smell:
|
489
|
+
class: Duplication
|
490
|
+
subclass: DuplicateMethodCall
|
491
|
+
message: calls invoice.total_revenue twice
|
492
|
+
call: invoice.total_revenue
|
493
|
+
occurrences: 2
|
494
|
+
status:
|
495
|
+
is_active: true
|
496
|
+
location:
|
497
|
+
context: SalesEngine::Merchant#revenue
|
498
|
+
lines:
|
499
|
+
- 32
|
500
|
+
- 36
|
501
|
+
source: ./lib/sales_engine/merchant.rb
|
502
|
+
- !ruby/object:Reek::SmellWarning
|
503
|
+
smell:
|
504
|
+
class: LowCohesion
|
505
|
+
subclass: FeatureEnvy
|
506
|
+
message: refers to invoice more than self
|
507
|
+
receiver: invoice
|
508
|
+
references: 3
|
509
|
+
status:
|
510
|
+
is_active: true
|
511
|
+
location:
|
512
|
+
context: SalesEngine::Merchant#revenue
|
513
|
+
lines:
|
514
|
+
- 29
|
515
|
+
source: ./lib/sales_engine/merchant.rb
|
516
|
+
- !ruby/object:Reek::SmellWarning
|
517
|
+
smell:
|
518
|
+
class: IrresponsibleModule
|
519
|
+
subclass: IrresponsibleModule
|
520
|
+
message: has no descriptive comment
|
521
|
+
module_name: Record
|
522
|
+
status:
|
523
|
+
is_active: true
|
524
|
+
location:
|
525
|
+
context: SalesEngine::Record
|
526
|
+
lines:
|
527
|
+
- 2
|
528
|
+
source: ./lib/sales_engine/record.rb
|
529
|
+
- !ruby/object:Reek::SmellWarning
|
530
|
+
smell:
|
531
|
+
class: LowCohesion
|
532
|
+
subclass: UtilityFunction
|
533
|
+
message: doesn't depend on instance state
|
534
|
+
status:
|
535
|
+
is_active: true
|
536
|
+
location:
|
537
|
+
context: SalesEngine::Record#convert_to_big_decimal
|
538
|
+
lines:
|
539
|
+
- 11
|
540
|
+
source: ./lib/sales_engine/record.rb
|
541
|
+
- !ruby/object:Reek::SmellWarning
|
542
|
+
smell:
|
543
|
+
class: LowCohesion
|
544
|
+
subclass: FeatureEnvy
|
545
|
+
message: refers to value more than self
|
546
|
+
receiver: value
|
547
|
+
references: 3
|
548
|
+
status:
|
549
|
+
is_active: true
|
550
|
+
location:
|
551
|
+
context: SalesEngine::Record#convert_to_big_decimal
|
552
|
+
lines:
|
553
|
+
- 11
|
554
|
+
source: ./lib/sales_engine/record.rb
|
555
|
+
- !ruby/object:Reek::SmellWarning
|
556
|
+
smell:
|
557
|
+
class: Duplication
|
558
|
+
subclass: DuplicateMethodCall
|
559
|
+
message: calls Time.now twice
|
560
|
+
call: Time.now
|
561
|
+
occurrences: 2
|
562
|
+
status:
|
563
|
+
is_active: true
|
564
|
+
location:
|
565
|
+
context: SalesEngine::Record#initialize
|
566
|
+
lines:
|
567
|
+
- 7
|
568
|
+
- 8
|
569
|
+
source: ./lib/sales_engine/record.rb
|
570
|
+
- !ruby/object:Reek::SmellWarning
|
571
|
+
smell:
|
572
|
+
class: Duplication
|
573
|
+
subclass: DuplicateMethodCall
|
574
|
+
message: calls Time.now.to_s twice
|
575
|
+
call: Time.now.to_s
|
576
|
+
occurrences: 2
|
577
|
+
status:
|
578
|
+
is_active: true
|
579
|
+
location:
|
580
|
+
context: SalesEngine::Record#initialize
|
581
|
+
lines:
|
582
|
+
- 7
|
583
|
+
- 8
|
584
|
+
source: ./lib/sales_engine/record.rb
|
585
|
+
- !ruby/object:Reek::SmellWarning
|
586
|
+
smell:
|
587
|
+
class: IrresponsibleModule
|
588
|
+
subclass: IrresponsibleModule
|
589
|
+
message: has no descriptive comment
|
590
|
+
module_name: Transaction
|
591
|
+
status:
|
592
|
+
is_active: true
|
593
|
+
location:
|
594
|
+
context: SalesEngine::Transaction
|
595
|
+
lines:
|
596
|
+
- 2
|
597
|
+
source: ./lib/sales_engine/transaction.rb
|
598
|
+
- !ruby/object:Reek::SmellWarning
|
599
|
+
smell:
|
600
|
+
class: IrresponsibleModule
|
601
|
+
subclass: IrresponsibleModule
|
602
|
+
message: has no descriptive comment
|
603
|
+
module_name: Array
|
604
|
+
status:
|
605
|
+
is_active: true
|
606
|
+
location:
|
607
|
+
context: Array
|
608
|
+
lines:
|
609
|
+
- 1
|
610
|
+
source: ./lib/utilities.rb
|
611
|
+
"
|
612
|
+
end
|
613
|
+
end
|