rubycritic 0.0.5 → 0.0.16
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/.travis.yml +10 -0
- data/README.md +72 -11
- data/bin/rubycritic +2 -0
- data/lib/rubycritic/adapters/complexity/flog.rb +22 -0
- data/lib/rubycritic/adapters/smell/flay.rb +68 -0
- data/lib/rubycritic/adapters/smell/flog.rb +62 -0
- data/lib/rubycritic/adapters/smell/reek.rb +44 -0
- data/lib/rubycritic/analysers/churn.rb +19 -0
- data/lib/rubycritic/analysers/config.reek +8 -0
- data/lib/rubycritic/analysers/flay.rb +15 -0
- data/lib/rubycritic/analysers/flog.rb +1 -2
- data/lib/rubycritic/analysers/stats.rb +31 -0
- data/lib/rubycritic/analysers_runner.rb +15 -14
- data/lib/rubycritic/cli.rb +35 -14
- data/lib/rubycritic/configuration.rb +24 -0
- data/lib/rubycritic/core/analysed_file.rb +50 -0
- data/lib/rubycritic/{location.rb → core/location.rb} +6 -2
- data/lib/rubycritic/core/rating.rb +22 -0
- data/lib/rubycritic/{smell.rb → core/smell.rb} +5 -12
- data/lib/rubycritic/files_initializer.rb +15 -0
- data/lib/rubycritic/orchestrator.rb +23 -0
- data/lib/rubycritic/report_generators/assets/javascripts/application.js +87 -8
- data/lib/rubycritic/report_generators/assets/javascripts/highcharts.src-4.0.1.js +17672 -0
- data/lib/rubycritic/report_generators/assets/javascripts/jquery.floatThead-v1.2.7.js +754 -0
- data/lib/rubycritic/report_generators/assets/javascripts/jquery.scrollTo-1.4.11.js +186 -0
- data/lib/rubycritic/report_generators/assets/javascripts/jquery.tablesorter-2.0.js +1031 -0
- data/lib/rubycritic/report_generators/assets/javascripts/jquery.timeago-v1.4.1.js +214 -0
- data/lib/rubycritic/report_generators/assets/stylesheets/application.css +204 -1
- data/lib/rubycritic/report_generators/assets/stylesheets/prettify.custom_theme.css +1 -4
- data/lib/rubycritic/report_generators/base.rb +49 -0
- data/lib/rubycritic/report_generators/code_file.rb +38 -0
- data/lib/rubycritic/report_generators/code_index.rb +24 -0
- data/lib/rubycritic/report_generators/current_code_file.rb +17 -0
- data/lib/rubycritic/report_generators/line.rb +31 -0
- data/lib/rubycritic/report_generators/overview.rb +25 -0
- data/lib/rubycritic/report_generators/smells_index.rb +24 -0
- data/lib/rubycritic/report_generators/templates/code_file.html.erb +36 -0
- data/lib/rubycritic/report_generators/templates/code_index.html.erb +26 -0
- data/lib/rubycritic/report_generators/templates/layouts/application.html.erb +27 -16
- data/lib/rubycritic/report_generators/templates/overview.html.erb +5 -0
- data/lib/rubycritic/report_generators/templates/smells_index.html.erb +20 -0
- data/lib/rubycritic/report_generators/view_helpers.rb +28 -9
- data/lib/rubycritic/reporters/base.rb +24 -0
- data/lib/rubycritic/reporters/main.rb +52 -0
- data/lib/rubycritic/reporters/mini.rb +30 -0
- data/lib/rubycritic/revision_comparator.rb +21 -28
- data/lib/rubycritic/serializer.rb +32 -0
- data/lib/rubycritic/smells_status_setter.rb +7 -16
- data/lib/rubycritic/source_control_systems/base.rb +60 -0
- data/lib/rubycritic/source_control_systems/double.rb +19 -0
- data/lib/rubycritic/source_control_systems/git.rb +47 -37
- data/lib/rubycritic/source_locator.rb +8 -12
- data/lib/rubycritic/turbulence.rb +17 -0
- data/lib/rubycritic/version.rb +1 -1
- data/lib/rubycritic.rb +2 -27
- data/rubycritic.gemspec +3 -0
- data/test/lib/rubycritic/adapters/complexity/flog_test.rb +18 -0
- data/test/lib/rubycritic/adapters/smell/flay_test.rb +34 -0
- data/test/lib/rubycritic/adapters/smell/flog_test.rb +26 -0
- data/test/lib/rubycritic/adapters/smell/reek_test.rb +35 -0
- data/test/lib/rubycritic/analysers/churn_test.rb +38 -0
- data/test/lib/rubycritic/configuration_test.rb +17 -0
- data/test/lib/rubycritic/core/analysed_file_test.rb +71 -0
- data/test/lib/rubycritic/{location_test.rb → core/location_test.rb} +8 -4
- data/test/lib/rubycritic/core/smell_test.rb +73 -0
- data/test/lib/rubycritic/{smells_array_test.rb → core/smells_array_test.rb} +1 -1
- data/test/lib/rubycritic/smells_status_setter_test.rb +5 -5
- data/test/lib/rubycritic/source_control_systems/source_control_system_test.rb +5 -11
- data/test/lib/rubycritic/source_locator_test.rb +26 -17
- data/test/lib/rubycritic/turbulence_test.rb +17 -0
- data/test/lib/rubycritic/version_test.rb +1 -0
- data/test/samples/flay/smelly.rb +17 -0
- data/test/samples/flog/complex.rb +11 -0
- data/test/samples/flog/smelly.rb +7 -2
- data/test/samples/reek/not_smelly.rb +31 -3
- data/test/test_helper.rb +1 -0
- metadata +97 -32
- data/SPEC.md +0 -58
- 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/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/lib/rubycritic/report_generators/assets/javascripts/{prettify.js → prettify-4-Mar-2013.js} +0 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<table id="js-index-table" class="index-table sortable-table">
|
|
2
|
+
<thead>
|
|
3
|
+
<tr>
|
|
4
|
+
<th class="first-cell">Name</th>
|
|
5
|
+
<th class="numeric-cell" title="Number of times a file has changed">Churn</th>
|
|
6
|
+
<th class="numeric-cell" title="Overall amount of code in a file">Complexity</th>
|
|
7
|
+
<th class="numeric-cell" title="Amount of code that is similar to other code">Duplication</th>
|
|
8
|
+
<th class="numeric-cell">Smells</th>
|
|
9
|
+
<th class="centered-cell last-cell">Rating</th>
|
|
10
|
+
</tr>
|
|
11
|
+
</thead>
|
|
12
|
+
<tbody>
|
|
13
|
+
<% @analysed_files.each do |analysed_file| %>
|
|
14
|
+
<tr>
|
|
15
|
+
<td class="first-cell">
|
|
16
|
+
<a href="<%= file_path(analysed_file.pathname.sub_ext('.html')) %>"><%= analysed_file.name %></a>
|
|
17
|
+
</td>
|
|
18
|
+
<td class="numeric-cell"><%= analysed_file.churn %></td>
|
|
19
|
+
<td class="numeric-cell"><%= analysed_file.complexity %></td>
|
|
20
|
+
<td class="numeric-cell"><%= analysed_file.duplication %></td>
|
|
21
|
+
<td class="numeric-cell"><%= analysed_file.smells.length %></td>
|
|
22
|
+
<td class="centered-cell last-cell"><span class="rating-<%= analysed_file.rating.to_s.downcase %> circled-rating circle"><%= analysed_file.rating %></td>
|
|
23
|
+
</tr>
|
|
24
|
+
<% end %>
|
|
25
|
+
</tbody>
|
|
26
|
+
</table>
|
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<
|
|
16
|
-
<
|
|
17
|
-
<
|
|
18
|
-
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
+
<title>RubyCritic</title>
|
|
7
|
+
<link href="<%= stylesheet_path(:application) %>" media="screen, projection, print" rel="stylesheet" type="text/css">
|
|
8
|
+
<link href="<%= stylesheet_path(:'prettify.custom_theme') %>" media="screen, projection, print" rel="stylesheet" type="text/css">
|
|
9
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<header class="project-header group">
|
|
13
|
+
<h1 class="logo"><a href="<%= file_path('overview.html') %>" class="logo-link">RubyCritic</a></h1>
|
|
14
|
+
<nav class="project-nav">
|
|
15
|
+
<a href="<%= file_path('overview.html') %>" class="project-nav-item">Overview</a>
|
|
16
|
+
<a href="<%= file_path('code_index.html') %>" class="project-nav-item">Code</a>
|
|
17
|
+
<a href="<%= file_path('smells_index.html') %>" class="project-nav-item">Smells</a>
|
|
18
|
+
</nav>
|
|
19
|
+
</header>
|
|
20
|
+
<%= yield %>
|
|
21
|
+
<%= javascript_tag(:'jquery-2.1.0') %>
|
|
22
|
+
<%= javascript_tag(:'jquery.tablesorter-2.0') %>
|
|
23
|
+
<%= javascript_tag(:'jquery.floatThead-v1.2.7') %>
|
|
24
|
+
<%= javascript_tag(:'jquery.timeago-v1.4.1') %>
|
|
25
|
+
<%= javascript_tag(:'highcharts.src-4.0.1') %>
|
|
26
|
+
<%= javascript_tag(:'jquery.scrollTo-1.4.11') %>
|
|
27
|
+
<%= javascript_tag(:'prettify-4-Mar-2013') %>
|
|
28
|
+
<%= javascript_tag(:application) %>
|
|
29
|
+
</body>
|
|
19
30
|
</html>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<table id="js-index-table" class="index-table sortable-table">
|
|
2
|
+
<thead>
|
|
3
|
+
<tr>
|
|
4
|
+
<th class="first-cell">Smell</th>
|
|
5
|
+
<th class="last-cell">Locations</th>
|
|
6
|
+
</tr>
|
|
7
|
+
</thead>
|
|
8
|
+
<tbody>
|
|
9
|
+
<% @smells.each do |smell| %>
|
|
10
|
+
<tr>
|
|
11
|
+
<td class="first-cell"><%= smell.type %></td>
|
|
12
|
+
<td class="last-cell">
|
|
13
|
+
<% smell.locations.each do |location| %>
|
|
14
|
+
<a href="<%= smell_location_path(location) %>"><%= location.file_name %></a>
|
|
15
|
+
<% end %>
|
|
16
|
+
</td>
|
|
17
|
+
</tr>
|
|
18
|
+
<% end %>
|
|
19
|
+
</tbody>
|
|
20
|
+
</table>
|
|
@@ -1,25 +1,44 @@
|
|
|
1
|
+
require "pathname"
|
|
2
|
+
|
|
1
3
|
module Rubycritic
|
|
2
4
|
|
|
3
5
|
module ViewHelpers
|
|
4
|
-
def
|
|
5
|
-
|
|
6
|
+
def timeago_tag(time)
|
|
7
|
+
"<time class='js-timeago' datetime='#{time}'>#{time}</time>"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def javascript_tag(file)
|
|
11
|
+
"<script src='" + asset_path("javascripts", "#{file}.js").to_s + "'></script>"
|
|
6
12
|
end
|
|
7
13
|
|
|
8
14
|
def stylesheet_path(file)
|
|
9
|
-
asset_path(
|
|
15
|
+
asset_path("stylesheets", "#{file}.css")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def asset_path(*fragments)
|
|
19
|
+
relative_path(([root_directory, "assets"] + fragments).reduce(:+))
|
|
10
20
|
end
|
|
11
21
|
|
|
12
|
-
def
|
|
13
|
-
|
|
22
|
+
def file_path(file)
|
|
23
|
+
relative_path(root_directory + file)
|
|
14
24
|
end
|
|
15
25
|
|
|
16
26
|
def smell_location_path(location)
|
|
17
|
-
|
|
18
|
-
|
|
27
|
+
relative_path(root_directory + "#{location.pathname.sub_ext('.html')}#L#{location.line}")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def relative_path(pathname)
|
|
33
|
+
pathname.relative_path_from(file_directory)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def file_directory
|
|
37
|
+
raise NotImplementedError.new("The #{self.class} class must implement the #{__method__} method.")
|
|
19
38
|
end
|
|
20
39
|
|
|
21
|
-
def
|
|
22
|
-
|
|
40
|
+
def root_directory
|
|
41
|
+
raise NotImplementedError.new("The #{self.class} class must implement the #{__method__} method.")
|
|
23
42
|
end
|
|
24
43
|
end
|
|
25
44
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
|
|
3
|
+
module Rubycritic
|
|
4
|
+
module Reporter
|
|
5
|
+
|
|
6
|
+
class Base
|
|
7
|
+
ASSETS_DIR = File.expand_path("../../report_generators/assets", __FILE__)
|
|
8
|
+
|
|
9
|
+
def create_directories_and_files(generators)
|
|
10
|
+
Array(generators).each do |generator|
|
|
11
|
+
FileUtils.mkdir_p(generator.file_directory)
|
|
12
|
+
File.open(generator.file_pathname, "w+") do |file|
|
|
13
|
+
file.write(generator.render)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def copy_assets_to_report_directory
|
|
19
|
+
FileUtils.cp_r(ASSETS_DIR, ::Rubycritic.configuration.root)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require "rubycritic/reporters/base"
|
|
2
|
+
require "rubycritic/report_generators/overview"
|
|
3
|
+
require "rubycritic/report_generators/smells_index"
|
|
4
|
+
require "rubycritic/report_generators/code_index"
|
|
5
|
+
require "rubycritic/report_generators/code_file"
|
|
6
|
+
|
|
7
|
+
module Rubycritic
|
|
8
|
+
module Reporter
|
|
9
|
+
|
|
10
|
+
class Main < Base
|
|
11
|
+
def initialize(analysed_files)
|
|
12
|
+
@analysed_files = analysed_files
|
|
13
|
+
@smells = analysed_files.flat_map(&:smells).uniq
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def generate_report
|
|
17
|
+
create_directories_and_files(generators)
|
|
18
|
+
copy_assets_to_report_directory
|
|
19
|
+
report_location
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def generators
|
|
25
|
+
[overview_generator, code_index_generator, smells_index_generator] + file_generators
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def overview_generator
|
|
29
|
+
@overview_generator ||= Generator::Overview.new(@analysed_files)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def code_index_generator
|
|
33
|
+
Generator::CodeIndex.new(@analysed_files)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def smells_index_generator
|
|
37
|
+
Generator::SmellsIndex.new(@smells)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def file_generators
|
|
41
|
+
@analysed_files.map do |analysed_file|
|
|
42
|
+
Generator::CodeFile.new(analysed_file)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def report_location
|
|
47
|
+
overview_generator.file_href
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require "rubycritic/reporters/base"
|
|
2
|
+
require "rubycritic/report_generators/current_code_file"
|
|
3
|
+
|
|
4
|
+
module Rubycritic
|
|
5
|
+
module Reporter
|
|
6
|
+
|
|
7
|
+
class Mini < Base
|
|
8
|
+
def initialize(analysed_files)
|
|
9
|
+
@analysed_file = analysed_files.first
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def generate_report
|
|
13
|
+
create_directories_and_files(file_generator)
|
|
14
|
+
copy_assets_to_report_directory
|
|
15
|
+
report_location
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def file_generator
|
|
21
|
+
@file_generator ||= Generator::CurrentCodeFile.new(@analysed_file)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def report_location
|
|
25
|
+
file_generator.file_href
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -1,54 +1,47 @@
|
|
|
1
|
-
require "rubycritic/
|
|
2
|
-
require "rubycritic/
|
|
1
|
+
require "rubycritic/serializer"
|
|
2
|
+
require "rubycritic/files_initializer"
|
|
3
3
|
require "rubycritic/analysers_runner"
|
|
4
|
-
require "rubycritic/smells_aggregator"
|
|
5
4
|
require "rubycritic/smells_status_setter"
|
|
6
5
|
|
|
7
6
|
module Rubycritic
|
|
8
7
|
|
|
9
8
|
class RevisionComparator
|
|
10
|
-
|
|
9
|
+
SNAPSHOTS_DIR_NAME = "snapshots"
|
|
11
10
|
|
|
12
|
-
def initialize(
|
|
13
|
-
@
|
|
11
|
+
def initialize(analysed_files, source_control_system)
|
|
12
|
+
@analysed_files_now = analysed_files
|
|
14
13
|
@source_control_system = source_control_system
|
|
15
14
|
end
|
|
16
15
|
|
|
17
|
-
def
|
|
18
|
-
SmellsStatusSetter.
|
|
16
|
+
def set_statuses
|
|
17
|
+
SmellsStatusSetter.set(
|
|
18
|
+
analysed_files_before.flat_map(&:smells),
|
|
19
|
+
@analysed_files_now.flat_map(&:smells)
|
|
20
|
+
)
|
|
19
21
|
end
|
|
20
22
|
|
|
21
23
|
private
|
|
22
24
|
|
|
23
|
-
def
|
|
24
|
-
serializer =
|
|
25
|
+
def analysed_files_before
|
|
26
|
+
serializer = Serializer.new(revision_file)
|
|
25
27
|
if File.file?(revision_file)
|
|
26
28
|
serializer.load
|
|
27
29
|
else
|
|
28
|
-
|
|
30
|
+
analysed_files = FilesInitializer.init(["."])
|
|
29
31
|
@source_control_system.travel_to_head do
|
|
30
|
-
|
|
32
|
+
AnalysersRunner.new(analysed_files, @source_control_system).run
|
|
31
33
|
end
|
|
32
|
-
serializer.dump(
|
|
33
|
-
|
|
34
|
+
serializer.dump(analysed_files)
|
|
35
|
+
analysed_files
|
|
34
36
|
end
|
|
35
37
|
end
|
|
36
38
|
|
|
37
|
-
def smelly_pathnames_now
|
|
38
|
-
smelly_pathnames(@paths)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def smelly_pathnames(paths)
|
|
42
|
-
smell_adapters = AnalysersRunner.new(paths).run
|
|
43
|
-
SmellsAggregator.new(smell_adapters).smelly_pathnames
|
|
44
|
-
end
|
|
45
|
-
|
|
46
39
|
def revision_file
|
|
47
|
-
@revision_file ||= File.join(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
40
|
+
@revision_file ||= File.join(
|
|
41
|
+
::Rubycritic.configuration.root,
|
|
42
|
+
SNAPSHOTS_DIR_NAME,
|
|
43
|
+
@source_control_system.head_reference
|
|
44
|
+
)
|
|
52
45
|
end
|
|
53
46
|
end
|
|
54
47
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
|
|
3
|
+
module Rubycritic
|
|
4
|
+
|
|
5
|
+
class Serializer
|
|
6
|
+
def initialize(file)
|
|
7
|
+
@file = file
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def load
|
|
11
|
+
Marshal.load(File.binread(@file))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def dump(content)
|
|
15
|
+
create_file_directory
|
|
16
|
+
File.open(@file, "w+") do |file|
|
|
17
|
+
Marshal.dump(content, file)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def create_file_directory
|
|
24
|
+
FileUtils.mkdir_p(file_directory)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def file_directory
|
|
28
|
+
File.dirname(@file)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
@@ -1,25 +1,16 @@
|
|
|
1
1
|
module Rubycritic
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
def
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def smelly_pathnames
|
|
10
|
-
@smelly_pathnames_now.each do |pathname, smells_now|
|
|
11
|
-
smells_before = @smelly_pathnames_before[pathname] || []
|
|
12
|
-
old_smells = smells_now & smells_before
|
|
13
|
-
set_status(old_smells, :old)
|
|
14
|
-
new_smells = smells_now - smells_before
|
|
15
|
-
set_status(new_smells, :new)
|
|
16
|
-
end
|
|
17
|
-
@smelly_pathnames_now
|
|
3
|
+
module SmellsStatusSetter
|
|
4
|
+
def self.set(smells_before, smells_now)
|
|
5
|
+
old_smells = smells_now & smells_before
|
|
6
|
+
set_status(old_smells, :old)
|
|
7
|
+
new_smells = smells_now - smells_before
|
|
8
|
+
set_status(new_smells, :new)
|
|
18
9
|
end
|
|
19
10
|
|
|
20
11
|
private
|
|
21
12
|
|
|
22
|
-
def set_status(smells, status)
|
|
13
|
+
def self.set_status(smells, status)
|
|
23
14
|
smells.each { |smell| smell.status = status }
|
|
24
15
|
end
|
|
25
16
|
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require "shellwords"
|
|
2
|
+
|
|
3
|
+
module Rubycritic
|
|
4
|
+
module SourceControlSystem
|
|
5
|
+
|
|
6
|
+
class Base
|
|
7
|
+
@@systems = []
|
|
8
|
+
|
|
9
|
+
def self.register_system
|
|
10
|
+
@@systems << self
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.create
|
|
14
|
+
supported_system = systems.detect(&:supported?)
|
|
15
|
+
if supported_system
|
|
16
|
+
supported_system.new
|
|
17
|
+
else
|
|
18
|
+
puts "Rubycritic requires a #{system_names} repository."
|
|
19
|
+
Double.new
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.systems
|
|
24
|
+
@@systems
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.system_names
|
|
28
|
+
systems.join(", ")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.supported?
|
|
32
|
+
raise NotImplementedError.new("The #{self.class} class must implement the #{__method__} method.")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def has_revision?
|
|
36
|
+
raise NotImplementedError.new("The #{self.class} class must implement the #{__method__} method.")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def head_reference
|
|
40
|
+
raise NotImplementedError.new("The #{self.class} class must implement the #{__method__} method.")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def travel_to_head
|
|
44
|
+
raise NotImplementedError.new("The #{self.class} class must implement the #{__method__} method.")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def revisions_count(path)
|
|
48
|
+
raise NotImplementedError.new("The #{self.class} class must implement the #{__method__} method.")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def date_of_last_commit(path)
|
|
52
|
+
raise NotImplementedError.new("The #{self.class} class must implement the #{__method__} method.")
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
require "rubycritic/source_control_systems/double"
|
|
60
|
+
require "rubycritic/source_control_systems/git"
|
|
@@ -1,53 +1,63 @@
|
|
|
1
1
|
module Rubycritic
|
|
2
|
+
module SourceControlSystem
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
class Git < Base
|
|
5
|
+
register_system
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
def self.supported?
|
|
8
|
+
`git branch 2>&1` && $?.success?
|
|
9
|
+
end
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
def self.to_s
|
|
12
|
+
"Git"
|
|
13
|
+
end
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
def has_revision?
|
|
16
|
+
head_reference && $?.success?
|
|
17
|
+
end
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
def head_reference
|
|
20
|
+
`git rev-parse --verify HEAD`.chomp!
|
|
21
|
+
end
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
def travel_to_head
|
|
24
|
+
stash_successful = stash_changes
|
|
25
|
+
yield
|
|
26
|
+
ensure
|
|
27
|
+
travel_to_original_state if stash_successful
|
|
28
|
+
end
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
def revisions_count(path)
|
|
31
|
+
`git log --follow --format=oneline #{path.shellescape}`.count("\n")
|
|
32
|
+
end
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
def date_of_last_commit(path)
|
|
35
|
+
`git log -1 --date=iso --format=%ad #{path.shellescape}`.chomp!
|
|
36
|
+
end
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
`git stash`
|
|
36
|
-
stashes_count_after = stashes_count
|
|
37
|
-
stashes_count_after > stashes_count_before
|
|
38
|
-
end
|
|
38
|
+
private
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
end
|
|
40
|
+
def stash_changes
|
|
41
|
+
return false if everything_commmited?
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
stashes_count_before = stashes_count
|
|
44
|
+
`git stash`
|
|
45
|
+
stashes_count_after = stashes_count
|
|
46
|
+
stashes_count_after > stashes_count_before
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def everything_commmited?
|
|
50
|
+
`git status --porcelain`.empty?
|
|
51
|
+
end
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
def stashes_count
|
|
54
|
+
`git stash list`.count("\n")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def travel_to_original_state
|
|
58
|
+
`git stash pop`
|
|
59
|
+
end
|
|
50
60
|
end
|
|
51
|
-
end
|
|
52
61
|
|
|
62
|
+
end
|
|
53
63
|
end
|
|
@@ -7,31 +7,27 @@ module Rubycritic
|
|
|
7
7
|
RUBY_FILES = File.join("**", "*#{RUBY_EXTENSION}")
|
|
8
8
|
|
|
9
9
|
def initialize(paths)
|
|
10
|
-
@
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def pathnames
|
|
14
|
-
@pathnames ||= expand_paths
|
|
10
|
+
@initial_paths = paths
|
|
15
11
|
end
|
|
16
12
|
|
|
17
13
|
def paths
|
|
18
14
|
@paths ||= pathnames.map(&:to_s)
|
|
19
15
|
end
|
|
20
16
|
|
|
17
|
+
def pathnames
|
|
18
|
+
@pathnames ||= expand_paths
|
|
19
|
+
end
|
|
20
|
+
|
|
21
21
|
private
|
|
22
22
|
|
|
23
23
|
def expand_paths
|
|
24
|
-
@
|
|
24
|
+
@initial_paths.map do |path|
|
|
25
25
|
if File.directory?(path)
|
|
26
|
-
Pathname.glob(
|
|
26
|
+
Pathname.glob(File.join(path, RUBY_FILES))
|
|
27
27
|
elsif File.exists?(path) && File.extname(path) == RUBY_EXTENSION
|
|
28
28
|
Pathname.new(path)
|
|
29
29
|
end
|
|
30
|
-
end.flatten.compact.sort
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def files_contained_in(path)
|
|
34
|
-
(path == ".") ? RUBY_FILES : File.join(path, RUBY_FILES)
|
|
30
|
+
end.flatten.compact.map(&:cleanpath).sort
|
|
35
31
|
end
|
|
36
32
|
end
|
|
37
33
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
module Rubycritic
|
|
4
|
+
|
|
5
|
+
module Turbulence
|
|
6
|
+
def self.data(analysed_files)
|
|
7
|
+
analysed_files.map do |analysed_file|
|
|
8
|
+
{
|
|
9
|
+
:name => analysed_file.pathname,
|
|
10
|
+
:x => analysed_file.churn,
|
|
11
|
+
:y => analysed_file.complexity
|
|
12
|
+
}
|
|
13
|
+
end.to_json
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
data/lib/rubycritic/version.rb
CHANGED