rubycritic 1.1.1 → 1.2.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 +1 -1
- data/CHANGELOG.md +7 -0
- data/CONTRIBUTING.md +17 -15
- data/README.md +15 -4
- data/Rakefile +9 -6
- data/bin/rubycritic +2 -2
- data/lib/rubycritic.rb +21 -1
- data/lib/rubycritic/analysers/churn.rb +4 -2
- data/lib/rubycritic/analysers/helpers/ast_node.rb +4 -8
- data/lib/rubycritic/analysers/helpers/methods_counter.rb +2 -5
- data/lib/rubycritic/analysers/helpers/modules_locator.rb +2 -5
- data/lib/rubycritic/analysers/helpers/parser.rb +12 -0
- data/lib/rubycritic/analysers/helpers/reek.rb +6 -2
- data/lib/rubycritic/analysers/smells/reek.rb +1 -1
- data/lib/rubycritic/analysers_runner.rb +13 -7
- data/lib/rubycritic/cli/application.rb +24 -0
- data/lib/rubycritic/cli/options.rb +57 -0
- data/lib/rubycritic/commands/ci.rb +28 -0
- data/lib/rubycritic/commands/default.rb +30 -0
- data/lib/rubycritic/commands/help.rb +13 -0
- data/lib/rubycritic/commands/version.rb +11 -0
- data/lib/rubycritic/configuration.rb +19 -14
- data/lib/rubycritic/core/analysed_module.rb +1 -1
- data/lib/rubycritic/core/smell.rb +1 -1
- data/lib/rubycritic/report_generators/base.rb +1 -1
- data/lib/rubycritic/report_generators/line.rb +1 -1
- data/lib/rubycritic/report_generators/smells_index.rb +1 -0
- data/lib/rubycritic/report_generators/templates/code_file.html.erb +1 -1
- data/lib/rubycritic/report_generators/templates/smells_index.html.erb +6 -2
- data/lib/rubycritic/report_generators/templates/smelly_line.html.erb +1 -1
- data/lib/rubycritic/report_generators/view_helpers.rb +4 -4
- data/lib/rubycritic/reporters/base.rb +1 -1
- data/lib/rubycritic/revision_comparator.rb +14 -14
- data/lib/rubycritic/source_control_systems/base.rb +9 -32
- data/lib/rubycritic/source_control_systems/double.rb +6 -7
- data/lib/rubycritic/source_control_systems/git.rb +10 -16
- data/lib/rubycritic/source_control_systems/mercurial.rb +29 -0
- data/lib/rubycritic/source_locator.rb +4 -5
- data/lib/rubycritic/version.rb +1 -1
- data/rubycritic.gemspec +4 -3
- data/test/lib/rubycritic/analysers/churn_test.rb +5 -5
- data/test/lib/rubycritic/analysers/smells/flay_test.rb +1 -1
- data/test/lib/rubycritic/configuration_test.rb +8 -7
- data/test/lib/rubycritic/core/analysed_module_test.rb +2 -2
- data/test/lib/rubycritic/core/smell_test.rb +2 -2
- data/test/lib/rubycritic/source_control_systems/{source_control_system_test.rb → base_test.rb} +1 -1
- 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 +8 -2
- data/test/test_helper.rb +29 -0
- metadata +49 -13
- data/lib/rubycritic/cli.rb +0 -46
- data/lib/rubycritic/modules_initializer.rb +0 -14
- data/lib/rubycritic/orchestrator.rb +0 -23
@@ -0,0 +1,30 @@
|
|
1
|
+
require "rubycritic/source_control_systems/base"
|
2
|
+
require "rubycritic/analysers_runner"
|
3
|
+
require "rubycritic/revision_comparator"
|
4
|
+
require "rubycritic/reporters/main"
|
5
|
+
|
6
|
+
module Rubycritic
|
7
|
+
module Command
|
8
|
+
class Default
|
9
|
+
def initialize(options)
|
10
|
+
@paths = options[:paths]
|
11
|
+
Config.source_control_system = SourceControlSystem::Base.create
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute
|
15
|
+
critique(@paths)
|
16
|
+
report
|
17
|
+
end
|
18
|
+
|
19
|
+
def critique(paths)
|
20
|
+
@analysed_modules = AnalysersRunner.new(paths).run
|
21
|
+
RevisionComparator.new(paths).set_statuses(@analysed_modules)
|
22
|
+
end
|
23
|
+
|
24
|
+
def report
|
25
|
+
report_location = Reporter::Main.new(@analysed_modules).generate_report
|
26
|
+
puts "New critique at #{report_location}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,24 +1,29 @@
|
|
1
|
-
require "pathname"
|
2
|
-
|
3
1
|
module Rubycritic
|
4
|
-
def self.configuration
|
5
|
-
@configuration ||= Configuration.new
|
6
|
-
end
|
7
|
-
|
8
2
|
class Configuration
|
9
3
|
attr_reader :root
|
4
|
+
attr_accessor :source_control_system, :mode
|
10
5
|
|
11
|
-
def
|
12
|
-
self.
|
6
|
+
def set(options)
|
7
|
+
self.mode = options[:mode] || :default
|
8
|
+
self.root = options[:root] || "tmp/rubycritic"
|
13
9
|
end
|
14
10
|
|
15
11
|
def root=(path)
|
16
|
-
@root =
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
@root = File.expand_path(path)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module Config
|
17
|
+
def self.configuration
|
18
|
+
@configuration ||= Configuration.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.set(options = {})
|
22
|
+
configuration.set(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.method_missing(method, *args, &block)
|
26
|
+
configuration.public_send(method, *args, &block)
|
22
27
|
end
|
23
28
|
end
|
24
29
|
end
|
@@ -3,7 +3,9 @@
|
|
3
3
|
<tr>
|
4
4
|
<th class="first-cell">Smell</th>
|
5
5
|
<th>Locations</th>
|
6
|
-
|
6
|
+
<% if @show_status %>
|
7
|
+
<th class="centered-cell last-cell" title="Code smells introduced recently are marked as new. There's still time before they are committed!">Status</th>
|
8
|
+
<% end %>
|
7
9
|
</tr>
|
8
10
|
</thead>
|
9
11
|
<tbody>
|
@@ -15,7 +17,9 @@
|
|
15
17
|
<a href="<%= smell_location_path(location) %>"><%= @analysed_module_names[location.pathname] %></a>
|
16
18
|
<% end %>
|
17
19
|
</td>
|
18
|
-
|
20
|
+
<% if @show_status %>
|
21
|
+
<td class="centered-cell last-cell"><span class="status-<%= smell.status %> circled-text circle"><%= smell.status %></span></td>
|
22
|
+
<% end %>
|
19
23
|
</tr>
|
20
24
|
<% end %>
|
21
25
|
</tbody>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<% @smells.each do |smell| %>
|
5
5
|
<li class="smell <%= smell.status %>">
|
6
6
|
<span class="description"><%= smell %>
|
7
|
-
<% if smell.
|
7
|
+
<% if smell.multiple_locations? %>
|
8
8
|
<% smell.locations.each_with_index do |location, index| %>
|
9
9
|
<a href="<%= smell_location_path(location) %>" class="js-smell-location"><%= index %></a>
|
10
10
|
<% end %>
|
@@ -14,11 +14,11 @@ module Rubycritic
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def asset_path(file)
|
17
|
-
relative_path(
|
17
|
+
relative_path("assets/#{file}")
|
18
18
|
end
|
19
19
|
|
20
20
|
def file_path(file)
|
21
|
-
relative_path(
|
21
|
+
relative_path(file)
|
22
22
|
end
|
23
23
|
|
24
24
|
def smell_location_path(location)
|
@@ -27,8 +27,8 @@ module Rubycritic
|
|
27
27
|
|
28
28
|
private
|
29
29
|
|
30
|
-
def relative_path(
|
31
|
-
|
30
|
+
def relative_path(file)
|
31
|
+
(root_directory + file).relative_path_from(file_directory)
|
32
32
|
end
|
33
33
|
|
34
34
|
def file_directory
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require "rubycritic/serializer"
|
2
|
-
require "rubycritic/modules_initializer"
|
3
2
|
require "rubycritic/analysers_runner"
|
4
3
|
require "rubycritic/smells_status_setter"
|
5
4
|
require "rubycritic/version"
|
@@ -10,17 +9,18 @@ module Rubycritic
|
|
10
9
|
class RevisionComparator
|
11
10
|
SNAPSHOTS_DIR_NAME = "snapshots"
|
12
11
|
|
13
|
-
def initialize(
|
14
|
-
@analysed_modules_now = analysed_modules
|
15
|
-
@source_control_system = source_control_system
|
12
|
+
def initialize(paths)
|
16
13
|
@paths = paths
|
17
14
|
end
|
18
15
|
|
19
|
-
def set_statuses
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
def set_statuses(analysed_modules_now)
|
17
|
+
if Config.source_control_system.revision?
|
18
|
+
SmellsStatusSetter.set(
|
19
|
+
analysed_modules_before.flat_map(&:smells),
|
20
|
+
analysed_modules_now.flat_map(&:smells)
|
21
|
+
)
|
22
|
+
end
|
23
|
+
analysed_modules_now
|
24
24
|
end
|
25
25
|
|
26
26
|
private
|
@@ -30,9 +30,9 @@ module Rubycritic
|
|
30
30
|
if File.file?(revision_file)
|
31
31
|
serializer.load
|
32
32
|
else
|
33
|
-
analysed_modules =
|
34
|
-
|
35
|
-
AnalysersRunner.new(
|
33
|
+
analysed_modules = nil
|
34
|
+
Config.source_control_system.travel_to_head do
|
35
|
+
analysed_modules = AnalysersRunner.new(@paths).run
|
36
36
|
end
|
37
37
|
serializer.dump(analysed_modules)
|
38
38
|
analysed_modules
|
@@ -41,11 +41,11 @@ module Rubycritic
|
|
41
41
|
|
42
42
|
def revision_file
|
43
43
|
@revision_file ||= File.join(
|
44
|
-
|
44
|
+
Config.root,
|
45
45
|
SNAPSHOTS_DIR_NAME,
|
46
46
|
VERSION,
|
47
47
|
Digest::MD5.hexdigest(Marshal.dump(@paths)),
|
48
|
-
|
48
|
+
Config.source_control_system.head_reference
|
49
49
|
)
|
50
50
|
end
|
51
51
|
end
|
@@ -10,46 +10,22 @@ module Rubycritic
|
|
10
10
|
@@systems << self
|
11
11
|
end
|
12
12
|
|
13
|
+
def self.systems
|
14
|
+
@@systems
|
15
|
+
end
|
16
|
+
|
13
17
|
def self.create
|
14
|
-
supported_system = systems.
|
18
|
+
supported_system = systems.find(&:supported?)
|
15
19
|
if supported_system
|
16
20
|
supported_system.new
|
17
21
|
else
|
18
|
-
puts "
|
22
|
+
puts "RubyCritic can provide more feedback if you use a #{connected_system_names} repository."
|
19
23
|
Double.new
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
23
|
-
def self.
|
24
|
-
|
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.")
|
27
|
+
def self.connected_system_names
|
28
|
+
"#{systems[0...-1].join(', ')} or #{systems[-1]}"
|
53
29
|
end
|
54
30
|
end
|
55
31
|
|
@@ -58,3 +34,4 @@ end
|
|
58
34
|
|
59
35
|
require "rubycritic/source_control_systems/double"
|
60
36
|
require "rubycritic/source_control_systems/git"
|
37
|
+
require "rubycritic/source_control_systems/mercurial"
|
@@ -1,18 +1,17 @@
|
|
1
1
|
module Rubycritic
|
2
2
|
module SourceControlSystem
|
3
|
-
|
4
3
|
class Double < Base
|
5
|
-
def
|
6
|
-
false
|
7
|
-
end
|
8
|
-
|
9
|
-
def revisions_count(path)
|
4
|
+
def revisions_count(_)
|
10
5
|
"N/A"
|
11
6
|
end
|
12
7
|
|
13
|
-
def date_of_last_commit(
|
8
|
+
def date_of_last_commit(_)
|
14
9
|
nil
|
15
10
|
end
|
11
|
+
|
12
|
+
def revision?
|
13
|
+
false
|
14
|
+
end
|
16
15
|
end
|
17
16
|
|
18
17
|
end
|
@@ -12,7 +12,15 @@ module Rubycritic
|
|
12
12
|
"Git"
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
15
|
+
def revisions_count(path)
|
16
|
+
`git log --follow --format=%h #{path.shellescape}`.count("\n")
|
17
|
+
end
|
18
|
+
|
19
|
+
def date_of_last_commit(path)
|
20
|
+
`git log -1 --date=iso --format=%ad #{path.shellescape}`.chomp!
|
21
|
+
end
|
22
|
+
|
23
|
+
def revision?
|
16
24
|
head_reference && $?.success?
|
17
25
|
end
|
18
26
|
|
@@ -27,31 +35,17 @@ module Rubycritic
|
|
27
35
|
travel_to_original_state if stash_successful
|
28
36
|
end
|
29
37
|
|
30
|
-
def revisions_count(path)
|
31
|
-
`git log --follow --format=oneline #{path.shellescape}`.count("\n")
|
32
|
-
end
|
33
|
-
|
34
|
-
def date_of_last_commit(path)
|
35
|
-
`git log -1 --date=iso --format=%ad #{path.shellescape}`.chomp!
|
36
|
-
end
|
37
|
-
|
38
38
|
private
|
39
39
|
|
40
40
|
def stash_changes
|
41
|
-
return false if everything_commmited?
|
42
|
-
|
43
41
|
stashes_count_before = stashes_count
|
44
42
|
`git stash`
|
45
43
|
stashes_count_after = stashes_count
|
46
44
|
stashes_count_after > stashes_count_before
|
47
45
|
end
|
48
46
|
|
49
|
-
def everything_commmited?
|
50
|
-
`git status --porcelain`.empty?
|
51
|
-
end
|
52
|
-
|
53
47
|
def stashes_count
|
54
|
-
`git stash list`.count("\n")
|
48
|
+
`git stash list --format=%h`.count("\n")
|
55
49
|
end
|
56
50
|
|
57
51
|
def travel_to_original_state
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Rubycritic
|
2
|
+
module SourceControlSystem
|
3
|
+
|
4
|
+
class Mercurial < Base
|
5
|
+
register_system
|
6
|
+
|
7
|
+
def self.supported?
|
8
|
+
`hg verify 2>&1` && $?.success?
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.to_s
|
12
|
+
"Mercurial"
|
13
|
+
end
|
14
|
+
|
15
|
+
def revisions_count(path)
|
16
|
+
`hg log #{path.shellescape} --template '1'`.size
|
17
|
+
end
|
18
|
+
|
19
|
+
def date_of_last_commit(path)
|
20
|
+
`hg log #{path.shellescape} --template '{date|isodate}' --limit 1`.chomp
|
21
|
+
end
|
22
|
+
|
23
|
+
def revision?
|
24
|
+
false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|