rubycritic 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +593 -0
  3. data/.travis.yml +1 -1
  4. data/CHANGELOG.md +7 -0
  5. data/CONTRIBUTING.md +17 -15
  6. data/README.md +15 -4
  7. data/Rakefile +9 -6
  8. data/bin/rubycritic +2 -2
  9. data/lib/rubycritic.rb +21 -1
  10. data/lib/rubycritic/analysers/churn.rb +4 -2
  11. data/lib/rubycritic/analysers/helpers/ast_node.rb +4 -8
  12. data/lib/rubycritic/analysers/helpers/methods_counter.rb +2 -5
  13. data/lib/rubycritic/analysers/helpers/modules_locator.rb +2 -5
  14. data/lib/rubycritic/analysers/helpers/parser.rb +12 -0
  15. data/lib/rubycritic/analysers/helpers/reek.rb +6 -2
  16. data/lib/rubycritic/analysers/smells/reek.rb +1 -1
  17. data/lib/rubycritic/analysers_runner.rb +13 -7
  18. data/lib/rubycritic/cli/application.rb +24 -0
  19. data/lib/rubycritic/cli/options.rb +57 -0
  20. data/lib/rubycritic/commands/ci.rb +28 -0
  21. data/lib/rubycritic/commands/default.rb +30 -0
  22. data/lib/rubycritic/commands/help.rb +13 -0
  23. data/lib/rubycritic/commands/version.rb +11 -0
  24. data/lib/rubycritic/configuration.rb +19 -14
  25. data/lib/rubycritic/core/analysed_module.rb +1 -1
  26. data/lib/rubycritic/core/smell.rb +1 -1
  27. data/lib/rubycritic/report_generators/base.rb +1 -1
  28. data/lib/rubycritic/report_generators/line.rb +1 -1
  29. data/lib/rubycritic/report_generators/smells_index.rb +1 -0
  30. data/lib/rubycritic/report_generators/templates/code_file.html.erb +1 -1
  31. data/lib/rubycritic/report_generators/templates/smells_index.html.erb +6 -2
  32. data/lib/rubycritic/report_generators/templates/smelly_line.html.erb +1 -1
  33. data/lib/rubycritic/report_generators/view_helpers.rb +4 -4
  34. data/lib/rubycritic/reporters/base.rb +1 -1
  35. data/lib/rubycritic/revision_comparator.rb +14 -14
  36. data/lib/rubycritic/source_control_systems/base.rb +9 -32
  37. data/lib/rubycritic/source_control_systems/double.rb +6 -7
  38. data/lib/rubycritic/source_control_systems/git.rb +10 -16
  39. data/lib/rubycritic/source_control_systems/mercurial.rb +29 -0
  40. data/lib/rubycritic/source_locator.rb +4 -5
  41. data/lib/rubycritic/version.rb +1 -1
  42. data/rubycritic.gemspec +4 -3
  43. data/test/lib/rubycritic/analysers/churn_test.rb +5 -5
  44. data/test/lib/rubycritic/analysers/smells/flay_test.rb +1 -1
  45. data/test/lib/rubycritic/configuration_test.rb +8 -7
  46. data/test/lib/rubycritic/core/analysed_module_test.rb +2 -2
  47. data/test/lib/rubycritic/core/smell_test.rb +2 -2
  48. data/test/lib/rubycritic/source_control_systems/{source_control_system_test.rb → base_test.rb} +1 -1
  49. data/test/lib/rubycritic/source_control_systems/double_test.rb +11 -0
  50. data/test/lib/rubycritic/source_control_systems/git_test.rb +13 -0
  51. data/test/lib/rubycritic/source_control_systems/interfaces/basic.rb +7 -0
  52. data/test/lib/rubycritic/source_control_systems/interfaces/time_travel.rb +7 -0
  53. data/test/lib/rubycritic/source_control_systems/mercurial_test.rb +11 -0
  54. data/test/lib/rubycritic/source_locator_test.rb +8 -2
  55. data/test/test_helper.rb +29 -0
  56. metadata +49 -13
  57. data/lib/rubycritic/cli.rb +0 -46
  58. data/lib/rubycritic/modules_initializer.rb +0 -14
  59. data/lib/rubycritic/orchestrator.rb +0 -23
@@ -5,6 +5,6 @@ rvm:
5
5
  - 2.0.0
