pelusa 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.pelusa.yml ADDED
@@ -0,0 +1 @@
1
+ sources: lib/**/*.rb
data/.rvmrc CHANGED
@@ -1 +1,2 @@
1
- rvm use rbx-head@pelusa
1
+ rvm use --create rbx@pelusa
2
+ RBXOPT="$RBXOPT -X19"
data/Readme.md CHANGED
@@ -1,4 +1,5 @@
1
- # pelusa - a Ruby Lint to improve your OO skills [![Build Status](https://secure.travis-ci.org/codegram/pelusa.png)](http://travis-ci.org/codegram/pelusa)
1
+ # pelusa - /pe 'lu sa/ [![Build Status](https://secure.travis-ci.org/codegram/pelusa.png)](http://travis-ci.org/codegram/pelusa) [![Dependency Status](https://gemnasium.com/codegram/pelusa.png)](https://gemnasium.com/codegram/pelusa)
2
+ ## A Ruby Lint to improve your OO skills
2
3
 
3
4
  Pelusa is a static analysis tool and framework to inspect your code style and
4
5
  notify you about possible red flags or missing best practices.
@@ -20,9 +21,9 @@ Here's a sample of pelusa linting on its own code base:
20
21
  Pelusa happens to be Spanish for the word "Lint". Yeah, I couldn't believe it
21
22
  either.
22
23
 
23
- ## Install and usage
24
+ ## Installation and usage
24
25
 
25
- rvm use rbx-head
26
+ rvm use rbx
26
27
  gem install pelusa
27
28
 
28
29
  To run pelusa, you must run Rubinius in 1.9 mode. To do this, export this
data/lib/pelusa.rb CHANGED
@@ -2,12 +2,21 @@ module Pelusa
2
2
  # Public: Runs the runner on a set of files.
3
3
  #
4
4
  # Returns an Array of results of a given Reporter
5
- def self.run(files=[], reporter=StdoutReporter, lints=Lint.all)
5
+ def self.run(files=[], reporter=StdoutReporter)
6
+ lints = configuration.enabled_lints
6
7
  runner = Runner.new(lints, reporter)
7
8
  runner.run(files)
8
9
  end
10
+
11
+ # Return configuration
12
+ def self.configuration
13
+ @configuration ||= Configuration.new
14
+ end
9
15
  end
10
16
 
17
+ require 'yaml'
18
+
19
+ require 'pelusa/configuration'
11
20
  require 'pelusa/cli'
12
21
  require 'pelusa/runner'
13
22
  require 'pelusa/analyzer'
data/lib/pelusa/cli.rb CHANGED
@@ -21,7 +21,9 @@ module Pelusa
21
21
  if glob = @args.detect { |arg| arg =~ /\*/ }
22
22
  return Dir[glob]
23
23
  end
24
- @args.select { |arg| arg =~ /\.rb/ }
24
+ _files = @args.select { |arg| arg =~ /\.rb/ }
25
+ _files = Dir[Pelusa.configuration.sources] if _files.empty?
26
+ _files
25
27
  end
26
28
  end
27
29
  end
@@ -0,0 +1,84 @@
1
+ module Pelusa
2
+ # Public: Class providing configuration for the runner and lints
3
+ #
4
+ # Examples
5
+ #
6
+ # configuration = Pelusa::Configuration.new('my_pelusa_config.yml')
7
+ # configuration.present? # => true
8
+ #
9
+ class Configuration
10
+ YAML_PATH = './.pelusa.yml'
11
+
12
+ # Public: Initializes a configuration instance
13
+ #
14
+ # yaml_path - optional path to the configuration file
15
+ def initialize(yaml_path = YAML_PATH)
16
+ if File.exist?(yaml_path)
17
+ @_configuration = YAML.load_file(yaml_path).freeze
18
+ end
19
+ end
20
+
21
+ # Public: Returns if a custom configuration is present
22
+ #
23
+ # Examples
24
+ #
25
+ # Pelusa.configuration.present? # => true
26
+ #
27
+ def present?
28
+ not @_configuration.nil?
29
+ end
30
+
31
+ # Public: Returns custom configuration for the given lint
32
+ #
33
+ # Examples
34
+ #
35
+ # Pelusa.configuration['LineRestriction'] # => {'limit' => 50}
36
+ #
37
+ # name - the name of the lint
38
+ def [](name)
39
+ for_lint(name)
40
+ end
41
+
42
+ # Public: Returns path to sources that should be analyzed
43
+ #
44
+ # Examples
45
+ #
46
+ # Pelusa.configuration.sources # => lib/**/*.rb
47
+ #
48
+ def sources
49
+ @_configuration['sources']
50
+ end
51
+
52
+ # Public: Returns an Array of enabled lints
53
+ #
54
+ # Examples
55
+ #
56
+ # Pelusa.configuration.enabled_lints # => [ Pelusa::Lint::DemeterLaw ]
57
+ #
58
+ def enabled_lints
59
+ (Lint.all - disabled_lints).uniq
60
+ end
61
+
62
+ #######
63
+ private
64
+ #######
65
+
66
+ # Private: Returns a Hash of configuration for lints
67
+ def lints
68
+ @_configuration.fetch('lints', {})
69
+ end
70
+
71
+ # Private: Returns an Array of lints disabled in the configuration
72
+ def disabled_lints
73
+ lints.select { |lint, conf| conf['enabled'] === false }.map do |lint,|
74
+ Lint.const_get(lint)
75
+ end
76
+ end
77
+
78
+ # Private: Public: Returns custom configuration for the given lint
79
+ def for_lint(name)
80
+ lints.fetch(name, {})
81
+ end
82
+
83
+ end # class Configuration
84
+ end # module Pelusa
data/lib/pelusa/lint.rb CHANGED
@@ -7,6 +7,8 @@ require 'pelusa/lint/else_clauses'
7
7
  require 'pelusa/lint/properties'
