rubycritic 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rubycritic.rb +14 -10
  3. data/lib/rubycritic/analysers_runner.rb +27 -0
  4. data/lib/rubycritic/report_generators/assets/stylesheets/application.css +8 -0
  5. data/lib/rubycritic/report_generators/base_generator.rb +36 -0
  6. data/lib/rubycritic/report_generators/file_generator.rb +7 -23
  7. data/lib/rubycritic/report_generators/index_generator.rb +28 -0
  8. data/lib/rubycritic/report_generators/line_generator.rb +5 -5
  9. data/lib/rubycritic/report_generators/reporter.rb +44 -0
  10. data/lib/rubycritic/report_generators/templates/index.html.erb +14 -0
  11. data/lib/rubycritic/report_generators/templates/layouts/application.html.erb +1 -1
  12. data/lib/rubycritic/report_generators/templates/smelly_line.html.erb +1 -1
  13. data/lib/rubycritic/revision_comparator.rb +55 -0
  14. data/lib/rubycritic/smell.rb +16 -0
  15. data/lib/rubycritic/smells_status_setter.rb +27 -0
  16. data/lib/rubycritic/smelly_pathnames_serializer.rb +34 -0
  17. data/lib/rubycritic/source_control_systems/git.rb +38 -0
  18. data/lib/rubycritic/source_control_systems/source_control_system.rb +42 -0
  19. data/lib/rubycritic/source_locator.rb +3 -2
  20. data/lib/rubycritic/version.rb +1 -1
  21. data/test/lib/rubycritic/metric_adapters/flog_adapter_test.rb +2 -2
  22. data/test/lib/rubycritic/metric_adapters/reek_adapter_test.rb +3 -3
  23. data/test/lib/rubycritic/smell_test.rb +12 -7
  24. data/test/lib/rubycritic/smells_array_test.rb +28 -0
  25. data/test/lib/rubycritic/smells_status_setter_test.rb +22 -0
  26. data/test/lib/rubycritic/source_control_systems/source_control_system_test.rb +26 -0
  27. data/test/lib/rubycritic/source_locator_test.rb +7 -1
  28. data/test/samples/location/file_with_different_extension.py +0 -0
  29. data/test/samples/location/file_with_no_extension +0 -0
  30. metadata +22 -3
  31. 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: e3254c84987373469b8c33271f81794a5495b7a1
4
- data.tar.gz: 7face22a8c659ef7fb50c701e2ceaab5925c618a
3
+ metadata.gz: 8ebaa6d00a861b24f55c474cec020a8377a7e392
4
+ data.tar.gz: 5cc6f6804dd52505d93e65e1faab58429fc1f168
5
5
  SHA512:
6
- metadata.gz: 3f00535b10889d81455894436c7b79d117a085745fcc6e886dfb9aabf7c53bcb47827d4d1d9ca1a6b596a46e2a4f9b4ca0494b555e7552321f8ac76d887e1671
7
- data.tar.gz: 5fd94e011dd5c5ae34fab83e23d528ec618307ce801fecb87cdf1971be8b32df281ee1c4ea05e12d338ac483a74f84b7566f9fd0ff7943f46661af8bad859496
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/analysers/reek"
3
- require "rubycritic/smell_adapters/reek"
2
+ require "rubycritic/analysers_runner"
4
3
  require "rubycritic/smells_aggregator"
5
- require "rubycritic/report_generators/report_generator"
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(paths)
11
- @source = SourceLocator.new(paths)
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
- ReportGenerator.new(@source.pathnames, @aggregator.smelly_pathnames).generate_report
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
@@ -1,4 +1,12 @@
1
1
  .smelly {
2
2
  display: inline;
3
+ background-color: #FFE7C8;
4
+ }
5
+
6
+ .smell {
3
7
  background-color: #FFC8C8;
4
8
  }
9
+
10
+ .smell.old {
11
+ background-color: #DFDFDF;
12
+ }
@@ -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
- "#{@pathname.basename.sub_ext('')}.html"
28
- end
29
-
30
- def output
31
- output ||= file_content
22
+ "#{analysed_file_name}.html"
32
23
  end
33
24
 
34
- def stylesheet_path
35
- File.join(REPORT_DIR, "assets/stylesheets/application.css")
25
+ def analysed_file_name
26
+ @pathname.basename.sub_ext('').to_s
36
27
  end
37
28
 
38
- def get_binding
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).output
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 output
25
- @output ||= @template.result(binding).delete("\n") + "\n"
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>
@@ -9,7 +9,7 @@
9
9
  <meta name="viewport" content="width=device-width, initial-scale=1">
10
10
  </head>
11
11
  <body>
12
- <h1>RubyCritic</h1>
12
+ <h1><a href="<%= index_path %>">RubyCritic</a></h1>
13
13
 
14
14
  <%= yield %>
15
15
  </body>
@@ -1 +1 @@
1
- <div class='smelly'><%= @number %>. <%= @text %> # <% @smells.each { |smell| %><%= smell %><% } %></div>
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
@@ -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
- RUBY_FILES = File.join("**", "*.rb")
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
@@ -1,3 +1,3 @@
1
1
  module Rubycritic
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -4,8 +4,8 @@ require "rubycritic/smell_adapters/flog"
4
4
 
5
5
  describe Rubycritic::SmellAdapter::Flog do
6
6
  before do
7
- @sample_path = "test/samples/flog/smelly.rb"
8
- flog = Rubycritic::Analyser::Flog.new([@sample_path])
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
- @sample_path = "test/samples/reek/smelly.rb"
9
- reek = Rubycritic::Analyser::Reek.new([@sample_path])
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 "deals with non-existent paths" do
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
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.1
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-18 00:00:00.000000000 Z
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/report_generator.rb
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