6
6
  - 2.1
7
7
  - jruby
8
- - rbx-2.2.10
8
+ - rbx-2
9
9
 
10
10
  script: "bundle exec rake"
@@ -1,3 +1,10 @@
1
+ # 1.2.0 / 2014-12-27
2
+
3
+ * [FEATURE] Add CI mode that only analyses the last commit
4
+ * [FEATURE] Add partial support for Mercurial
5
+ * [FEATURE] Allow using Rubycritic programatically
6
+ * [CHANGE] Update to Reek 1.6.0 (from 1.3.8)
7
+
1
8
  # 1.1.1 / 2014-07-29
2
9
 
3
10
  * [BUGFIX] Analyse only the files whose paths are specified in the CLI
@@ -26,28 +26,30 @@ If you want to squash a bug or add a new feature, please:
26
26
  Make exactly as many commits as you need.
27
27
  Each commit should do one thing and one thing only. For example, all whitespace fixes should be relegated to a single commit.
28
28
 
29
- 7. Write descriptive commit messages, in accordance with [these guidelines][1].
29
+ 7. Write [descriptive commit messages].
30
30
 
31
- 8. [Hide the sausage making][3]. Squash, split and reorder commits if necessary (`git rebase -i`).
32
- For a more in-depth look at interactive rebasing, be sure to check [how to rewrite history][4].
31
+ 8. Push the branch to GitHub (`git push origin my-new-feature`).
33
32
 
34
- 9. Push the branch to GitHub (`git push origin my-new-feature`).
33
+ 9. [Create a Pull Request] and send it to be merged with the master branch.
35
34
 
36
- 10. Create a new [Pull Request][5] and send it to be merged with the master branch.
35
+ 10. After your code is reviewed, [hide the sausage making]. Squash, split and reorder commits if necessary (`git rebase -i`).
36
+ For a more in-depth look at interactive rebasing, be sure to check [how to rewrite history].
37
37
 
38
38
  Improving the Documentation
39
39
  ---------------------------
40
40
 
41
- You are welcome to clarify how something works or simply fix a typo. Please include `[ci skip]` on a new line in each of your commit messages. This will signal [Travis][2] that running the test suite is not necessary for these changes.
41
+ You are welcome to clarify how something works or simply fix a typo. Please include `[ci skip]` on a new line in each of your commit messages. This will signal [Travis] that running the test suite is not necessary for these changes.
42
42
 
43
43
  Reporting a Bug
44
44
  ---------------
45
45
 
46
46
  If you are experiencing unexpected behavior and, after having read Rubycritic's documentation, are convinced this behavior is a bug, please:
47
47
 
48
- 1. Search the [issues tracker][6] to see if it was already reported / fixed.
48
+ 1. Search the [issues tracker] to see if it was already reported / fixed.
49
49
 
50
- 2. Include the Ruby and RubyCritic versions in your report. Here's a little table to help you out:
50
+ 2. [Create a new issue].
51
+
52
+ 3. Include the Ruby and RubyCritic versions in your report. Here's a little table to help you out:
51
53
 
52
54
  ```
53
55
  | | Version |
@@ -58,11 +60,11 @@ If you are experiencing unexpected behavior and, after having read Rubycritic's
58
60
 
59
61
  The more information you provide, the easier it will be to track down the issue and fix it.
60
62
 
61
- 3. Create a new issue.
62
63
 
63
- [1]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
64
- [2]: https://travis-ci.org
65
- [3]: http://sethrobertson.github.io/GitBestPractices/#sausage
66
- [4]: http://git-scm.com/book/en/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages
67
- [5]: https://help.github.com/articles/creating-a-pull-request
68
- [6]: https://github.com/whitesmith/rubycritic/search?type=Issues
64
+ [descriptive commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
65
+ [Create a pull request]: https://help.github.com/articles/creating-a-pull-request
66
+ [hide the sausage making]: http://sethrobertson.github.io/GitBestPractices/#sausage
67
+ [how to rewrite history]: http://git-scm.com/book/en/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages
68
+ [Travis]: https://travis-ci.org
69
+ [issues tracker]: https://github.com/whitesmith/rubycritic/search?type=Issues
70
+ [Create a new issue]: https://github.com/whitesmith/rubycritic/issues/new
data/README.md CHANGED
@@ -86,10 +86,11 @@ For a full list of the command-line options run:
86
86
  $ rubycritic --help
87
87
  ```