8
8
  require 'pelusa/lint/collection_wrappers'
9
9
  require 'pelusa/lint/short_identifiers'
10
+ require 'pelusa/lint/case_statements'
11
+ require 'pelusa/lint/many_arguments'
10
12
 
11
13
  module Pelusa
12
14
  # Public: A Lint is a quality standard, applicable on a given piece of code to
@@ -23,6 +25,7 @@ module Pelusa
23
25
  Properties,
24
26
  CollectionWrappers,
25
27
  ShortIdentifiers,
28
+ ManyArguments
26
29
  ]
27
30
  end
28
31
  end
@@ -0,0 +1,35 @@
1
+ module Pelusa
2
+ module Lint
3
+ class CaseStatements
4
+ def initialize
5
+ @violations = Set.new
6
+ end
7
+
8
+ def check(klass)
9
+ initialize
10
+ iterate_lines!(klass)
11
+
12
+ return SuccessfulAnalysis.new(name) if @violations.empty?
13
+
14
+ FailedAnalysis.new(name, @violations) do |violations|
15
+ "There are #{violations.length} case statements in lines #{violations.to_a.join(', ')}"
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def name
22
+ "Doesn't use case statements"
23
+ end
24
+
25
+ def iterate_lines!(klass)
26
+ iterator = Iterator.new do |node|
27
+ if node.is_a?(Rubinius::AST::Case)
28
+ @violations << node.line
29
+ end
30
+ end
31
+ Array(klass).each(&iterator)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -29,7 +29,11 @@ module Pelusa
29
29
  __iterate = Iterator.new do |node|
30
30
  if body = get_body_from_node[node]
31
31
  if node.line != [body].flatten.first.line
32
- @violations << body.line
32
+ if body.is_a?(Array)
33
+ @violations.merge body.map(&:line)
34
+ else
35
+ @violations << body.line
36
+ end
33
37
  end
34
38
  end
35
39
  end
@@ -23,7 +23,7 @@ module Pelusa
23
23
  end
24
24
 
25
25
  def limit
26
- 3
26
+ Pelusa.configuration['InstanceVariables'].fetch('limit', 3)
27
27
  end
28
28
 
29
29
  def iterate_lines!(klass)
@@ -23,7 +23,7 @@ module Pelusa
23
23
  end
24
24
 
25
25
  def limit
26
- 50
26
+ Pelusa.configuration['LineRestriction'].fetch('limit', 50)
27
27
  end
28
28
 
29
29
  def lines
