rubycritic 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -4
  3. data/bin/rubycritic +2 -0
  4. data/lib/rubycritic/adapters/complexity/flog.rb +8 -6
  5. data/lib/rubycritic/adapters/smell/flay.rb +31 -9
  6. data/lib/rubycritic/adapters/smell/flog.rb +18 -9
  7. data/lib/rubycritic/adapters/smell/reek.rb +12 -5
  8. data/lib/rubycritic/analysers/churn.rb +6 -3
  9. data/lib/rubycritic/analysers/stats.rb +31 -0
  10. data/lib/rubycritic/analysers_runner.rb +13 -19
  11. data/lib/rubycritic/cli.rb +34 -18
  12. data/lib/rubycritic/configuration.rb +7 -1
  13. data/lib/rubycritic/core/analysed_file.rb +27 -1
  14. data/lib/rubycritic/core/location.rb +1 -1
  15. data/lib/rubycritic/core/rating.rb +22 -0
  16. data/lib/rubycritic/core/smell.rb +3 -12
  17. data/lib/rubycritic/files_initializer.rb +15 -0
  18. data/lib/rubycritic/orchestrator.rb +23 -0
  19. data/lib/rubycritic/report_generators/assets/javascripts/application.js +5 -3
  20. data/lib/rubycritic/report_generators/assets/javascripts/jquery.timeago-v1.4.1.js +214 -0
  21. data/lib/rubycritic/report_generators/assets/stylesheets/application.css +87 -2
  22. data/lib/rubycritic/report_generators/code_file.rb +1 -3
  23. data/lib/rubycritic/report_generators/code_index.rb +0 -1
  24. data/lib/rubycritic/report_generators/current_code_file.rb +17 -0
  25. data/lib/rubycritic/report_generators/line.rb +0 -1
  26. data/lib/rubycritic/report_generators/overview.rb +1 -2
  27. data/lib/rubycritic/report_generators/smells_index.rb +0 -1
  28. data/lib/rubycritic/report_generators/templates/code_file.html.erb +28 -1
  29. data/lib/rubycritic/report_generators/templates/code_index.html.erb +6 -2
  30. data/lib/rubycritic/report_generators/templates/layouts/application.html.erb +8 -7
  31. data/lib/rubycritic/report_generators/templates/overview.html.erb +1 -1
  32. data/lib/rubycritic/report_generators/view_helpers.rb +6 -2
  33. data/lib/rubycritic/reporters/main.rb +7 -3
  34. data/lib/rubycritic/reporters/mini.rb +13 -4
  35. data/lib/rubycritic/revision_comparator.rb +15 -16
  36. data/lib/rubycritic/serializer.rb +32 -0
  37. data/lib/rubycritic/smells_status_setter.rb +5 -11
  38. data/lib/rubycritic/source_control_systems/base.rb +60 -0
  39. data/lib/rubycritic/source_control_systems/double.rb +19 -0
  40. data/lib/rubycritic/source_control_systems/git.rb +46 -40
  41. data/lib/rubycritic/turbulence.rb +3 -7
  42. data/lib/rubycritic/version.rb +1 -1
  43. data/lib/rubycritic.rb +1 -7
  44. data/rubycritic.gemspec +1 -0
  45. data/test/lib/rubycritic/adapters/complexity/flog_test.rb +5 -5
  46. data/test/lib/rubycritic/adapters/smell/flay_test.rb +19 -8
  47. data/test/lib/rubycritic/adapters/smell/flog_test.rb +11 -8
  48. data/test/lib/rubycritic/adapters/smell/reek_test.rb +14 -10
  49. data/test/lib/rubycritic/analysers/churn_test.rb +23 -8
  50. data/test/lib/rubycritic/core/analysed_file_test.rb +31 -11
  51. data/test/lib/rubycritic/core/smell_test.rb +13 -20
  52. data/test/lib/rubycritic/smells_status_setter_test.rb +2 -2
  53. data/test/lib/rubycritic/source_control_systems/source_control_system_test.rb +5 -12
  54. data/test/lib/rubycritic/turbulence_test.rb +1 -2
  55. data/test/lib/rubycritic/version_test.rb +1 -0
  56. data/test/samples/flog/{smelly2.rb → complex.rb} +0 -0
  57. data/test/test_helper.rb +1 -0
  58. metadata +27 -17
  59. data/lib/rubycritic/active_support/methods.rb +0 -36
  60. data/lib/rubycritic/analysed_files_builder.rb +0 -36
  61. data/lib/rubycritic/orchestrators/base.rb +0 -27
  62. data/lib/rubycritic/orchestrators/main.rb +0 -14
  63. data/lib/rubycritic/orchestrators/mini.rb +0 -14
  64. data/lib/rubycritic/smells_serializer.rb +0 -32
  65. data/lib/rubycritic/source_control_systems/source_control_system.rb +0 -50
  66. data/test/lib/rubycritic/analysed_files_builder_test.rb +0 -36
  67. data/test/lib/rubycritic/analysers_runner_test.rb +0 -11
  68. data/test/samples/analysers_runner/empty.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 74b9972ae846d78f2a449e831f4f56d5475349d8