88
88
 
89
- | Command flag | Description |
90
- |--------------------------|-----------------------------------------|
91
- | `-v/--version` | Displays the current version and exits. |
92
- | `-p/--path` | Customizes the output directory. |
89
+ | Command flag | Description |
90
+ |--------------------------|-------------------------------------------------------|
91
+ | `-v/--version` | Displays the current version and exits |
92
+ | `-p/--path` | Sets the output directory (tmp/rubycritic by default) |
93
+ | `-m/--mode-ci` | Uses CI mode (faster, but only analyses last commit) |
93
94
 
94
95
  Alternative Usage Methods
95
96
  -------------------------
@@ -109,6 +110,13 @@ Similarly, Pull Requests that improve the look and feel of the gem, that tweak t
109
110
 
110
111
  See RubyCritic's [contributing guidelines](CONTRIBUTING.md) about how to proceed.
111
112
 
113
+ Credits
114
+ -------
115
+
116
+ ![Whitesmith](http://i.imgur.com/Si2l3kd.png)
117
+
118
+ RubyCritic is maintained and funded by [Whitesmith][9]. Tweet your questions or suggestions to [@glitchdout][10] or [@Whitesmithco][11].
119
+
112
120
  [1]: https://github.com/troessner/reek
113
121
  [2]: https://github.com/seattlerb/flay
114
122
  [3]: https://github.com/seattlerb/flog
@@ -117,3 +125,6 @@ See RubyCritic's [contributing guidelines](CONTRIBUTING.md) about how to proceed
117
125
  [6]: https://github.com/whitesmith/rubycritic/wiki/Building-your-own-Code-Climate
118
126
  [7]: https://github.com/charliesome/better_errors
119
127
  [8]: https://github.com/charliesome/better_errors/pull/22
128
+ [9]: http://www.whitesmith.co/
129
+ [10]: https://twitter.com/glitchdout
130
+ [11]: https://twitter.com/Whitesmithco
data/Rakefile CHANGED
@@ -1,10 +1,13 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
+ require "rubocop/rake_task"
3
4
 
4
- task :default => :test
5
-
6
- Rake::TestTask.new do |t|
7
- t.libs.push "lib"
8
- t.libs.push "test"
9
- t.pattern = "test/**/*_test.rb"
5
+ Rake::TestTask.new do |task|
6
+ task.libs.push "lib"
7
+ task.libs.push "test"
8
+ task.pattern = "test/**/*_test.rb"
10
9
  end
10
+
11
+ RuboCop::RakeTask.new
12
+
13
+ task :default => [:test, :rubocop]
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "rubycritic/cli"
3
+ require "rubycritic/cli/application"
4
4
 
5
- exit Rubycritic::Cli.new(ARGV).execute
5
+ exit Rubycritic::Cli::Application.new(ARGV).execute
@@ -1,2 +1,22 @@
1
1
  require "rubycritic/configuration"
2
- require "rubycritic/orchestrator"
2
+
3
+ module Rubycritic
4
+ def self.create(options = {})
5
+ options_hash = options.to_h
6
+ Config.set(options_hash)
7
+ case Config.mode
8
+ when :version
9
+ require "rubycritic/commands/version"
10
+ Command::Version.new
11
+ when :help
12
+ require "rubycritic/commands/help"
13
+ Command::Help.new(options)
14
+ when :ci
15
+ require "rubycritic/commands/ci"
16
+ Command::Ci.new(options_hash)
17
+ else
18
+ require "rubycritic/commands/default"
19
+ Command::Default.new(options_hash)
20
+ end
21
+ end
22
+ end
@@ -2,9 +2,11 @@ module Rubycritic
2
2
  module Analyser
3
3
 
4
4
  class Churn
5
- def initialize(analysed_modules, source_control_system)
5
+ attr_writer :source_control_system
6
+
7
+ def initialize(analysed_modules)
6
8
  @analysed_modules = analysed_modules
7
- @source_control_system = source_control_system
9
+ @source_control_system = Config.source_control_system
8
10
  end
9
11
 
10
12
  def run
@@ -23,9 +23,9 @@ module Parser
23
23
  def get_module_names
24
24
  children_modules = children
25
25
  .select { |child| child.is_a?(Parser::AST::Node) }
26
- .flat_map { |child| child.get_module_names }
26
+ .flat_map(&:get_module_names)
27
27
 
28
- if MODULE_TYPES.include?(self.type)
28
+ if MODULE_TYPES.include?(type)
29
29
  if children_modules.empty?
30
30
  [module_name]
31
31
  else
@@ -33,8 +33,6 @@ module Parser
33
33
  "#{module_name}::#{children_module}"
34
34
  end
35
35
  end
36
- elsif children_modules.empty?
37
- []
38
36
  else
39
37
  children_modules
40
38
  end
@@ -45,22 +43,20 @@ module Parser
45
43
  def module_name
46
44
  name_segments = []
47
45
  current_node = children[0]
48
- while(current_node) do
46
+ while current_node
49
47
  name_segments.unshift(current_node.children[1])
50
48
  current_node = current_node.children[0]
51
49
  end
52
50
  name_segments.join("::")
53
51
  end
54
52
  end
55
-
56
53
  end
57
54
  end
58
55
 
59
56
  module Rubycritic
60
57
  module AST
61
-
62
58
  class EmptyNode
63
- def count_nodes_of_type(*types)
59
+ def count_nodes_of_type(*)
64
60
  0
65
61
  end
66
62
 
@@ -1,5 +1,4 @@
1
- require "parser/current"
2
- require "rubycritic/analysers/helpers/ast_node"
1
+ require "rubycritic/analysers/helpers/parser"
3
2
 
4
3
  module Rubycritic
5
4
 
@@ -15,9 +14,7 @@ module Rubycritic
15
14
  private
16
15
 
17
16
  def node
18
- Parser::CurrentRuby.parse(content) || AST::EmptyNode.new
19
- rescue Parser::SyntaxError => error
20
- AST::EmptyNode.new
17
+ Parser.parse(content)
21
18
  end
22
19
 
23
20
  def content
@@ -1,5 +1,4 @@
1
- require "parser/current"
2
- require "rubycritic/analysers/helpers/ast_node"
1
+ require "rubycritic/analysers/helpers/parser"
3
2
 
4
3
  module Rubycritic
5
4
 
@@ -25,9 +24,7 @@ module Rubycritic
25
24
  private
26
25
 
27
26
  def node
28
- Parser::CurrentRuby.parse(content) || AST::EmptyNode.new
29
- rescue Parser::SyntaxError => error
30
- AST::EmptyNode.new
27
+ Parser.parse(content)
31
28
  end
32
29
 
33
30
  def content
@@ -0,0 +1,12 @@
1
+ require "parser/current"
2
+ require "rubycritic/analysers/helpers/ast_node"
3
+
4
+ module Rubycritic
5
+ module Parser
6
+ def self.parse(content)
7
+ ::Parser::CurrentRuby.parse(content) || AST::EmptyNode.new
8
+ rescue ::Parser::SyntaxError
9
+ AST::EmptyNode.new
10
+ end
11
+ end
12
+ end
@@ -1,12 +1,16 @@
1
1
  require "reek"
2
+ require "reek/configuration/app_configuration"
3
+ require "ostruct"
2
4
 
3
5
  module Rubycritic
4
6
 
5
7
  class Reek < ::Reek::Examiner
6
- DEFAULT_CONFIG_FILES = [File.expand_path("../config.reek", __FILE__)]
8
+ DEFAULT_CONFIG_FILE = File.expand_path("../config.reek", __FILE__)
7
9
 
8
10
  def initialize(paths)
9
- super(Array(paths), DEFAULT_CONFIG_FILES)
11
+ config = OpenStruct.new(:options => OpenStruct.new(:config_file => DEFAULT_CONFIG_FILE))
12
+ ::Reek::Configuration::AppConfiguration.initialize_with(config)
13
+ super(Array(paths))
10
14
  end
11
15
  end
12
16
 
@@ -28,7 +28,7 @@ module Rubycritic
28
28
  :locations => smell_locations(smell.source, smell.lines),
29
29
  :context => smell.context,
30
30
  :message => smell.message,
31
- :type => smell.subclass,
31
+ :type => smell.smell_type,
32
32
  :cost => 0
33
33
  )
