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.
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