4
- data.tar.gz: 737c696e6b0b42393c3b6ddb2a8f6d09f446fed2
3
+ metadata.gz: 68c58782f25f2ad071d05ae5060034e4f2b77832
4
+ data.tar.gz: 61ae75fea93cde03f7e9ab378e363f345eb8f184
5
5
  SHA512:
6
- metadata.gz: b5490faab830e968d3cdef7cdb0f04c1158197c8b738b30f383f9227fbbc102ba17d0276a248007ce7a668d53640cc54410d09c136f3e4ce24d59c1a9c26653e
7
- data.tar.gz: d51c2940dc3a15ec3b6551d35c0ee24f6f7e8ed510e3dc74865301ef59e41cf361511e17a6db14e098e45fbdb188cf9524629ad72a35670c1f98d8f1eae05c4b
6
+ metadata.gz: 15a35a6440ba6536d6989451ec60d0d8037303e93c47049aaa73c05846ea65f22bad0517084510811ed9cfa794acf86f0f5dc512cee37320841cff402fb381ba
7
+ data.tar.gz: 493ebc3d9f648e39ca5869d397dfcd4af1bc5facb5c1a669eda9a358bce67f85c21b93c7781ae8dbce3a9c4a34bdf98b8df788c08964e5214affb957a081edd6
data/README.md CHANGED
@@ -3,7 +3,7 @@ RubyCritic
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/rubycritic.svg)](http://badge.fury.io/rb/rubycritic)
5
5
  [![Build Status](https://travis-ci.org/whitesmith/rubycritic.svg?branch=master)](https://travis-ci.org/whitesmith/rubycritic)
6
- [![Code Climate](https://codeclimate.com/github/whitesmith/rubycritic.png)](https://codeclimate.com/github/whitesmith/rubycritic)
6
+ [![Code Climate](http://img.shields.io/codeclimate/github/whitesmith/rubycritic.svg)](https://codeclimate.com/github/whitesmith/rubycritic)
7
7
 
8
8
  RubyCritic is a gem that wraps around static analysis gems such as [Reek][1]
9
9
  and [Flay][2] to provide a quality report of your Ruby code.
@@ -16,11 +16,11 @@ This gem provides features such as:
16
16
 
17
17
  2. An index of the project files with their respective number of smells:
18
18
 
19
- ![RubyCritic code index screenshot](http://i.imgur.com/Hx2y2cG.png)
19
+ ![RubyCritic code index screenshot](http://i.imgur.com/0ETNrX7.png)
20
20
 
21
21
  3. An index of the smells detected:
22
22
 
23
- ![RubyCritic smells index screenshot](http://i.imgur.com/ogXYIwR.png)
23
+ ![RubyCritic smells index screenshot](http://i.imgur.com/5CpPt9v.png)
24
24
 
25
25
  4. Finally, when analysing code like the following:
26
26
 
@@ -40,7 +40,7 @@ This gem provides features such as:
40
40
 
41
41
  Into something like this:
42
42
 
43
- ![RubyCritic file code screenshot](http://i.imgur.com/88ApcGd.png)
43
+ ![RubyCritic file code screenshot](http://i.imgur.com/KLVrhMm.png)
44
44
 
45
45
  Installation
46
46
  ------------
@@ -80,6 +80,18 @@ Alternatively you can pass `rubycritic` a list of files and directories to check
80
80
  $ rubycritic app lib/foo.rb
81
81
  ```
82
82
 
83
+ By default, RubyCritic generates its report in `tmp/rubycritic`. You can customize the output directory using the `path` option. You can use relative paths:
84
+
85
+ ```bash
86
+ rubycritic --path tmp/custom_dir # outputs to tmp/custom_dir
87
+ ```
88
+
89
+ Or full paths:
90
+
91
+ ```bash
92
+ rubycritic --path $HOME/tmp/custom_dir # outputs to $HOME/tmp/custom_dir
93
+ ```
94
+
83
95
  For a full list of the command-line options run:
84
96
 
85
97
  ```bash
data/bin/rubycritic CHANGED
@@ -1,3 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "rubycritic/cli"
4
+
5
+ exit Rubycritic::Cli.new(ARGV).execute
@@ -1,17 +1,19 @@
1
+ require "rubycritic/analysers/flog"
2
+
1
3
  module Rubycritic
2
4
  module ComplexityAdapter
3
5
 
4
6
  class Flog
5
- def initialize(paths)
6
- @flog = ::Rubycritic::Analyser::Flog.new
7
- @paths = paths
7
+ def initialize(analysed_files)
8
+ @flog = Analyser::Flog.new
9
+ @analysed_files = analysed_files
8
10
  end
9
11
 
10
12
  def complexity
11
- @paths.map do |path|
13
+ @analysed_files.each do |analysed_file|
12
14
  @flog.reset
13
- @flog.flog(path)
14
- @flog.total_score.round
15
+ @flog.flog(analysed_file.path)
16
+ analysed_file.complexity = @flog.total_score.round
15
17
  end
16
18
  end
17
19
  end
@@ -5,25 +5,43 @@ module Rubycritic
5
5
  module SmellAdapter
6
6
 
7
7
  class Flay
8
- def initialize(paths)
9
- @flay = ::Rubycritic::Analyser::Flay.new(paths)
8
+ def initialize(analysed_files)
9
+ @analysed_files = paths_to_analysed_files(analysed_files)
10
+ @flay = Analyser::Flay.new(@analysed_files.keys)
10
11
  end
11
12
 
12
13
  def smells
13
- @flay.hashes.map do |structural_hash, nodes|
14
- create_smell(structural_hash, nodes)
14
+ @flay.hashes.each do |structural_hash, nodes|
15
+ smell = create_smell(structural_hash, nodes)
16
+ nodes.map(&:file).uniq.each do |file|
17
+ @analysed_files[file].smells << smell
18
+ end
19
+
20
+ nodes.each do |node|
21
+ @analysed_files[node.file].duplication += node.mass
22
+ end
15
23
  end
16
24
  end
17
25
 
18
26
  private
19
27
 
28
+ def paths_to_analysed_files(analysed_files)
29
+ paths = {}
30
+ analysed_files.each do |analysed_file|
31
+ paths[analysed_file.path] = analysed_file
32
+ end
33
+ paths
34
+ end
35
+
20
36
  def create_smell(structural_hash, nodes)
37
+ mass = @flay.masses[structural_hash]
21
38
  Smell.new(
22
39
  :locations => smell_locations(nodes),
23
- :context => "#{similarity(structural_hash)} code",
40
+ :context => similarity(structural_hash),
24
41
  :message => "found in #{nodes.size} nodes",
25
- :score => @flay.masses[structural_hash],
26
- :type => "DuplicateCode"
42
+ :score => mass,
43
+ :type => "DuplicateCode",
44
+ :cost => cost(mass)
27
45
  )
28
46
  end
29
47
 
@@ -35,11 +53,15 @@ module Rubycritic
35
53
 
36
54
  def similarity(structural_hash)
37
55
  if @flay.identical[structural_hash]
38
- "Identical"
56
+ "Identical code"
39
57
  else
40
- "Similar"
58
+ "Similar code"
41
59
  end
42
60
  end
61
+
62
+ def cost(mass)
63
+ mass / 25
64
+ end
43
65
  end
44
66
 
45
67
  end
@@ -8,29 +8,38 @@ module Rubycritic
8
8
  HIGH_COMPLEXITY_SCORE_THRESHOLD = 25
9
9
  VERY_HIGH_COMPLEXITY_SCORE_THRESHOLD = 60
10
10
 
11
- def initialize(paths)
12
- @flog = ::Rubycritic::Analyser::Flog.new
13
- @flog.flog(*paths)
11
+ def initialize(analysed_files)
12
+ @flog = Analyser::Flog.new
13
+ @analysed_files = analysed_files
14
14
  end
15
15
 
16
16
  def smells
17
- smells = []
18
- @flog.each_by_score do |class_method, original_score|
19
- score = original_score.round
20
- smells << create_smell(class_method, score) if score >= HIGH_COMPLEXITY_SCORE_THRESHOLD
17
+ @analysed_files.each do |analysed_file|
18
+ add_smells_to(analysed_file)
21
19
  end
22
- smells
23
20
  end
24
21
 
25
22
  private
26
23
 
24
+ def add_smells_to(analysed_file)
25
+ @flog.reset
26
+ @flog.flog(analysed_file.path)
27
+ @flog.each_by_score do |class_method, original_score|
28
+ score = original_score.round
29
+ if score >= HIGH_COMPLEXITY_SCORE_THRESHOLD
30
+ analysed_file.smells << create_smell(class_method, score)
31
+ end
32
+ end
33
+ end
34
+
27
35
  def create_smell(context, score)
28
36
  Smell.new(
29
37
  :locations => smell_locations(context),
30
38
  :context => context,
31
39
  :message => "has a flog score of #{score}",
32
40
  :score => score,
33
- :type => type(score)
41
+ :type => type(score),
42
+ :cost => 0
34
43
  )
35
44
  end
36
45
 
@@ -5,24 +5,31 @@ module Rubycritic
5
5
  module SmellAdapter
6
6
 
7
7
  class Reek
8
- def initialize(paths)
9
- @reek = ::Rubycritic::Analyser::Reek.new(paths)
8
+ def initialize(analysed_files)
9
+ @analysed_files = analysed_files
10
10
  end
11
11
 
12
12
  def smells
13
- @reek.smells.map do |smell|
14
- create_smell(smell)
13
+ @analysed_files.each do |analysed_file|
14
+ add_smells_to(analysed_file)
15
15
  end
16
16
  end
17
17
 
18
18
  private
19
19
 
20
+ def add_smells_to(analysed_file)
21
+ Analyser::Reek.new(analysed_file.path).smells.each do |smell|
22
+ analysed_file.smells << create_smell(smell)
23
+ end
24
+ end
25
+
20
26
  def create_smell(smell)
21
27
  Smell.new(
22
28
  :locations => smell_locations(smell.source, smell.lines),
23
29
  :context => smell.context,
24
30
  :message => smell.message,
25
- :type => smell.subclass
31
+ :type => smell.subclass,
32
+ :cost => 0
26
33
  )
27
34
  end
28
35
 
@@ -2,13 +2,16 @@ module Rubycritic
2
2
  module Analyser
3
3
 
4
4
  class Churn
5
- def initialize(paths, source_control_system)
6
- @paths = paths
5
+ def initialize(analysed_files, source_control_system)
6
+ @analysed_files = analysed_files
7
7
  @source_control_system = source_control_system
8
8
  end
9
9
 
10
10
  def churn
11
- @paths.map { |path| @source_control_system.revisions_count(path) }
11
+ @analysed_files.each do |analysed_file|
12
+ analysed_file.churn = @source_control_system.revisions_count(analysed_file.path)
13
+ analysed_file.committed_at = @source_control_system.date_of_last_commit(analysed_file.path)
14
+ end
12
15
  end
13
16
  end
14
17
 
@@ -0,0 +1,31 @@
1
+ require "code_analyzer"
2
+
3
+ module Rubycritic
4
+ module Analyser
5
+
6
+ class Stats
7
+ def initialize(analysed_files)
8
+ @analysed_files = analysed_files
9
+ end
10
+
11
+ def stats
12
+ @analysed_files.each do |analysed_file|
13
+ analysed_file.methods_count = methods_count(analysed_file.path)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def methods_count(path)
20
+ content = File.read(path)
21
+ node = parse_content(content)
22
+ node.grep_nodes_count(sexp_type: [:def, :defs])
23
+ end
24
+
25
+ def parse_content(content)
26
+ Sexp.from_array(Ripper::SexpBuilder.new(content).parse)[1]
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -1,33 +1,27 @@
1
- require "rubycritic/active_support/methods"
2
1
  require "rubycritic/adapters/smell/flay"
3
2
  require "rubycritic/adapters/smell/flog"
4
3
  require "rubycritic/adapters/smell/reek"
4
+ require "rubycritic/adapters/complexity/flog"
5
+ require "rubycritic/analysers/churn"
6
+ require "rubycritic/analysers/stats"
5
7
 
6
8
  module Rubycritic
7
9
 
8
10
  class AnalysersRunner
9
- include ActiveSupport
11
+ SMELL_ANALYSERS = [SmellAdapter::Flay, SmellAdapter::Flog, SmellAdapter::Reek]
10
12
 
11
- ANALYSERS = ["Flay", "Flog", "Reek"]
12
-
13
- def initialize(paths)
14
- @paths = paths
15
- end
16
-
17
- def smells
18
- aggregate_smells(smell_adapters)
13
+ def initialize(analysed_files, source_control_system)
14
+ @analysed_files = analysed_files
15
+ @source_control_system = source_control_system
19
16
  end
20
17
 
21
- private
22
-
23
- def smell_adapters
24
- ANALYSERS.map do |analyser_name|
25
- constantize("Rubycritic::SmellAdapter::#{analyser_name}").new(@paths)
18
+ def run
19
+ SMELL_ANALYSERS.map do |analyser|
20
+ analyser.new(@analysed_files).smells
26
21
  end
27
- end
28
-
29
- def aggregate_smells(smell_adapters)
30
- smell_adapters.flat_map(&:smells)
22
+ ComplexityAdapter::Flog.new(@analysed_files).complexity
23
+ Analyser::Churn.new(@analysed_files, @source_control_system).churn
24
+ Analyser::Stats.new(@analysed_files).stats
31
25
  end
32
26
  end
33
27
 
@@ -1,30 +1,46 @@
1
1
  require "optparse"
2
2
  require "rubycritic"
3
- require "rubycritic/orchestrators/main"
3
+ require "rubycritic/reporters/main"
4
4
 
5
5
  module Rubycritic
6
6
 
7
- OptionParser.new do |opts|
8
- opts.banner = "Usage: rubycritic [options] [paths]"
7
+ class Cli
8
+ STATUS_SUCCESS = 0
9
9
 
10
- opts.on("-p", "--path [PATH]", "Set path where report will be saved (tmp/rubycritic by default)") do |path|
11
- configuration.root = path
10
+ def initialize(argv)
11
+ @argv = argv
12
+ @argv << "." if @argv.empty?
13
+ @main_command = true
12
14
  end
13
15
 
14
- opts.on_tail("-v", "--version", "Show gem's version") do
15
- require "rubycritic/version"
16
- puts VERSION
17
- exit 0
18
- end
16
+ def execute
17
+ OptionParser.new do |opts|
18
+ opts.banner = "Usage: rubycritic [options] [paths]"
19
19
 
20
- opts.on_tail("-h", "--help", "Show this message") do
21
- puts opts
22
- exit 0
23
- end
24
- end.parse!
20
+ opts.on("-p", "--path [PATH]", "Set path where report will be saved (tmp/rubycritic by default)") do |path|
21
+ ::Rubycritic.configuration.root = path
22
+ end
23
+
24
+ opts.on_tail("-v", "--version", "Show gem's version") do
25
+ require "rubycritic/version"
26
+ puts "RubyCritic #{VERSION}"
27
+ @main_command = false
28
+ end
25
29
 
26
- ARGV << "." if ARGV.empty?
27
- puts "New critique at #{Orchestrator::Main.new.critique(ARGV)}"
28
- exit 0
30
+ opts.on_tail("-h", "--help", "Show this message") do
31
+ puts opts
32
+ @main_command = false
33
+ end
34
+ end.parse!(@argv)
35
+
36
+ if @main_command
37
+ analysed_files = Orchestrator.new.critique(@argv)
38
+ report_location = Reporter::Main.new(analysed_files).generate_report
39
+ puts "New critique at #{report_location}"
40
+ end
41
+
42
+ STATUS_SUCCESS
43
+ end
44
+ end
29
45
 
30
46
  end
@@ -1,3 +1,5 @@
1
+ require "pathname"
2
+
1
3
  module Rubycritic
2
4
  def self.configuration
3
5
  @configuration ||= Configuration.new
@@ -11,7 +13,11 @@ module Rubycritic
11
13
  end
12
14
 
13
15
  def root=(path)
14
- @root = File.expand_path(path)
16
+ @root = if Pathname(path).relative?
17
+ File.expand_path(path)
18
+ else
19
+ path
20
+ end
15
21
  end
16
22
  end
17
23
  end
@@ -1,4 +1,5 @@
1
1
  require "virtus"
2
+ require "rubycritic/core/rating"
2
3
 
3
4
  module Rubycritic
4
5
 
@@ -8,15 +9,40 @@ module Rubycritic
8
9
  attribute :pathname
9
10
  attribute :smells
10
11
  attribute :churn
12
+ attribute :committed_at
11
13
  attribute :complexity
14
+ attribute :duplication
15
+ attribute :methods_count
12
16
 
13
17
  def name
14
- pathname.basename.sub_ext("").to_s
18
+ @name ||= pathname.basename.sub_ext("").to_s
19
+ end
20
+
21
+ def path
22
+ @path ||= pathname.to_s
23
+ end
24
+
25
+ def cost
26
+ @cost ||= smells.map(&:cost).inject(0, :+) + (complexity / 25)
27
+ end
28
+
29
+ def rating
30
+ @rating ||= Rating.from_cost(cost)
31
+ end
32
+
33
+ def complexity_per_method
34
+ complexity.fdiv(methods_count).round(1)
35
+ rescue ZeroDivisionError
36
+ "N/A"
15
37
  end
16
38
 
17
39
  def has_smells?
18
40
  !smells.empty?
19
41
  end
42
+
43
+ def smells_at_location(location)
44
+ smells.select { |smell| smell.at_location?(location) }
45
+ end
20
46
  end
21
47
 
22
48
  end
@@ -19,7 +19,7 @@ module Rubycritic
19
19
  end
20
20
 
21
21
  def ==(other)
22
- self.class == other.class && state == other.state
22
+ state == other.state
23
23
  end
24
24
 
25
25
  def <=>(other)
@@ -0,0 +1,22 @@
1
+ module Rubycritic
2
+
3
+ class Rating
4
+ def self.from_cost(cost)
5
+ if cost <= 2 then new("A")
6
+ elsif cost <= 4 then new("B")
7
+ elsif cost <= 8 then new("C")
8
+ elsif cost <= 16 then new("D")
9
+ else new("F")
10
+ end
11
+ end
12
+
13
+ def initialize(letter)
14
+ @letter = letter
15
+ end
16
+
17
+ def to_s
18
+ @letter
19
+ end
20
+ end
21
+
22
+ end
@@ -7,15 +7,12 @@ module Rubycritic
7
7
  include Virtus.model
8
8
 
9
9
  attribute :context
10
+ attribute :cost
10
11
  attribute :locations
11
12
  attribute :message
12
13
  attribute :score
13
- attribute :type
14
14
  attribute :status
15
-
16
- def at_pathname?(other_pathname)
17
- pathnames.any? { |pathname| pathname == other_pathname }
18
- end
15
+ attribute :type
19
16
 
20
17
  def at_location?(other_location)
21
18
  locations.any? { |location| location == other_location }
@@ -26,7 +23,7 @@ module Rubycritic
26
23
  end
27
24
 
28
25
  def ==(other)
29
- self.class == other.class && state == other.state
26
+ state == other.state
30
27
  end
31
28
  alias_method :eql?, :==
32
29
 
@@ -43,12 +40,6 @@ module Rubycritic
43
40
  def state
44
41
  [@context, @message, @score, @type]
45
42
  end
46
-
47
- private
48
-
49
- def pathnames
50
- @pathnames ||= locations.map(&:pathname).uniq
51
- end
52
43
  end
53
44
 
54
45
  end
@@ -0,0 +1,15 @@
1
+ require "rubycritic/source_locator"
2
+ require "rubycritic/core/analysed_file"
3
+
4
+ module Rubycritic
5
+
6
+ module FilesInitializer
7
+ def self.init(paths)
8
+ source = SourceLocator.new(paths)
9
+ source.pathnames.map do |pathname|
10
+ AnalysedFile.new(:pathname => pathname, :smells => [], :duplication => 0)
11
+ end
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,23 @@
1
+ require "rubycritic/source_control_systems/base"
2
+ require "rubycritic/files_initializer"
3
+ require "rubycritic/analysers_runner"
4
+ require "rubycritic/revision_comparator"
5
+
6
+ module Rubycritic
7
+
8
+ class Orchestrator
9
+ def initialize
10
+ @source_control_system = SourceControlSystem::Base.create
11
+ end
12
+
13
+ def critique(paths)
14
+ analysed_files = FilesInitializer.init(paths)
15
+ AnalysersRunner.new(analysed_files, @source_control_system).run
16
+ if @source_control_system.has_revision?
17
+ RevisionComparator.new(analysed_files, @source_control_system).set_statuses
18
+ end
19
+ analysed_files
20
+ end
21
+ end
22
+
23
+ end
@@ -8,8 +8,8 @@ function emphasizeLineFromFragment() {
8
8
 
9
9
  $(".js-file-code").on("click", ".js-smell-location", emphasizeLineFromHref);
10
10
 
11
- function emphasizeLineFromHref() {
12
- if (hrefTargetIsOnCurrentPage(this)) {
11
+ function emphasizeLineFromHref(event) {
12
+ if (hrefTargetIsOnCurrentPage(this) && !event.ctrlKey) {
13
13
  $(".js-file-code li").removeClass("highlight");
14
14
  var lineId = "#" + this.href.split("#")[1];
15
15
  emphasizeLine(lineId);
@@ -52,6 +52,8 @@ $("#js-index-table")
52
52
  })
53
53
  .floatThead(); // Make table headers stick to the top when scrolling
54
54
 
55
+ $(".js-timeago").timeago();
56
+
55
57
  $("#js-chart-container").highcharts({
56
58
  chart: {
57
59
  type: "scatter",
@@ -97,6 +99,6 @@ $("#js-chart-container").highcharts({
97
99
  series: [{
98
100
  showInLegend: false,
99
101
  color: "steelblue",
100
- data: turbulence_data
102
+ data: turbulenceData
101
103
  }]
102
104
  });