34
34
  end
@@ -1,3 +1,5 @@
1
+ require "rubycritic/source_locator"
2
+ require "rubycritic/core/analysed_module"
1
3
  require "rubycritic/analysers/smells/flay"
2
4
  require "rubycritic/analysers/smells/flog"
3
5
  require "rubycritic/analysers/smells/reek"
@@ -13,19 +15,23 @@ module Rubycritic
13
15
  Analyser::FlogSmells,
14
16
  Analyser::ReekSmells,
15
17
  Analyser::Complexity,
16
- Analyser::Attributes
18
+ Analyser::Attributes,
19
+ Analyser::Churn
17
20
  ]
18
21
 
19
- def initialize(analysed_modules, source_control_system)
20
- @analysed_modules = analysed_modules
21
- @source_control_system = source_control_system
22
+ def initialize(paths)
23
+ @paths = paths
22
24
  end
23
25
 
24
26
  def run
25
- ANALYSERS.each do |analyser|
26
- analyser.new(@analysed_modules).run
27
+ ANALYSERS.each { |analyser| analyser.new(analysed_modules).run }
28
+ analysed_modules
29
+ end
30
+
31
+ def analysed_modules
32
+ @analysed_modules ||= SourceLocator.new(@paths).pathnames.map do |pathname|
33
+ AnalysedModule.new(:pathname => pathname)
27
34
  end