@@ -0,0 +1,42 @@
1
+ module Pelusa
2
+ module Lint
3
+ class ManyArguments
4
+ def initialize
5
+ @violations = Set.new
6
+ end
7
+
8
+ def check(klass)
9
+ initialize
10
+ iterate_lines!(klass)
11
+ return SuccessfulAnalysis.new(name) if @violations.empty?
12
+
13
+ FailedAnalysis.new(name, formatted_violations) do |violations|
14
+ "Methods with more than #{limit} arguments: #{violations.join(', ')}"
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def name
21
+ "Methods have short argument lists"
22
+ end
23
+
24
+ def limit
25
+ Pelusa.configuration['ManyArguments'].fetch('limit', 3)
26
+ end
27
+
28
+ def iterate_lines!(klass)
29
+ iterator = Iterator.new do |node|
30
+ if node.is_a?(Rubinius::AST::Define) && node.arguments.total_args > limit
31
+ @violations << node.name
32
+ end
33
+ end
34
+ Array(klass).each(&iterator)
35
+ end
36
+
37
+ def formatted_violations
38
+ @violations.to_a
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,3 +1,3 @@
1
1
  module Pelusa
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,7 @@
1
+ sources: lib/**/*.rb
2
+ lints:
3
+ ElseClauses:
4
+ enabled: false
5
+ LineRestriction:
6
+ enabled: true
7
+ limit: 80
@@ -0,0 +1,56 @@
1
+ require 'test_helper'
2
+
3
+ module Pelusa
4
+ describe Configuration do
5
+ let(:configuration) do
6
+ Pelusa::Configuration.new("#{FIXTURES_PATH}/sample_config_one.yml")
7
+ end
8
+
9
+ describe "#present?" do
10
+ it "returns false when configuration doesn't file exists" do
11
+ configuration = Pelusa::Configuration.new("#{FIXTURES_PATH}/not_here.yml")
12
+ configuration.present?.must_equal(false)
13
+ end
14
+
15
+ it "returns false when configuration file exists" do
16
+ configuration.present?.must_equal(true)
17
+ end
18
+ end
19
+
20
+ describe '#sources' do
21
+ it 'returns path to sources' do
22
+ configuration.sources.must_equal 'lib/**/*.rb'
23
+ end
24
+ end
25
+
26
+ describe '#enabled_lints' do
27
+ let(:enabled_lints) { Lint.all - [ Pelusa::Lint::ElseClauses ] }
28
+
29
+ it 'returns all enabled lints' do
30
+ configuration.enabled_lints.must_equal(enabled_lints)
31
+ end
32
+ end
33
+
34
+ describe '#[]' do
35
+ describe 'when lint configuration exists' do
36
+ let(:lint_configuration) { configuration['LineRestriction'] }
37
+
38
+ it 'returns a configuration hash for the given lint' do
39
+ lint_configuration.must_be_instance_of(Hash)
40
+ end
41
+
42
+ it 'must return valid configuration' do
43
+ lint_configuration['limit'].must_equal(80)
44
+ end
45
+ end
46
+
47
+ describe "when lint configuration doesn't exist" do
48
+ let(:lint_configuration) { configuration['DemeterLaw'] }
49
+
50
+ it 'returns an empty configuration hash' do
51
+ lint_configuration.must_equal({})
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,43 @@
1
+ require 'test_helper'
2
+
3
+ module Pelusa
4
+ module Lint
5
+ describe CaseStatements do
6
+ before do
7
+ @lint = CaseStatements.new
8
+ end
9
+
10
+ describe '#check' do
11
+ describe 'when the class does not use switch statements' do
12
+ it 'returns a SuccessAnalysis' do
13
+ klass = """
14
+ class Foo
15
+ def initialize
16
+ return nil
17
+ end
18
+ end""".to_ast
19
+
20
+ analysis = @lint.check(klass)
21
+ analysis.successful?.must_equal true
22
+ end
23
+ end
24
+
25
+ describe 'when the class uses case statements' do
26
+ it 'returns a FailureAnalysis' do
27
+ klass = """
28
+ class Foo
29
+ def initialize
30
+ case foo
31
+ when bar
32
+ end
33
+ end
34
+ end""".to_ast
35
+
36
+ analysis = @lint.check(klass)
37
+ analysis.failed?.must_equal true
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -41,6 +41,26 @@ module Pelusa
41
41
  analysis.failed?.must_equal true
42
42
  end
43
43
  end
44
+
45
+ describe "when there is method which produces nested list" do
46
+ it 'returns a FailureAnalysis' do
47
+ klass = """
48
+ class Foo
49
+ def initialize
50
+ if test
51
+ a = [
52
+ (1..3).map do |num|
53
+ num
54
+ end
55
+ ]
56
+ end
57
+ end
58
+ end""".to_ast
59
+
60
+ analysis = @lint.check klass
61
+ analysis.failed?.must_equal true
62
+ end
63
+ end
44
64
  end
45
65
  end
46
66
  end
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+
3
+ module Pelusa
4
+ module Lint
5
+ describe ManyArguments do
6
+ before do
7
+ @lint = ManyArguments.new
8
+ end
9
+
10
+ describe '#check' do
11
+ describe 'when the class contains only method definitions with a small number of arguments' do
12
+ it 'returns a SuccessAnalysis' do
13
+ klass = """
14
+ class Foo
15
+ def bar(dog)
16
+ return dog
17
+ end
18
+ def baz(dog, cat)
19
+ return dog + cat
20
+ end
21
+ def bam(dog, cat, fish)
22
+ return dog + cat + fish
23
+ end
24
+ end""".to_ast
25
+
26
+ analysis = @lint.check(klass)
27
+ analysis.successful?.must_equal true
28
+ end
29
+ end
30
+
31
+ describe 'when the class contains a method definition with many arguments' do
32
+ it 'returns a FailureAnalysis' do
33
+ klass = """
34
+ class Foo
35
+ def bar(dog, cat, fish, lobster)
36
+ x = 2
37
+ end
38
+ end""".to_ast
39
+
40
+ analysis = @lint.check(klass)
41
+ analysis.failed?.must_equal true
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
data/test/test_helper.rb CHANGED
@@ -3,3 +3,5 @@ require 'minitest/spec'
3
3
  require 'mocha'
