rubycritic 0.0.14 → 0.0.15

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 (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
  });