28
- Analyser::Churn.new(@analysed_modules, @source_control_system).run
29
35
  end
30
36
  end
31
37
 
@@ -0,0 +1,24 @@
1
+ require "rubycritic"
2
+ require "rubycritic/cli/options"
3
+
4
+ module Rubycritic
5
+ module Cli
6
+ class Application
7
+ STATUS_SUCCESS = 0
8
+ STATUS_ERROR = 1
9
+
10
+ def initialize(argv)
11
+ @options = Options.new(argv)
12
+ end
13
+
14
+ def execute
15
+ parsed_options = @options.parse
16
+ ::Rubycritic.create(parsed_options).execute
17
+ STATUS_SUCCESS
18
+ rescue OptionParser::InvalidOption => error
19
+ $stderr.puts "Error: #{error}"
20
+ STATUS_ERROR
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,57 @@
1
+ require "optparse"
2
+
3
+ module Rubycritic
4
+ module Cli
5
+ class Options
6
+ def initialize(argv)
7
+ @argv = argv
8
+ @parser = OptionParser.new
9
+ end
10
+
11
+ def parse
12
+ @parser.new do |opts|
13
+ opts.banner = "Usage: rubycritic [options] [paths]"
14
+
15
+ opts.on("-p", "--path [PATH]", "Set path where report will be saved (tmp/rubycritic by default)") do |path|
16
+ @root = path
17
+ end
18
+
19
+ opts.on("-m", "--mode-ci", "Use CI mode (faster, but only analyses last commit)") do
20
+ @mode = :ci
21
+ end
22
+
23
+ opts.on_tail("-v", "--version", "Show gem's version") do
24
+ @mode = :version
25
+ end
26
+
27
+ opts.on_tail("-h", "--help", "Show this message") do
28
+ @mode = :help
29
+ end
30
+ end.parse!(@argv)
31
+ self
32
+ end
33
+
34
+ def help_text
35
+ @parser.help
36
+ end
37
+
38
+ def to_h
39
+ {
40
+ :mode => @mode,
41
+ :root => @root,
42
+ :paths => paths
43
+ }
44
+ end
45
+
46
+ private
47
+
48
+ def paths
49
+ if @argv.empty?
50
+ ["."]
51
+ else
52
+ @argv
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,28 @@
1
+ require "rubycritic/source_control_systems/base"
2
+ require "rubycritic/analysers_runner"
3
+ require "rubycritic/reporters/main"
4
+
5
+ module Rubycritic
6
+ module Command
7
+ class Ci
8
+ def initialize(options)
9
+ @paths = options[:paths]
10
+ Config.source_control_system = SourceControlSystem::Base.create
11
+ end
12
+
13
+ def execute
14
+ critique(@paths)
15
+ report
16
+ end
17
+
18
+ def critique(paths)
19
+ @analysed_modules = AnalysersRunner.new(paths).run
20
+ end
21
+
22
+ def report
23
+ report_location = Reporter::Main.new(@analysed_modules).generate_report
24
+ puts "New critique at #{report_location}"
25
+ end
26
+ end
27
+ end
28
+ end