rubycritic 0.0.5 → 1.4.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +593 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +45 -0
- data/CONTRIBUTING.md +67 -15
- data/README.md +105 -14
- data/Rakefile +9 -6
- data/bin/rubycritic +3 -1
- data/lib/rubycritic/analysers/attributes.rb +21 -0
- data/lib/rubycritic/analysers/churn.rb +21 -0
- data/lib/rubycritic/analysers/complexity.rb +22 -0
- data/lib/rubycritic/analysers/helpers/ast_node.rb +69 -0
- data/lib/rubycritic/analysers/{config.reek → helpers/config.reek} +8 -0
- data/lib/rubycritic/analysers/helpers/flay.rb +13 -0
- data/lib/rubycritic/analysers/helpers/flog.rb +17 -0
- data/lib/rubycritic/analysers/helpers/methods_counter.rb +25 -0
- data/lib/rubycritic/analysers/helpers/modules_locator.rb +43 -0
- data/lib/rubycritic/analysers/helpers/parser.rb +12 -0
- data/lib/rubycritic/analysers/helpers/reek.rb +17 -0
- data/lib/rubycritic/analysers/smells/flay.rb +68 -0
- data/lib/rubycritic/analysers/smells/flog.rb +62 -0
- data/lib/rubycritic/analysers/smells/reek.rb +44 -0
- data/lib/rubycritic/analysers_runner.rb +21 -10
- data/lib/rubycritic/cli/application.rb +24 -0
- data/lib/rubycritic/cli/options.rb +79 -0
- data/lib/rubycritic/commands/ci.rb +26 -0
- data/lib/rubycritic/commands/default.rb +28 -0
- data/lib/rubycritic/commands/help.rb +13 -0
- data/lib/rubycritic/commands/version.rb +11 -0
- data/lib/rubycritic/configuration.rb +33 -0
- data/lib/rubycritic/core/analysed_module.rb +66 -0
- data/lib/rubycritic/{location.rb → core/location.rb} +17 -2
- data/lib/rubycritic/core/rating.rb +30 -0
- data/lib/rubycritic/{smell.rb → core/smell.rb} +22 -13
- data/lib/rubycritic/generators/html/assets/javascripts/application.js +104 -0
- data/lib/rubycritic/generators/html/assets/javascripts/highcharts.src-4.0.1.js +17672 -0
- data/lib/rubycritic/generators/html/assets/javascripts/jquery.floatThead-v1.2.7.js +754 -0
- data/lib/rubycritic/generators/html/assets/javascripts/jquery.scrollTo-1.4.11.js +186 -0
- data/lib/rubycritic/generators/html/assets/javascripts/jquery.tablesorter.js +2089 -0
- data/lib/rubycritic/generators/html/assets/javascripts/jquery.timeago-v1.4.1.js +214 -0
- data/lib/rubycritic/generators/html/assets/stylesheets/application.css +303 -0
- data/lib/rubycritic/{report_generators → generators/html}/assets/stylesheets/prettify.custom_theme.css +1 -4
- data/lib/rubycritic/generators/html/base.rb +52 -0
- data/lib/rubycritic/generators/html/code_file.rb +40 -0
- data/lib/rubycritic/generators/html/code_index.rb +26 -0
- data/lib/rubycritic/generators/html/line.rb +37 -0
- data/lib/rubycritic/generators/html/overview.rb +27 -0
- data/lib/rubycritic/generators/html/smells_index.rb +38 -0
- data/lib/rubycritic/generators/html/templates/code_file.html.erb +38 -0
- data/lib/rubycritic/generators/html/templates/code_index.html.erb +30 -0
- data/lib/rubycritic/generators/html/templates/layouts/application.html.erb +34 -0
- data/lib/rubycritic/generators/html/templates/overview.html.erb +5 -0
- data/lib/rubycritic/generators/html/templates/smells_index.html.erb +26 -0
- data/lib/rubycritic/{report_generators → generators/html}/templates/smelly_line.html.erb +1 -1
- data/lib/rubycritic/generators/html/turbulence.rb +17 -0
- data/lib/rubycritic/generators/html/view_helpers.rb +43 -0
- data/lib/rubycritic/generators/html_report.rb +66 -0
- data/lib/rubycritic/generators/json/simple.rb +30 -0
- data/lib/rubycritic/generators/json_report.rb +23 -0
- data/lib/rubycritic/reporter.rb +20 -0
- data/lib/rubycritic/revision_comparator.rb +27 -29
- data/lib/rubycritic/serializer.rb +32 -0
- data/lib/rubycritic/smells_status_setter.rb +7 -16
- data/lib/rubycritic/source_control_systems/base.rb +37 -0
- data/lib/rubycritic/source_control_systems/double.rb +18 -0
- data/lib/rubycritic/source_control_systems/git.rb +41 -37
- data/lib/rubycritic/source_control_systems/mercurial.rb +29 -0
- data/lib/rubycritic/source_locator.rb +25 -13
- data/lib/rubycritic/version.rb +1 -1
- data/lib/rubycritic.rb +17 -22
- data/rubycritic.gemspec +10 -7
- data/test/analysers_test_helper.rb +3 -0
- data/test/lib/rubycritic/analysers/churn_test.rb +33 -0
- data/test/lib/rubycritic/analysers/complexity_test.rb +16 -0
- data/test/lib/rubycritic/analysers/helpers/methods_counter_test.rb +29 -0
- data/test/lib/rubycritic/analysers/helpers/modules_locator_test.rb +53 -0
- data/test/lib/rubycritic/analysers/smells/flay_test.rb +39 -0
- data/test/lib/rubycritic/analysers/smells/flog_test.rb +26 -0
- data/test/lib/rubycritic/analysers/smells/reek_test.rb +33 -0
- data/test/lib/rubycritic/configuration_test.rb +29 -0
- data/test/lib/rubycritic/core/analysed_module_test.rb +88 -0
- data/test/lib/rubycritic/{location_test.rb → core/location_test.rb} +8 -4
- data/test/lib/rubycritic/core/smell_test.rb +72 -0
- data/test/lib/rubycritic/{smells_array_test.rb → core/smells_array_test.rb} +1 -1
- data/test/lib/rubycritic/report_generators/turbulence_test.rb +17 -0
- data/test/lib/rubycritic/report_generators/view_helpers_test.rb +83 -0
- data/test/lib/rubycritic/smells_status_setter_test.rb +5 -5
- data/test/lib/rubycritic/source_control_systems/base_test.rb +29 -0
- data/test/lib/rubycritic/source_control_systems/double_test.rb +11 -0
- data/test/lib/rubycritic/source_control_systems/git_test.rb +13 -0
- data/test/lib/rubycritic/source_control_systems/interfaces/basic.rb +7 -0
- data/test/lib/rubycritic/source_control_systems/interfaces/time_travel.rb +7 -0
- data/test/lib/rubycritic/source_control_systems/mercurial_test.rb +11 -0
- data/test/lib/rubycritic/source_locator_test.rb +42 -18
- data/test/lib/rubycritic/version_test.rb +1 -0
- data/test/samples/empty.rb +0 -0
- data/test/samples/flay/smelly.rb +8 -0
- data/test/samples/flay/smelly2.rb +8 -0
- data/test/samples/flog/complex.rb +11 -0
- data/test/samples/flog/smelly.rb +7 -2
- data/test/samples/location/file0_symlink.rb +0 -0
- data/test/samples/methods_count.rb +7 -0
- data/test/samples/module_names.rb +18 -0
- data/test/samples/reek/not_smelly.rb +31 -3
- data/test/samples/unparsable.rb +1 -0
- data/test/test_helper.rb +39 -0
- metadata +178 -53
- data/SPEC.md +0 -58
- data/lib/rubycritic/analysers/flog.rb +0 -20
- data/lib/rubycritic/analysers/reek.rb +0 -15
- data/lib/rubycritic/cli.rb +0 -25
- data/lib/rubycritic/report_generators/assets/javascripts/application.js +0 -25
- data/lib/rubycritic/report_generators/assets/stylesheets/application.css +0 -26
- data/lib/rubycritic/report_generators/base_generator.rb +0 -42
- data/lib/rubycritic/report_generators/file_generator.rb +0 -42
- data/lib/rubycritic/report_generators/index_generator.rb +0 -28
- data/lib/rubycritic/report_generators/line_generator.rb +0 -27
- data/lib/rubycritic/report_generators/reporter.rb +0 -45
- data/lib/rubycritic/report_generators/templates/file.html.erb +0 -3
- data/lib/rubycritic/report_generators/templates/index.html.erb +0 -14
- data/lib/rubycritic/report_generators/templates/layouts/application.html.erb +0 -19
- data/lib/rubycritic/report_generators/view_helpers.rb +0 -26
- data/lib/rubycritic/smell_adapters/flog.rb +0 -41
- data/lib/rubycritic/smell_adapters/reek.rb +0 -35
- data/lib/rubycritic/smells_aggregator.rb +0 -29
- data/lib/rubycritic/smelly_pathnames_serializer.rb +0 -34
- data/lib/rubycritic/source_control_systems/source_control_system.rb +0 -42
- data/test/lib/rubycritic/metric_adapters/flog_adapter_test.rb +0 -25
- data/test/lib/rubycritic/metric_adapters/reek_adapter_test.rb +0 -34
- data/test/lib/rubycritic/smell_test.rb +0 -71
- data/test/lib/rubycritic/smells_aggregator_test.rb +0 -47
- data/test/lib/rubycritic/source_control_systems/source_control_system_test.rb +0 -26
- /data/lib/rubycritic/{report_generators → generators/html}/assets/javascripts/jquery-2.1.0.js +0 -0
- /data/lib/rubycritic/{report_generators/assets/javascripts/prettify.js → generators/html/assets/javascripts/prettify-4-Mar-2013.js} +0 -0
- /data/lib/rubycritic/{report_generators → generators/html}/templates/line.html.erb +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require "rubycritic/analysers/helpers/reek"
|
|
2
|
+
require "rubycritic/core/smell"
|
|
3
|
+
|
|
4
|
+
module Rubycritic
|
|
5
|
+
module Analyser
|
|
6
|
+
|
|
7
|
+
class ReekSmells
|
|
8
|
+
def initialize(analysed_modules)
|
|
9
|
+
@analysed_modules = analysed_modules
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def run
|
|
13
|
+
@analysed_modules.each do |analysed_module|
|
|
14
|
+
add_smells_to(analysed_module)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def add_smells_to(analysed_module)
|
|
21
|
+
Reek.new(analysed_module.path).smells.each do |smell|
|
|
22
|
+
analysed_module.smells << create_smell(smell)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def create_smell(smell)
|
|
27
|
+
Smell.new(
|
|
28
|
+
:locations => smell_locations(smell.source, smell.lines),
|
|
29
|
+
:context => smell.context,
|
|
30
|
+
:message => smell.message,
|
|
31
|
+
:type => smell.smell_type,
|
|
32
|
+
:cost => 0
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def smell_locations(file_path, file_lines)
|
|
37
|
+
file_lines.uniq.map do |file_line|
|
|
38
|
+
Location.new(file_path, file_line)
|
|
39
|
+
end.sort
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -1,25 +1,36 @@
|
|
|
1
|
-
require "rubycritic/
|
|
2
|
-
require "rubycritic/
|
|
1
|
+
require "rubycritic/source_locator"
|
|
2
|
+
require "rubycritic/core/analysed_module"
|
|
3
|
+
require "rubycritic/analysers/smells/flay"
|
|
4
|
+
require "rubycritic/analysers/smells/flog"
|
|
5
|
+
require "rubycritic/analysers/smells/reek"
|
|
6
|
+
require "rubycritic/analysers/complexity"
|
|
7
|
+
require "rubycritic/analysers/churn"
|
|
8
|
+
require "rubycritic/analysers/attributes"
|
|
3
9
|
|
|
4
10
|
module Rubycritic
|
|
5
11
|
|
|
6
12
|
class AnalysersRunner
|
|
7
|
-
ANALYSERS = [
|
|
13
|
+
ANALYSERS = [
|
|
14
|
+
Analyser::FlaySmells,
|
|
15
|
+
Analyser::FlogSmells,
|
|
16
|
+
Analyser::ReekSmells,
|
|
17
|
+
Analyser::Complexity,
|
|
18
|
+
Analyser::Attributes,
|
|
19
|
+
Analyser::Churn
|
|
20
|
+
]
|
|
8
21
|
|
|
9
22
|
def initialize(paths)
|
|
10
23
|
@paths = paths
|
|
11
24
|
end
|
|
12
25
|
|
|
13
26
|
def run
|
|
14
|
-
|
|
27
|
+
ANALYSERS.each { |analyser| analyser.new(analysed_modules).run }
|
|
28
|
+
analysed_modules
|
|
15
29
|
end
|
|
16
30
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
ANALYSERS.map do |analyser_name|
|
|
21
|
-
analyser = Object.const_get("Rubycritic::Analyser::#{analyser_name}").new(@paths)
|
|
22
|
-
Object.const_get("Rubycritic::SmellAdapter::#{analyser_name}").new(analyser)
|
|
31
|
+
def analysed_modules
|
|
32
|
+
@analysed_modules ||= SourceLocator.new(@paths).pathnames.map do |pathname|
|
|
33
|
+
AnalysedModule.new(:pathname => pathname)
|
|
23
34
|
end
|
|
24
35
|
end
|
|
25
36
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require "rubycritic"
|
|
2
|
+
require "rubycritic/cli/options"
|
|
3
|
+
|
|
4
|
+
module Rubycritic
|
|
5
|
+
module Cli
|
|
6
|
+
class Application
|
|
7
|
+
STATUS_SUCCESS = 0
|
|
8
|
+
STATUS_ERROR = 1
|
|
9
|
+
|
|
10
|
+
def initialize(argv)
|
|
11
|
+
@options = Options.new(argv)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def execute
|
|
15
|
+
parsed_options = @options.parse
|
|
16
|
+
::Rubycritic.create(parsed_options).execute
|
|
17
|
+
STATUS_SUCCESS
|
|
18
|
+
rescue OptionParser::InvalidOption => error
|
|
19
|
+
$stderr.puts "Error: #{error}"
|
|
20
|
+
STATUS_ERROR
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require "optparse"
|
|
2
|
+
|
|
3
|
+
module Rubycritic
|
|
4
|
+
module Cli
|
|
5
|
+
class Options
|
|
6
|
+
def initialize(argv)
|
|
7
|
+
@argv = argv
|
|
8
|
+
@parser = OptionParser.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# rubocop:disable Metrics/MethodLength
|
|
12
|
+
def parse
|
|
13
|
+
@parser.new do |opts|
|
|
14
|
+
opts.banner = "Usage: rubycritic [options] [paths]"
|
|
15
|
+
|
|
16
|
+
opts.on("-p", "--path [PATH]", "Set path where report will be saved (tmp/rubycritic by default)") do |path|
|
|
17
|
+
@root = path
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
opts.on(
|
|
21
|
+
"-f", "--format [FORMAT]",
|
|
22
|
+
[:html, :json],
|
|
23
|
+
"Report smells in the given format:",
|
|
24
|
+
" html (default)",
|
|
25
|
+
" json"
|
|
26
|
+
) do |format|
|
|
27
|
+
@format = format
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
opts.on("-m", "--mode-ci", "Use CI mode (faster, but only analyses last commit)") do
|
|
31
|
+
@mode = :ci
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
opts.on("--deduplicate-symlinks", "De-duplicate symlinks based on their final target") do
|
|
35
|
+
@deduplicate_symlinks = true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
opts.on("--suppress-ratings", "Suppress letter ratings") do
|
|
39
|
+
@suppress_ratings = true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
opts.on_tail("-v", "--version", "Show gem's version") do
|
|
43
|
+
@mode = :version
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
|
47
|
+
@mode = :help
|
|
48
|
+
end
|
|
49
|
+
end.parse!(@argv)
|
|
50
|
+
self
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def help_text
|
|
54
|
+
@parser.help
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def to_h
|
|
58
|
+
{
|
|
59
|
+
:mode => @mode,
|
|
60
|
+
:root => @root,
|
|
61
|
+
:format => @format,
|
|
62
|
+
:deduplicate_symlinks => @deduplicate_symlinks,
|
|
63
|
+
:paths => paths,
|
|
64
|
+
:suppress_ratings => @suppress_ratings
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def paths
|
|
71
|
+
if @argv.empty?
|
|
72
|
+
["."]
|
|
73
|
+
else
|
|
74
|
+
@argv
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "rubycritic/source_control_systems/base"
|
|
2
|
+
require "rubycritic/analysers_runner"
|
|
3
|
+
require "rubycritic/reporter"
|
|
4
|
+
|
|
5
|
+
module Rubycritic
|
|
6
|
+
module Command
|
|
7
|
+
class Ci
|
|
8
|
+
def initialize(paths)
|
|
9
|
+
@paths = paths
|
|
10
|
+
Config.source_control_system = SourceControlSystem::Base.create
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def execute
|
|
14
|
+
report(critique)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def critique
|
|
18
|
+
AnalysersRunner.new(@paths).run
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def report(analysed_modules)
|
|
22
|
+
Reporter.generate_report(analysed_modules)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require "rubycritic/source_control_systems/base"
|
|
2
|
+
require "rubycritic/analysers_runner"
|
|
3
|
+
require "rubycritic/revision_comparator"
|
|
4
|
+
require "rubycritic/reporter"
|
|
5
|
+
|
|
6
|
+
module Rubycritic
|
|
7
|
+
module Command
|
|
8
|
+
class Default
|
|
9
|
+
def initialize(paths)
|
|
10
|
+
@paths = paths
|
|
11
|
+
Config.source_control_system = SourceControlSystem::Base.create
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def execute
|
|
15
|
+
report(critique)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def critique
|
|
19
|
+
analysed_modules = AnalysersRunner.new(@paths).run
|
|
20
|
+
RevisionComparator.new(@paths).set_statuses(analysed_modules)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def report(analysed_modules)
|
|
24
|
+
Reporter.generate_report(analysed_modules)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Rubycritic
|
|
2
|
+
class Configuration
|
|
3
|
+
attr_reader :root
|
|
4
|
+
attr_accessor :source_control_system, :mode, :format, :deduplicate_symlinks,
|
|
5
|
+
:suppress_ratings
|
|
6
|
+
|
|
7
|
+
def set(options)
|
|
8
|
+
self.mode = options[:mode] || :default
|
|
9
|
+
self.root = options[:root] || "tmp/rubycritic"
|
|
10
|
+
self.format = options[:format] || :html
|
|
11
|
+
self.deduplicate_symlinks = options[:deduplicate_symlinks] || false
|
|
12
|
+
self.suppress_ratings = options[:suppress_ratings] || false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def root=(path)
|
|
16
|
+
@root = File.expand_path(path)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
module Config
|
|
21
|
+
def self.configuration
|
|
22
|
+
@configuration ||= Configuration.new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.set(options = {})
|
|
26
|
+
configuration.set(options)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.method_missing(method, *args, &block)
|
|
30
|
+
configuration.public_send(method, *args, &block)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require "virtus"
|
|
2
|
+
require "rubycritic/core/rating"
|
|
3
|
+
|
|
4
|
+
module Rubycritic
|
|
5
|
+
|
|
6
|
+
class AnalysedModule
|
|
7
|
+
include Virtus.model
|
|
8
|
+
|
|
9
|
+
attribute :name
|
|
10
|
+
attribute :pathname
|
|
11
|
+
attribute :smells, Array, :default => []
|
|
12
|
+
attribute :churn
|
|
13
|
+
attribute :committed_at
|
|
14
|
+
attribute :complexity
|
|
15
|
+
attribute :duplication, Integer, :default => 0
|
|
16
|
+
attribute :methods_count
|
|
17
|
+
|
|
18
|
+
def path
|
|
19
|
+
@path ||= pathname.to_s
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def cost
|
|
23
|
+
@cost ||= smells.map(&:cost).inject(0, :+) + (complexity / 25)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def rating
|
|
27
|
+
@rating ||= Rating.from_cost(cost)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def complexity_per_method
|
|
31
|
+
if methods_count == 0
|
|
32
|
+
"N/A"
|
|
33
|
+
else
|
|
34
|
+
complexity.fdiv(methods_count).round(1)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def smells?
|
|
39
|
+
!smells.empty?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def smells_at_location(location)
|
|
43
|
+
smells.select { |smell| smell.at_location?(location) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def to_h
|
|
47
|
+
{
|
|
48
|
+
:name => name,
|
|
49
|
+
:path => path,
|
|
50
|
+
:smells => smells,
|
|
51
|
+
:churn => churn,
|
|
52
|
+
:committed_at => committed_at,
|
|
53
|
+
:complexity => complexity,
|
|
54
|
+
:duplication => duplication,
|
|
55
|
+
:methods_count => methods_count,
|
|
56
|
+
:cost => cost,
|
|
57
|
+
:rating => rating
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def to_json(*a)
|
|
62
|
+
to_h.to_json(*a)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
@@ -7,15 +7,30 @@ module Rubycritic
|
|
|
7
7
|
|
|
8
8
|
def initialize(path, line)
|
|
9
9
|
@pathname = Pathname.new(path)
|
|
10
|
-
@line = line
|
|
10
|
+
@line = line.to_i
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def file_name
|
|
14
|
+
@pathname.basename.sub_ext("").to_s
|
|
11
15
|
end
|
|
12
16
|
|
|
13
17
|
def to_s
|
|
14
18
|
"#{pathname}:#{line}"
|
|
15
19
|
end
|
|
16
20
|
|
|
21
|
+
def to_h
|
|
22
|
+
{
|
|
23
|
+
:path => pathname.to_s,
|
|
24
|
+
:line => line
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def to_json(*a)
|
|
29
|
+
to_h.to_json(*a)
|
|
30
|
+
end
|
|
31
|
+
|
|
17
32
|
def ==(other)
|
|
18
|
-
|
|
33
|
+
state == other.state
|
|
19
34
|
end
|
|
20
35
|
|
|
21
36
|
def <=>(other)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Rubycritic
|
|
2
|
+
|
|
3
|
+
class Rating
|
|
4
|
+
def self.from_cost(cost)
|
|
5
|
+
if cost <= 2 then new("A")
|
|
6
|
+
elsif cost <= 4 then new("B")
|
|
7
|
+
elsif cost <= 8 then new("C")
|
|
8
|
+
elsif cost <= 16 then new("D")
|
|
9
|
+
else new("F")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(letter)
|
|
14
|
+
@letter = letter
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_s
|
|
18
|
+
@letter
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_h
|
|
22
|
+
@letter
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def to_json(*a)
|
|
26
|
+
to_h.to_json(*a)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require "virtus"
|
|
2
|
-
require "rubycritic/location"
|
|
2
|
+
require "rubycritic/core/location"
|
|
3
3
|
|
|
4
4
|
module Rubycritic
|
|
5
5
|
|
|
@@ -7,37 +7,46 @@ module Rubycritic
|
|
|
7
7
|
include Virtus.model
|
|
8
8
|
|
|
9
9
|
attribute :context
|
|
10
|
+
attribute :cost
|
|
10
11
|
attribute :locations
|
|
11
12
|
attribute :message
|
|
12
13
|
attribute :score
|
|
13
|
-
attribute :type
|
|
14
14
|
attribute :status
|
|
15
|
+
attribute :type
|
|
15
16
|
|
|
16
|
-
def
|
|
17
|
-
@pathnames ||= locations.map(&:pathname).uniq
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def located_in?(other_location)
|
|
17
|
+
def at_location?(other_location)
|
|
21
18
|
locations.any? { |location| location == other_location }
|
|
22
19
|
end
|
|
23
20
|
|
|
24
|
-
def
|
|
21
|
+
def multiple_locations?
|
|
25
22
|
locations.length > 1
|
|
26
23
|
end
|
|
27
24
|
|
|
28
25
|
def ==(other)
|
|
29
|
-
|
|
26
|
+
state == other.state
|
|
30
27
|
end
|
|
31
28
|
alias_method :eql?, :==
|
|
32
29
|
|
|
33
|
-
def <=>(other)
|
|
34
|
-
locations <=> other.locations
|
|
35
|
-
end
|
|
36
|
-
|
|
37
30
|
def to_s
|
|
38
31
|
"(#{type}) #{context} #{message}"
|
|
39
32
|
end
|
|
40
33
|
|
|
34
|
+
def to_h
|
|
35
|
+
{
|
|
36
|
+
:context => context,
|
|
37
|
+
:cost => cost,
|
|
38
|
+
:locations => locations,
|
|
39
|
+
:message => message,
|
|
40
|
+
:score => score,
|
|
41
|
+
:status => status,
|
|
42
|
+
:type => type
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def to_json(*a)
|
|
47
|
+
to_h.to_json(*a)
|
|
48
|
+
end
|
|
49
|
+
|
|
41
50
|
def hash
|
|
42
51
|
state.hash
|
|
43
52
|
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
prettyPrint();
|
|
2
|
+
|
|
3
|
+
emphasizeLineFromFragment();
|
|
4
|
+
|
|
5
|
+
function emphasizeLineFromFragment() {
|
|
6
|
+
emphasizeLine(window.location.hash)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
$(".js-file-code").on("click", ".js-smell-location", emphasizeLineFromHref);
|
|
10
|
+
|
|
11
|
+
function emphasizeLineFromHref(event) {
|
|
12
|
+
if (hrefTargetIsOnCurrentPage(this) && !event.ctrlKey) {
|
|
13
|
+
$(".js-file-code li").removeClass("highlight");
|
|
14
|
+
var lineId = "#" + this.href.split("#")[1];
|
|
15
|
+
emphasizeLine(lineId);
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function hrefTargetIsOnCurrentPage(aTag) {
|
|
21
|
+
return (window.location.pathname === aTag.pathname);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function emphasizeLine(lineReference) {
|
|
25
|
+
scrollToTarget(lineReference);
|
|
26
|
+
highlightLine(lineReference);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function scrollToTarget(lineReference) {
|
|
30
|
+
$.scrollTo(lineReference, {
|
|
31
|
+
duration: 300,
|
|
32
|
+
easing: "linear",
|
|
33
|
+
onAfter: function() {
|
|
34
|
+
window.location.hash = lineReference;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function highlightLine(lineReference) {
|
|
40
|
+
$(lineReference).addClass("highlight");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
$("#js-toggle-smells").on("click", toggleSmells);
|
|
44
|
+
|
|
45
|
+
function toggleSmells() {
|
|
46
|
+
$(".js-smells").toggle();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
$("#js-index-table")
|
|
50
|
+
.tablesorter({ // Sort the table
|
|
51
|
+
sortList: [[0,0]] // on the first column, in ascending order
|
|
52
|
+
})
|
|
53
|
+
.floatThead(); // Make table headers stick to the top when scrolling
|
|
54
|
+
|
|
55
|
+
$(".js-timeago").timeago();
|
|
56
|
+
|
|
57
|
+
$("#js-chart-container").highcharts({
|
|
58
|
+
chart: {
|
|
59
|
+
type: "scatter",
|
|
60
|
+
zoomType: "xy"
|
|
61
|
+
},
|
|
62
|
+
title: {
|
|
63
|
+
text: "Churn vs Complexity"
|
|
64
|
+
},
|
|
65
|
+
xAxis: {
|
|
66
|
+
title: {
|
|
67
|
+
enabled: true,
|
|
68
|
+
text: "Churn"
|
|
69
|
+
},
|
|
70
|
+
floor: 0,
|
|
71
|
+
startOnTick: true,
|
|
72
|
+
endOnTick: true
|
|
73
|
+
},
|
|
74
|
+
yAxis: {
|
|
75
|
+
title: {
|
|
76
|
+
text: "Complexity"
|
|
77
|
+
},
|
|
78
|
+
floor: 0,
|
|
79
|
+
startOnTick: true,
|
|
80
|
+
endOnTick: true
|
|
81
|
+
},
|
|
82
|
+
plotOptions: {
|
|
83
|
+
scatter: {
|
|
84
|
+
marker: {
|
|
85
|
+
radius: 5,
|
|
86
|
+
states: {
|
|
87
|
+
hover: {
|
|
88
|
+
enabled: true,
|
|
89
|
+
lineColor: "rgb(100,100,100)"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
tooltip: {
|
|
94
|
+
headerFormat: "<b>{point.key}</b><br>",
|
|
95
|
+
pointFormat: "Committed {point.x} times, with Flog score of {point.y}"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
series: [{
|
|
100
|
+
showInLegend: false,
|
|
101
|
+
color: "steelblue",
|
|
102
|
+
data: turbulenceData
|
|
103
|
+
}]
|
|
104
|
+
});
|