pelusa 0.0.2 → 0.1.0
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.
- data/.pelusa.yml +1 -0
- data/.rvmrc +2 -1
- data/Readme.md +4 -3
- data/lib/pelusa.rb +10 -1
- data/lib/pelusa/cli.rb +3 -1
- data/lib/pelusa/configuration.rb +84 -0
- data/lib/pelusa/lint.rb +3 -0
- data/lib/pelusa/lint/case_statements.rb +35 -0
- data/lib/pelusa/lint/indentation_level.rb +5 -1
- data/lib/pelusa/lint/instance_variables.rb +1 -1
- data/lib/pelusa/lint/line_restriction.rb +1 -1
- data/lib/pelusa/lint/many_arguments.rb +42 -0
- data/lib/pelusa/version.rb +1 -1
- data/test/fixtures/sample_config_one.yml +7 -0
- data/test/pelusa/configuration_test.rb +56 -0
- data/test/pelusa/lint/case_statements_test.rb +43 -0
- data/test/pelusa/lint/indentation_level_test.rb +20 -0
- data/test/pelusa/lint/many_arguments_test.rb +47 -0
- data/test/test_helper.rb +2 -0
- metadata +15 -4
data/.pelusa.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
sources: lib/**/*.rb
|
data/.rvmrc
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
rvm use rbx
|
1
|
+
rvm use --create rbx@pelusa
|
2
|
+
RBXOPT="$RBXOPT -X19"
|
data/Readme.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
# pelusa -
|
1
|
+
# pelusa - /pe 'lu sa/ [](http://travis-ci.org/codegram/pelusa) [](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
|
-
##
|
24
|
+
## Installation and usage
|
24
25
|
|
25
|
-
rvm use rbx
|
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
|
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
|
-
|
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
|
@@ -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
|
data/lib/pelusa/version.rb
CHANGED
@@ -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
metadata
CHANGED
@@ -2,24 +2,24 @@
|
|
2
2
|
name: pelusa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0
|
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-
|
12
|
+
date: 2012-02-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
version_requirements: &
|
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: *
|
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
|