4
4
 
5
5
  require 'pelusa'
6
+
7
+ FIXTURES_PATH = File.dirname(__FILE__) + '/fixtures'
metadata CHANGED
@@ -2,24 +2,24 @@
2
2
  name: pelusa
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.2
5
+ version: 0.1.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Josep M. Bach
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-15 00:00:00.000000000 Z
12
+ date: 2012-02-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- version_requirements: &6324 !ruby/object:Gem::Requirement
15
+ version_requirements: &4832 !ruby/object:Gem::Requirement
16
16
  none: false
17
17
  requirements:
18
18
  - - ! '>='
19
19
  - !ruby/object:Gem::Version
20
20
  version: '0'
21
21
  prerelease: false
22
- requirement: *6324
22
+ requirement: *4832
23
23
  name: mocha
24
24
  type: :development
25
25
  description: Static analysis Lint-type tool to improve your OO Ruby code
@@ -31,6 +31,7 @@ extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
33
  - .gitignore
34
+ - .pelusa.yml
34
35
  - .rvmrc
35
36
  - .travis.yml
36
37
  - Gemfile
@@ -42,14 +43,17 @@ files:
42
43
  - lib/pelusa/analyzer.rb
43
44
  - lib/pelusa/class_analyzer.rb
44
45
  - lib/pelusa/cli.rb
46
+ - lib/pelusa/configuration.rb
45
47
  - lib/pelusa/iterator.rb
46
48
  - lib/pelusa/lint.rb
49
+ - lib/pelusa/lint/case_statements.rb
47
50
  - lib/pelusa/lint/collection_wrappers.rb
48
51
  - lib/pelusa/lint/demeter_law.rb
49
52
  - lib/pelusa/lint/else_clauses.rb
50
53
  - lib/pelusa/lint/indentation_level.rb
51
54
  - lib/pelusa/lint/instance_variables.rb
52
55
  - lib/pelusa/lint/line_restriction.rb
56
+ - lib/pelusa/lint/many_arguments.rb
53
57
  - lib/pelusa/lint/properties.rb
54
58
  - lib/pelusa/lint/short_identifiers.rb
55
59
  - lib/pelusa/report.rb
@@ -59,16 +63,20 @@ files:
59
63
  - lib/pelusa/runner.rb
60
64
  - lib/pelusa/version.rb
61
65
  - pelusa.gemspec
66
+ - test/fixtures/sample_config_one.yml
62
67
  - test/pelusa/analysis_test.rb
63
68
  - test/pelusa/analyzer_test.rb
64
69
  - test/pelusa/class_analyzer_test.rb
70
+ - test/pelusa/configuration_test.rb
65
71
  - test/pelusa/iterator_test.rb
72
+ - test/pelusa/lint/case_statements_test.rb
66
73
  - test/pelusa/lint/collection_wrappers_test.rb
67
74
  - test/pelusa/lint/demeter_law_test.rb
68
75
  - test/pelusa/lint/else_clauses_test.rb
69
76
  - test/pelusa/lint/indentation_level_test.rb
70
77
  - test/pelusa/lint/instance_variables_test.rb
71
78
  - test/pelusa/lint/line_restriction_test.rb
79
+ - test/pelusa/lint/many_arguments_test.rb
72
80
  - test/pelusa/lint/properties_test.rb
73
81
  - test/pelusa/lint/short_identifiers_test.rb
74
82
  - test/pelusa/reporters/ruby_reporter_test.rb
@@ -105,14 +113,17 @@ test_files:
105
113
  - test/pelusa/analysis_test.rb
106
114
  - test/pelusa/analyzer_test.rb
107
115
  - test/pelusa/class_analyzer_test.rb
116
+ - test/pelusa/configuration_test.rb
108
117
  - test/pelusa/iterator_test.rb
109
118
  - test/pelusa/runner_test.rb
119
+ - test/pelusa/lint/case_statements_test.rb
110
120
  - test/pelusa/lint/collection_wrappers_test.rb
111
121
  - test/pelusa/lint/demeter_law_test.rb
112
122
  - test/pelusa/lint/else_clauses_test.rb
113
123
  - test/pelusa/lint/indentation_level_test.rb
114
124
  - test/pelusa/lint/instance_variables_test.rb
115
125
  - test/pelusa/lint/line_restriction_test.rb
126
+ - test/pelusa/lint/many_arguments_test.rb
116
127
  - test/pelusa/lint/properties_test.rb
117
128
  - test/pelusa/lint/short_identifiers_test.rb
118
129
  - test/pelusa/reporters/ruby_reporter_test.rb