rubycritic 0.0.1 → 0.0.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.
- checksums.yaml +4 -4
- data/lib/rubycritic.rb +14 -10
- data/lib/rubycritic/analysers_runner.rb +27 -0
- data/lib/rubycritic/report_generators/assets/stylesheets/application.css +8 -0
- data/lib/rubycritic/report_generators/base_generator.rb +36 -0
- data/lib/rubycritic/report_generators/file_generator.rb +7 -23
- data/lib/rubycritic/report_generators/index_generator.rb +28 -0
- data/lib/rubycritic/report_generators/line_generator.rb +5 -5
- data/lib/rubycritic/report_generators/reporter.rb +44 -0
- data/lib/rubycritic/report_generators/templates/index.html.erb +14 -0
- data/lib/rubycritic/report_generators/templates/layouts/application.html.erb +1 -1
- data/lib/rubycritic/report_generators/templates/smelly_line.html.erb +1 -1
- data/lib/rubycritic/revision_comparator.rb +55 -0
- data/lib/rubycritic/smell.rb +16 -0
- data/lib/rubycritic/smells_status_setter.rb +27 -0
- data/lib/rubycritic/smelly_pathnames_serializer.rb +34 -0
- data/lib/rubycritic/source_control_systems/git.rb +38 -0
- data/lib/rubycritic/source_control_systems/source_control_system.rb +42 -0
- data/lib/rubycritic/source_locator.rb +3 -2
- data/lib/rubycritic/version.rb +1 -1
- data/test/lib/rubycritic/metric_adapters/flog_adapter_test.rb +2 -2
- data/test/lib/rubycritic/metric_adapters/reek_adapter_test.rb +3 -3
- data/test/lib/rubycritic/smell_test.rb +12 -7
- data/test/lib/rubycritic/smells_array_test.rb +28 -0
- data/test/lib/rubycritic/smells_status_setter_test.rb +22 -0
- data/test/lib/rubycritic/source_control_systems/source_control_system_test.rb +26 -0
- data/test/lib/rubycritic/source_locator_test.rb +7 -1
- data/test/samples/location/file_with_different_extension.py +0 -0
- data/test/samples/location/file_with_no_extension +0 -0
- metadata +22 -3
- data/lib/rubycritic/report_generators/report_generator.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ebaa6d00a861b24f55c474cec020a8377a7e392
|
4
|
+
data.tar.gz: 5cc6f6804dd52505d93e65e1faab58429fc1f168
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 586b8ad529ef714157aa4c95c5c69edf6e0c4c66a6a392763168af534845febb273bdcb6ecebcc04122d86f2d176ec6bd9afa86a6af6be0382630b65853f8b85
|
7
|
+
data.tar.gz: 0ac6a82d16c51b59958a32d6e55a76d255c55fd47080c7951c2be1ce43b6f9becbefdf338a2a16fd18f31d4ba5a2adafb907acffdda0f972914507941431e69d
|
data/lib/rubycritic.rb
CHANGED
@@ -1,22 +1,26 @@
|
|
1
1
|
require "rubycritic/source_locator"
|
2
|
-
require "rubycritic/
|
3
|
-
require "rubycritic/smell_adapters/reek"
|
2
|
+
require "rubycritic/analysers_runner"
|
4
3
|
require "rubycritic/smells_aggregator"
|
5
|
-
require "rubycritic/
|
4
|
+
require "rubycritic/source_control_systems/source_control_system"
|
5
|
+
require "rubycritic/revision_comparator"
|
6
|
+
require "rubycritic/report_generators/reporter"
|
6
7
|
|
7
8
|
module Rubycritic
|
8
9
|
|
9
10
|
class Rubycritic
|
10
|
-
def initialize(
|
11
|
-
@source = SourceLocator.new(
|
12
|
-
|
13
|
-
analyser = Analyser::Reek.new(@source.paths)
|
14
|
-
smell_adapters = [ SmellAdapter::Reek.new(analyser) ]
|
15
|
-
@aggregator = SmellsAggregator.new(smell_adapters)
|
11
|
+
def initialize(dirs)
|
12
|
+
@source = SourceLocator.new(dirs)
|
13
|
+
@source_control_system = SourceControlSystem.create
|
16
14
|
end
|
17
15
|
|
18
16
|
def critique
|
19
|
-
|
17
|
+
if @source_control_system.has_revision?
|
18
|
+
smelly_pathnames = RevisionComparator.new(@source.paths, @source_control_system).compare
|
19
|
+
else
|
20
|
+
smell_adapters = AnalysersRunner.new(@source.paths).run
|
21
|
+
smelly_pathnames = SmellsAggregator.new(smell_adapters).smelly_pathnames
|
22
|
+
end
|
23
|
+
Reporter.new(@source.pathnames, smelly_pathnames).generate_report
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "rubycritic/analysers/reek"
|
2
|
+
require "rubycritic/smell_adapters/reek"
|
3
|
+
|
4
|
+
module Rubycritic
|
5
|
+
|
6
|
+
class AnalysersRunner
|
7
|
+
ANALYSERS = ["Reek"]
|
8
|
+
|
9
|
+
def initialize(paths)
|
10
|
+
@paths = paths
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
smell_adapters
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def smell_adapters
|
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)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Rubycritic
|
2
|
+
|
3
|
+
class BaseGenerator
|
4
|
+
REPORT_DIR = File.expand_path("tmp/rubycritic", Dir.getwd)
|
5
|
+
TEMPLATES_DIR = File.expand_path("../templates", __FILE__)
|
6
|
+
|
7
|
+
def file_pathname
|
8
|
+
File.join(file_directory, file_name)
|
9
|
+
end
|
10
|
+
|
11
|
+
def file_directory
|
12
|
+
raise NotImplementedError.new("You must implement the file_directory method.")
|
13
|
+
end
|
14
|
+
|
15
|
+
def file_name
|
16
|
+
raise NotImplementedError.new("You must implement the file_name method.")
|
17
|
+
end
|
18
|
+
|
19
|
+
def render
|
20
|
+
raise NotImplementedError.new("You must implement the render file_name method.")
|
21
|
+
end
|
22
|
+
|
23
|
+
def stylesheet_path
|
24
|
+
File.join(REPORT_DIR, "assets/stylesheets/application.css")
|
25
|
+
end
|
26
|
+
|
27
|
+
def index_path
|
28
|
+
File.join(REPORT_DIR, "index.html")
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_binding
|
32
|
+
binding
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -1,12 +1,11 @@
|
|
1
1
|
require "erb"
|
2
|
+
require "rubycritic/report_generators/base_generator"
|
2
3
|
require "rubycritic/report_generators/line_generator"
|
3
4
|
|
4
5
|
module Rubycritic
|
5
6
|
|
6
|
-
class FileGenerator
|
7
|
+
class FileGenerator < BaseGenerator
|
7
8
|
LINE_NUMBER_OFFSET = 1
|
8
|
-
REPORT_DIR = File.expand_path("tmp/rubycritic", Dir.getwd)
|
9
|
-
TEMPLATES_DIR = File.expand_path("../templates", __FILE__)
|
10
9
|
FILE_TEMPLATE = ERB.new(File.read(File.join(TEMPLATES_DIR, "file.html.erb")))
|
11
10
|
LAYOUT_TEMPLATE = ERB.new(File.read(File.join(TEMPLATES_DIR, "layouts", "application.html.erb")))
|
12
11
|
|
@@ -15,42 +14,27 @@ module Rubycritic
|
|
15
14
|
@smells = smells
|
16
15
|
end
|
17
16
|
|
18
|
-
def file_pathname
|
19
|
-
File.join(file_directory, file_name)
|
20
|
-
end
|
21
|
-
|
22
17
|
def file_directory
|
23
18
|
File.join(REPORT_DIR, File.dirname(@pathname))
|
24
19
|
end
|
25
20
|
|
26
21
|
def file_name
|
27
|
-
"#{
|
28
|
-
end
|
29
|
-
|
30
|
-
def output
|
31
|
-
output ||= file_content
|
22
|
+
"#{analysed_file_name}.html"
|
32
23
|
end
|
33
24
|
|
34
|
-
def
|
35
|
-
|
25
|
+
def analysed_file_name
|
26
|
+
@pathname.basename.sub_ext('').to_s
|
36
27
|
end
|
37
28
|
|
38
|
-
def
|
39
|
-
binding
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def file_content
|
29
|
+
def render
|
45
30
|
file_code = ""
|
46
31
|
File.readlines(@pathname).each.with_index(LINE_NUMBER_OFFSET) do |line_text, line_number|
|
47
32
|
location = Location.new(@pathname, line_number)
|
48
33
|
line_smells = @smells.select { |smell| smell.located_in?(location) }
|
49
|
-
file_code << LineGenerator.new(line_text, line_number, line_smells).
|
34
|
+
file_code << LineGenerator.new(line_text, line_number, line_smells).render
|
50
35
|
end
|
51
36
|
|
52
37
|
file_body = FILE_TEMPLATE.result(self.get_binding { file_code })
|
53
|
-
|
54
38
|
LAYOUT_TEMPLATE.result(self.get_binding { file_body })
|
55
39
|
end
|
56
40
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "erb"
|
2
|
+
require "rubycritic/report_generators/base_generator"
|
3
|
+
|
4
|
+
module Rubycritic
|
5
|
+
|
6
|
+
class IndexGenerator < BaseGenerator
|
7
|
+
INDEX_TEMPLATE = ERB.new(File.read(File.join(TEMPLATES_DIR, "index.html.erb")))
|
8
|
+
LAYOUT_TEMPLATE = ERB.new(File.read(File.join(TEMPLATES_DIR, "layouts", "application.html.erb")))
|
9
|
+
|
10
|
+
def initialize(file_generators)
|
11
|
+
@file_generators = file_generators.sort { |a, b| a.analysed_file_name <=> b.analysed_file_name }
|
12
|
+
end
|
13
|
+
|
14
|
+
def file_directory
|
15
|
+
REPORT_DIR
|
16
|
+
end
|
17
|
+
|
18
|
+
def file_name
|
19
|
+
"index.html"
|
20
|
+
end
|
21
|
+
|
22
|
+
def render
|
23
|
+
index_body = INDEX_TEMPLATE.result(self.get_binding)
|
24
|
+
LAYOUT_TEMPLATE.result(self.get_binding { index_body })
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
|
-
require "cgi"
|
2
1
|
require "erb"
|
2
|
+
require "rubycritic/report_generators/base_generator"
|
3
|
+
require "cgi"
|
3
4
|
|
4
5
|
module Rubycritic
|
5
6
|
|
6
|
-
class LineGenerator
|
7
|
+
class LineGenerator < BaseGenerator
|
7
8
|
LINE_NUMBER_PADDING = 3
|
8
|
-
TEMPLATES_DIR = File.expand_path("../templates", __FILE__)
|
9
9
|
NORMAL_TEMPLATE = ERB.new(File.read(File.join(TEMPLATES_DIR, "line.html.erb")))
|
10
10
|
SMELLY_TEMPLATE = ERB.new(File.read(File.join(TEMPLATES_DIR, "smelly_line.html.erb")))
|
11
11
|
|
@@ -21,8 +21,8 @@ module Rubycritic
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
25
|
-
@
|
24
|
+
def render
|
25
|
+
@template.result(binding).delete("\n") + "\n"
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "rubycritic/report_generators/base_generator"
|
2
|
+
require "rubycritic/report_generators/file_generator"
|
3
|
+
require "rubycritic/report_generators/index_generator"
|
4
|
+
require "fileutils"
|
5
|
+
|
6
|
+
module Rubycritic
|
7
|
+
|
8
|
+
class Reporter
|
9
|
+
ASSETS_DIR = File.expand_path("../assets", __FILE__)
|
10
|
+
|
11
|
+
def initialize(source_pathnames, smelly_pathnames)
|
12
|
+
@source_pathnames = source_pathnames
|
13
|
+
@smelly_pathnames = smelly_pathnames
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate_report
|
17
|
+
generators.each do |generator|
|
18
|
+
FileUtils.mkdir_p(generator.file_directory)
|
19
|
+
File.open(generator.file_pathname, "w+") do |file|
|
20
|
+
file.write(generator.render)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
FileUtils.cp_r(ASSETS_DIR, BaseGenerator::REPORT_DIR)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def generators
|
29
|
+
file_generators + [index_generator]
|
30
|
+
end
|
31
|
+
|
32
|
+
def index_generator
|
33
|
+
IndexGenerator.new(file_generators)
|
34
|
+
end
|
35
|
+
|
36
|
+
def file_generators
|
37
|
+
@file_generators ||= @source_pathnames.map do |pathname|
|
38
|
+
file_smells = @smelly_pathnames[pathname]
|
39
|
+
FileGenerator.new(pathname, file_smells)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<table>
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<th>Name</th>
|
5
|
+
</tr>
|
6
|
+
</thead>
|
7
|
+
<tbody>
|
8
|
+
<% @file_generators.each do |file_generator| %>
|
9
|
+
<tr>
|
10
|
+
<td><a href="<%= file_generator.file_pathname %>"><%= file_generator.analysed_file_name %></a></td>
|
11
|
+
</tr>
|
12
|
+
<% end %>
|
13
|
+
</tbody>
|
14
|
+
</table>
|
@@ -1 +1 @@
|
|
1
|
-
<div class='smelly'><%= @number %>. <%= @text
|
1
|
+
<div class='smelly'><%= @number %>. <%= @text %><% @smells.each { |smell| %><span class="smell <%= smell.status %>"> # <%= smell %><span><% } %></div>
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "rubycritic/smelly_pathnames_serializer"
|
2
|
+
require "rubycritic/source_locator"
|
3
|
+
require "rubycritic/analysers_runner"
|
4
|
+
require "rubycritic/smells_aggregator"
|
5
|
+
require "rubycritic/smells_status_setter"
|
6
|
+
|
7
|
+
module Rubycritic
|
8
|
+
|
9
|
+
class RevisionComparator
|
10
|
+
SNAPSHOTS_DIR = File.expand_path("tmp/rubycritic/snapshots", Dir.getwd)
|
11
|
+
|
12
|
+
def initialize(paths, source_control_system)
|
13
|
+
@paths = paths
|
14
|
+
@source_control_system = source_control_system
|
15
|
+
end
|
16
|
+
|
17
|
+
def compare
|
18
|
+
SmellsStatusSetter.new(smelly_pathnames_before, smelly_pathnames_now).smelly_pathnames
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def smelly_pathnames_before
|
24
|
+
serializer = SmellyPathnamesSerializer.new(revision_file)
|
25
|
+
if File.file?(revision_file)
|
26
|
+
serializer.load
|
27
|
+
else
|
28
|
+
smelly_pathnames = nil
|
29
|
+
@source_control_system.travel_to_head do
|
30
|
+
smelly_pathnames = smelly_pathnames(paths_of_tracked_files)
|
31
|
+
end
|
32
|
+
serializer.dump(smelly_pathnames)
|
33
|
+
smelly_pathnames
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
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
|
+
def revision_file
|
47
|
+
@revision_file ||= File.join(SNAPSHOTS_DIR, @source_control_system.head_reference)
|
48
|
+
end
|
49
|
+
|
50
|
+
def paths_of_tracked_files
|
51
|
+
SourceLocator.new(["."]).paths
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/lib/rubycritic/smell.rb
CHANGED
@@ -11,6 +11,7 @@ module Rubycritic
|
|
11
11
|
attribute :message
|
12
12
|
attribute :score
|
13
13
|
attribute :type
|
14
|
+
attribute :status
|
14
15
|
|
15
16
|
def pathnames
|
16
17
|
@pathnames ||= locations.map(&:pathname).uniq
|
@@ -20,6 +21,11 @@ module Rubycritic
|
|
20
21
|
locations.any? { |location| location == other_location }
|
21
22
|
end
|
22
23
|
|
24
|
+
def ==(other)
|
25
|
+
self.class == other.class && state == other.state
|
26
|
+
end
|
27
|
+
alias_method :eql?, :==
|
28
|
+
|
23
29
|
def <=>(other)
|
24
30
|
locations <=> other.locations
|
25
31
|
end
|
@@ -27,6 +33,16 @@ module Rubycritic
|
|
27
33
|
def to_s
|
28
34
|
"(#{type}) #{context} #{message}"
|
29
35
|
end
|
36
|
+
|
37
|
+
def hash
|
38
|
+
state.hash
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
def state
|
44
|
+
[@context, @message, @score, @type]
|
45
|
+
end
|
30
46
|
end
|
31
47
|
|
32
48
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Rubycritic
|
2
|
+
|
3
|
+
class SmellsStatusSetter
|
4
|
+
def initialize(smelly_pathnames_before, smelly_pathnames_now)
|
5
|
+
@smelly_pathnames_before = smelly_pathnames_before
|
6
|
+
@smelly_pathnames_now = smelly_pathnames_now
|
7
|
+
end
|
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
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def set_status(smells, status)
|
23
|
+
smells.each { |smell| smell.status = status }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
|
3
|
+
module Rubycritic
|
4
|
+
|
5
|
+
class SmellyPathnamesSerializer
|
6
|
+
def initialize(file_name)
|
7
|
+
@file_name = file_name
|
8
|
+
end
|
9
|
+
|
10
|
+
def load
|
11
|
+
Marshal.load(File.read(@file_name))
|
12
|
+
end
|
13
|
+
|
14
|
+
def dump(smelly_pathnames)
|
15
|
+
create_file_directory
|
16
|
+
# HACK It's not possible to Marshal procs or lambdas.
|
17
|
+
smelly_pathnames.default = []
|
18
|
+
File.open(@file_name, "w+") do |file|
|
19
|
+
Marshal.dump(smelly_pathnames, file)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def create_file_directory
|
26
|
+
FileUtils.mkdir_p(file_directory)
|
27
|
+
end
|
28
|
+
|
29
|
+
def file_directory
|
30
|
+
File.dirname(@file_name)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Rubycritic
|
2
|
+
|
3
|
+
class Git < SourceControlSystem
|
4
|
+
register_system
|
5
|
+
|
6
|
+
def self.supported?
|
7
|
+
`git branch 2>&1` && $?.success?
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.to_s
|
11
|
+
"Git"
|
12
|
+
end
|
13
|
+
|
14
|
+
def has_revision?
|
15
|
+
head_reference && $?.success?
|
16
|
+
end
|
17
|
+
|
18
|
+
def travel_to_head
|
19
|
+
if uncommited_changes?
|
20
|
+
stashed_changes = `git stash` && $?.success?
|
21
|
+
end
|
22
|
+
yield
|
23
|
+
ensure
|
24
|
+
`git stash pop` if stashed_changes
|
25
|
+
end
|
26
|
+
|
27
|
+
def head_reference
|
28
|
+
`git rev-parse --verify HEAD`.chomp
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def uncommited_changes?
|
34
|
+
!`git status --porcelain`.empty?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Rubycritic
|
2
|
+
|
3
|
+
class SourceControlSystem
|
4
|
+
@@systems = []
|
5
|
+
|
6
|
+
def self.register_system
|
7
|
+
@@systems << self
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.create
|
11
|
+
supported_system = systems.detect(&:supported?)
|
12
|
+
if supported_system
|
13
|
+
supported_system.new
|
14
|
+
else
|
15
|
+
raise "Rubycritic requires a #{system_names} repository."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.systems
|
20
|
+
@@systems
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.system_names
|
24
|
+
systems.join(", ")
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_revision?
|
28
|
+
raise NotImplementedError.new("You must implement the has_revision? method.")
|
29
|
+
end
|
30
|
+
|
31
|
+
def travel_to_head
|
32
|
+
raise NotImplementedError.new("You must implement the travel_to_head method.")
|
33
|
+
end
|
34
|
+
|
35
|
+
def head_reference
|
36
|
+
raise NotImplementedError.new("You must implement the head_reference method.")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
require "rubycritic/source_control_systems/git"
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module Rubycritic
|
2
2
|
|
3
3
|
class SourceLocator
|
4
|
-
|
4
|
+
RUBY_EXTENSION = ".rb"
|
5
|
+
RUBY_FILES = File.join("**", "*#{RUBY_EXTENSION}")
|
5
6
|
|
6
7
|
def initialize(dirs)
|
7
8
|
@dirs = dirs
|
@@ -21,7 +22,7 @@ module Rubycritic
|
|
21
22
|
@dirs.map do |path|
|
22
23
|
if File.directory?(path)
|
23
24
|
Pathname.glob(RUBY_FILES)
|
24
|
-
elsif File.exists?(path)
|
25
|
+
elsif File.exists?(path) && File.extname(path) == RUBY_EXTENSION
|
25
26
|
Pathname.new(path)
|
26
27
|
end
|
27
28
|
end.flatten.compact.sort
|
data/lib/rubycritic/version.rb
CHANGED
@@ -4,8 +4,8 @@ require "rubycritic/smell_adapters/flog"
|
|
4
4
|
|
5
5
|
describe Rubycritic::SmellAdapter::Flog do
|
6
6
|
before do
|
7
|
-
|
8
|
-
flog = Rubycritic::Analyser::Flog.new([
|
7
|
+
sample_path = "test/samples/flog/smelly.rb"
|
8
|
+
flog = Rubycritic::Analyser::Flog.new([sample_path])
|
9
9
|
@adapter = Rubycritic::SmellAdapter::Flog.new(flog)
|
10
10
|
end
|
11
11
|
|
@@ -5,8 +5,8 @@ require "rubycritic/smell_adapters/reek"
|
|
5
5
|
describe Rubycritic::SmellAdapter::Reek do
|
6
6
|
context "when analysing a smelly file" do
|
7
7
|
before do
|
8
|
-
|
9
|
-
reek = Rubycritic::Analyser::Reek.new([
|
8
|
+
sample_path = "test/samples/reek/smelly.rb"
|
9
|
+
reek = Rubycritic::Analyser::Reek.new([sample_path])
|
10
10
|
@adapter = Rubycritic::SmellAdapter::Reek.new(reek)
|
11
11
|
end
|
12
12
|
|
@@ -23,7 +23,7 @@ describe Rubycritic::SmellAdapter::Reek do
|
|
23
23
|
context "when analysing a file with smells ignored in config.reek" do
|
24
24
|
before do
|
25
25
|
sample_path = "test/samples/reek/not_smelly.rb"
|
26
|
-
reek = Rubycritic::Analyser::Reek.new(sample_path)
|
26
|
+
reek = Rubycritic::Analyser::Reek.new([sample_path])
|
27
27
|
@adapter = Rubycritic::SmellAdapter::Reek.new(reek)
|
28
28
|
end
|
29
29
|
|
@@ -40,13 +40,6 @@ describe Rubycritic::Smell do
|
|
40
40
|
smell.type.must_equal type
|
41
41
|
end
|
42
42
|
|
43
|
-
it "is sortable" do
|
44
|
-
location1 = Rubycritic::Location.new("./foo", 42)
|
45
|
-
location2 = Rubycritic::Location.new("./bar", 23)
|
46
|
-
location3 = Rubycritic::Location.new("./bar", 16)
|
47
|
-
[location1, location2, location3].sort.must_equal [location3, location2, location1]
|
48
|
-
end
|
49
|
-
|
50
43
|
describe "#located_in?" do
|
51
44
|
it "returns true if the smell has a location that matches the location passed as argument" do
|
52
45
|
location = Rubycritic::Location.new("./foo", "42")
|
@@ -54,4 +47,16 @@ describe Rubycritic::Smell do
|
|
54
47
|
smell.located_in?(location).must_equal true
|
55
48
|
end
|
56
49
|
end
|
50
|
+
|
51
|
+
it "is comparable" do
|
52
|
+
attributes = {
|
53
|
+
:context => "#bar",
|
54
|
+
:message => "This smells",
|
55
|
+
:score => 0,
|
56
|
+
:type => :complexity
|
57
|
+
}
|
58
|
+
smell1 = Rubycritic::Smell.new(attributes)
|
59
|
+
smell2 = Rubycritic::Smell.new(attributes)
|
60
|
+
smell1.must_equal smell2
|
61
|
+
end
|
57
62
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "rubycritic/smell"
|
3
|
+
|
4
|
+
describe "Array of Smells" do
|
5
|
+
it "is sortable" do
|
6
|
+
location1 = Rubycritic::Location.new("./foo", 42)
|
7
|
+
location2 = Rubycritic::Location.new("./bar", 23)
|
8
|
+
location3 = Rubycritic::Location.new("./bar", 16)
|
9
|
+
smell1 = Rubycritic::Smell.new(:locations => [location1])
|
10
|
+
smell2 = Rubycritic::Smell.new(:locations => [location2])
|
11
|
+
smell3 = Rubycritic::Smell.new(:locations => [location3])
|
12
|
+
[smell1, smell2, smell3].sort.must_equal [smell3, smell2, smell1]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "implements set intersection" do
|
16
|
+
smell1 = Rubycritic::Smell.new(:context => "#bar")
|
17
|
+
smell2 = Rubycritic::Smell.new(:context => "#bar")
|
18
|
+
smell3 = Rubycritic::Smell.new(:context => "#foo")
|
19
|
+
([smell1, smell3] & [smell2]).must_equal [smell1]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "implements set union" do
|
23
|
+
smell1 = Rubycritic::Smell.new(:context => "#bar")
|
24
|
+
smell2 = Rubycritic::Smell.new(:context => "#bar")
|
25
|
+
smell3 = Rubycritic::Smell.new(:context => "#foo")
|
26
|
+
([smell1, smell3] | [smell2]).must_equal [smell1, smell3]
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "rubycritic/smell"
|
3
|
+
require "rubycritic/smells_status_setter"
|
4
|
+
|
5
|
+
describe Rubycritic::SmellsStatusSetter do
|
6
|
+
describe "#smelly_pathnames" do
|
7
|
+
before do
|
8
|
+
@smell = Rubycritic::Smell.new(:context => "#bar")
|
9
|
+
@smelly_pathnames = { "file0.rb" => [@smell] }
|
10
|
+
end
|
11
|
+
|
12
|
+
it "marks old smells" do
|
13
|
+
Rubycritic::SmellsStatusSetter.new(@smelly_pathnames, @smelly_pathnames).smelly_pathnames
|
14
|
+
@smell.status.must_equal :old
|
15
|
+
end
|
16
|
+
|
17
|
+
it "marks new smells" do
|
18
|
+
Rubycritic::SmellsStatusSetter.new({}, @smelly_pathnames).smelly_pathnames
|
19
|
+
@smell.status.must_equal :new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "rubycritic/source_control_systems/source_control_system"
|
3
|
+
|
4
|
+
describe Rubycritic::SourceControlSystem do
|
5
|
+
before do
|
6
|
+
Rubycritic::SourceControlSystem.systems.each do |system|
|
7
|
+
system.stubs(:supported?).returns(false)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "::create" do
|
12
|
+
describe "when a source control system is found" do
|
13
|
+
it "creates an instance of that source control system" do
|
14
|
+
Rubycritic::Git.stubs(:supported?).returns(true)
|
15
|
+
system = Rubycritic::SourceControlSystem.create
|
16
|
+
system.must_be_instance_of Rubycritic::Git
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "when no source control system is found" do
|
21
|
+
it "raises an error" do
|
22
|
+
proc { Rubycritic::SourceControlSystem.create }.must_raise RuntimeError
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
require "rubycritic/source_locator"
|
3
|
+
require "pathname"
|
3
4
|
|
4
5
|
describe Rubycritic::SourceLocator do
|
5
6
|
before do
|
@@ -23,10 +24,15 @@ describe Rubycritic::SourceLocator do
|
|
23
24
|
Rubycritic::SourceLocator.new(["."]).paths.must_equal paths
|
24
25
|
end
|
25
26
|
|
26
|
-
it "
|
27
|
+
it "ignores non-existent paths" do
|
27
28
|
paths = ["non_existent_dir1/non_existent_file1.rb", "non_existent_file0.rb"]
|
28
29
|
Rubycritic::SourceLocator.new(paths).paths.must_equal []
|
29
30
|
end
|
31
|
+
|
32
|
+
it "ignores existent paths that do not match the Ruby extension" do
|
33
|
+
paths = ["file_with_no_extension", "file_with_different_extension.py"]
|
34
|
+
Rubycritic::SourceLocator.new(paths).paths.must_equal []
|
35
|
+
end
|
30
36
|
end
|
31
37
|
|
32
38
|
describe "#pathnames" do
|
File without changes
|
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubycritic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guilherme Simoes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: virtus
|
@@ -129,20 +129,29 @@ files:
|
|
129
129
|
- lib/rubycritic/analysers/config.reek
|
130
130
|
- lib/rubycritic/analysers/flog.rb
|
131
131
|
- lib/rubycritic/analysers/reek.rb
|
132
|
+
- lib/rubycritic/analysers_runner.rb
|
132
133
|
- lib/rubycritic/cli.rb
|
133
134
|
- lib/rubycritic/location.rb
|
134
135
|
- lib/rubycritic/report_generators/assets/stylesheets/application.css
|
136
|
+
- lib/rubycritic/report_generators/base_generator.rb
|
135
137
|
- lib/rubycritic/report_generators/file_generator.rb
|
138
|
+
- lib/rubycritic/report_generators/index_generator.rb
|
136
139
|
- lib/rubycritic/report_generators/line_generator.rb
|
137
|
-
- lib/rubycritic/report_generators/
|
140
|
+
- lib/rubycritic/report_generators/reporter.rb
|
138
141
|
- lib/rubycritic/report_generators/templates/file.html.erb
|
142
|
+
- lib/rubycritic/report_generators/templates/index.html.erb
|
139
143
|
- lib/rubycritic/report_generators/templates/layouts/application.html.erb
|
140
144
|
- lib/rubycritic/report_generators/templates/line.html.erb
|
141
145
|
- lib/rubycritic/report_generators/templates/smelly_line.html.erb
|
146
|
+
- lib/rubycritic/revision_comparator.rb
|
142
147
|
- lib/rubycritic/smell.rb
|
143
148
|
- lib/rubycritic/smell_adapters/flog.rb
|
144
149
|
- lib/rubycritic/smell_adapters/reek.rb
|
145
150
|
- lib/rubycritic/smells_aggregator.rb
|
151
|
+
- lib/rubycritic/smells_status_setter.rb
|
152
|
+
- lib/rubycritic/smelly_pathnames_serializer.rb
|
153
|
+
- lib/rubycritic/source_control_systems/git.rb
|
154
|
+
- lib/rubycritic/source_control_systems/source_control_system.rb
|
146
155
|
- lib/rubycritic/source_locator.rb
|
147
156
|
- lib/rubycritic/version.rb
|
148
157
|
- rubycritic.gemspec
|
@@ -151,11 +160,16 @@ files:
|
|
151
160
|
- test/lib/rubycritic/metric_adapters/reek_adapter_test.rb
|
152
161
|
- test/lib/rubycritic/smell_test.rb
|
153
162
|
- test/lib/rubycritic/smells_aggregator_test.rb
|
163
|
+
- test/lib/rubycritic/smells_array_test.rb
|
164
|
+
- test/lib/rubycritic/smells_status_setter_test.rb
|
165
|
+
- test/lib/rubycritic/source_control_systems/source_control_system_test.rb
|
154
166
|
- test/lib/rubycritic/source_locator_test.rb
|
155
167
|
- test/lib/rubycritic/version_test.rb
|
156
168
|
- test/samples/flog/smelly.rb
|
157
169
|
- test/samples/location/dir1/file1.rb
|
158
170
|
- test/samples/location/file0.rb
|
171
|
+
- test/samples/location/file_with_different_extension.py
|
172
|
+
- test/samples/location/file_with_no_extension
|
159
173
|
- test/samples/reek/not_smelly.rb
|
160
174
|
- test/samples/reek/smelly.rb
|
161
175
|
- test/test_helper.rb
|
@@ -189,11 +203,16 @@ test_files:
|
|
189
203
|
- test/lib/rubycritic/metric_adapters/reek_adapter_test.rb
|
190
204
|
- test/lib/rubycritic/smell_test.rb
|
191
205
|
- test/lib/rubycritic/smells_aggregator_test.rb
|
206
|
+
- test/lib/rubycritic/smells_array_test.rb
|
207
|
+
- test/lib/rubycritic/smells_status_setter_test.rb
|
208
|
+
- test/lib/rubycritic/source_control_systems/source_control_system_test.rb
|
192
209
|
- test/lib/rubycritic/source_locator_test.rb
|
193
210
|
- test/lib/rubycritic/version_test.rb
|
194
211
|
- test/samples/flog/smelly.rb
|
195
212
|
- test/samples/location/dir1/file1.rb
|
196
213
|
- test/samples/location/file0.rb
|
214
|
+
- test/samples/location/file_with_different_extension.py
|
215
|
+
- test/samples/location/file_with_no_extension
|
197
216
|
- test/samples/reek/not_smelly.rb
|
198
217
|
- test/samples/reek/smelly.rb
|
199
218
|
- test/test_helper.rb
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require "fileutils"
|
2
|
-
require "rubycritic/report_generators/file_generator"
|
3
|
-
|
4
|
-
module Rubycritic
|
5
|
-
|
6
|
-
class ReportGenerator
|
7
|
-
ASSETS_DIR = File.expand_path("../assets", __FILE__)
|
8
|
-
REPORT_DIR = File.expand_path("tmp/rubycritic", Dir.getwd)
|
9
|
-
|
10
|
-
def initialize(source_pathnames, smelly_pathnames)
|
11
|
-
@source_pathnames = source_pathnames
|
12
|
-
@smelly_pathnames = smelly_pathnames
|
13
|
-
end
|
14
|
-
|
15
|
-
def generate_report
|
16
|
-
FileUtils.mkdir_p(REPORT_DIR)
|
17
|
-
FileUtils.cp_r(ASSETS_DIR, REPORT_DIR)
|
18
|
-
|
19
|
-
@source_pathnames.each do |pathname|
|
20
|
-
file_smells = @smelly_pathnames[pathname]
|
21
|
-
file_generator = FileGenerator.new(pathname, file_smells)
|
22
|
-
|
23
|
-
FileUtils.mkdir_p(file_generator.file_directory)
|
24
|
-
File.open(file_generator.file_pathname, "w+") do |report_file|
|
25
|
-
report_file.write(file_generator.output)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|