ruby-lint 0.0.1a
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.rbenv-version +1 -0
- data/.yardopts +10 -0
- data/Gemfile +3 -0
- data/LICENSE +19 -0
- data/MANIFEST +79 -0
- data/README.md +48 -0
- data/Rakefile +14 -0
- data/bin/rlint +6 -0
- data/doc/.gitkeep +0 -0
- data/doc/build/.gitkeep +0 -0
- data/doc/css/.gitkeep +0 -0
- data/doc/css/common.css +68 -0
- data/lib/rlint/analyze/coding_style.rb +407 -0
- data/lib/rlint/analyze/definitions.rb +244 -0
- data/lib/rlint/analyze/method_validation.rb +104 -0
- data/lib/rlint/analyze/shadowing_variables.rb +37 -0
- data/lib/rlint/analyze/undefined_variables.rb +99 -0
- data/lib/rlint/analyze/unused_variables.rb +103 -0
- data/lib/rlint/callback.rb +67 -0
- data/lib/rlint/cli.rb +167 -0
- data/lib/rlint/constant_importer.rb +102 -0
- data/lib/rlint/definition.rb +230 -0
- data/lib/rlint/formatter/text.rb +54 -0
- data/lib/rlint/helper/definition_resolver.rb +143 -0
- data/lib/rlint/helper/scoping.rb +138 -0
- data/lib/rlint/iterator.rb +193 -0
- data/lib/rlint/options.rb +58 -0
- data/lib/rlint/parser.rb +1252 -0
- data/lib/rlint/parser_error.rb +42 -0
- data/lib/rlint/report.rb +98 -0
- data/lib/rlint/token/assignment_token.rb +46 -0
- data/lib/rlint/token/begin_rescue_token.rb +57 -0
- data/lib/rlint/token/block_token.rb +17 -0
- data/lib/rlint/token/case_token.rb +44 -0
- data/lib/rlint/token/class_token.rb +24 -0
- data/lib/rlint/token/method_definition_token.rb +64 -0
- data/lib/rlint/token/method_token.rb +58 -0
- data/lib/rlint/token/parameters_token.rb +99 -0
- data/lib/rlint/token/regexp_token.rb +15 -0
- data/lib/rlint/token/statement_token.rb +69 -0
- data/lib/rlint/token/token.rb +162 -0
- data/lib/rlint/token/variable_token.rb +18 -0
- data/lib/rlint/version.rb +3 -0
- data/lib/rlint.rb +36 -0
- data/ruby-lint.gemspec +23 -0
- data/spec/benchmarks/memory.rb +52 -0
- data/spec/benchmarks/parse_parser.rb +16 -0
- data/spec/helper.rb +4 -0
- data/spec/rlint/analyze/coding_style.rb +224 -0
- data/spec/rlint/analyze/definitions/classes.rb +114 -0
- data/spec/rlint/analyze/definitions/methods.rb +91 -0
- data/spec/rlint/analyze/definitions/modules.rb +207 -0
- data/spec/rlint/analyze/definitions/variables.rb +103 -0
- data/spec/rlint/analyze/method_validation.rb +177 -0
- data/spec/rlint/analyze/shadowing_variables.rb +30 -0
- data/spec/rlint/analyze/undefined_variables.rb +230 -0
- data/spec/rlint/analyze/unused_variables.rb +225 -0
- data/spec/rlint/callback.rb +28 -0
- data/spec/rlint/constant_importer.rb +27 -0
- data/spec/rlint/definition.rb +96 -0
- data/spec/rlint/formatter/text.rb +21 -0
- data/spec/rlint/iterator.rb +452 -0
- data/spec/rlint/parser/arrays.rb +147 -0
- data/spec/rlint/parser/classes.rb +152 -0
- data/spec/rlint/parser/errors.rb +19 -0
- data/spec/rlint/parser/hashes.rb +136 -0
- data/spec/rlint/parser/methods.rb +249 -0
- data/spec/rlint/parser/modules.rb +49 -0
- data/spec/rlint/parser/objects.rb +39 -0
- data/spec/rlint/parser/operators.rb +75 -0
- data/spec/rlint/parser/procs.rb +113 -0
- data/spec/rlint/parser/ranges.rb +49 -0
- data/spec/rlint/parser/regexp.rb +31 -0
- data/spec/rlint/parser/scalars.rb +93 -0
- data/spec/rlint/parser/statements.rb +550 -0
- data/spec/rlint/parser/variables.rb +181 -0
- data/spec/rlint/report.rb +30 -0
- data/task/test.rake +6 -0
- metadata +188 -0
@@ -0,0 +1,147 @@
|
|
1
|
+
require File.expand_path('../../../helper', __FILE__)
|
2
|
+
|
3
|
+
describe 'Rlint::Parser' do
|
4
|
+
it 'Parse an Array' do
|
5
|
+
token = Rlint::Parser.new('[10, 20]').parse[0]
|
6
|
+
|
7
|
+
token.class.should == Rlint::Token::Token
|
8
|
+
token.type.should == :array
|
9
|
+
|
10
|
+
token.value.class.should == Array
|
11
|
+
token.value.length.should == 2
|
12
|
+
|
13
|
+
token.line.should == 1
|
14
|
+
token.column.should == 8
|
15
|
+
token.code.should == '[10, 20]'
|
16
|
+
|
17
|
+
token.value[0].class.should == Rlint::Token::Token
|
18
|
+
token.value[0].type.should == :integer
|
19
|
+
token.value[0].value.should == '10'
|
20
|
+
|
21
|
+
token.value[1].class.should == Rlint::Token::Token
|
22
|
+
token.value[1].type.should == :integer
|
23
|
+
token.value[1].value.should == '20'
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'Parse an Array using %w{}' do
|
27
|
+
token = Rlint::Parser.new('%w{10 20}').parse[0]
|
28
|
+
|
29
|
+
token.class.should == Rlint::Token::Token
|
30
|
+
token.type.should == :array
|
31
|
+
|
32
|
+
token.value.class.should == Array
|
33
|
+
token.value.length.should == 2
|
34
|
+
|
35
|
+
token.line.should == 1
|
36
|
+
token.column.should == 9
|
37
|
+
token.code.should == '%w{10 20}'
|
38
|
+
|
39
|
+
token.value[0].class.should == Rlint::Token::Token
|
40
|
+
token.value[0].type.should == :string
|
41
|
+
token.value[0].value.should == '10'
|
42
|
+
|
43
|
+
token.value[1].class.should == Rlint::Token::Token
|
44
|
+
token.value[1].type.should == :string
|
45
|
+
token.value[1].value.should == '20'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'Parse an Array using %W{}' do
|
49
|
+
token = Rlint::Parser.new('%W{10 20}').parse[0]
|
50
|
+
|
51
|
+
token.class.should == Rlint::Token::Token
|
52
|
+
token.type.should == :array
|
53
|
+
|
54
|
+
token.value.class.should == Array
|
55
|
+
token.value.length.should == 2
|
56
|
+
|
57
|
+
token.line.should == 1
|
58
|
+
token.column.should == 9
|
59
|
+
token.code.should == '%W{10 20}'
|
60
|
+
|
61
|
+
token.value[0].class.should == Rlint::Token::Token
|
62
|
+
token.value[0].type.should == :string
|
63
|
+
token.value[0].value.should == '10'
|
64
|
+
|
65
|
+
token.value[1].class.should == Rlint::Token::Token
|
66
|
+
token.value[1].type.should == :string
|
67
|
+
token.value[1].value.should == '20'
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'Parse an Array index reference' do
|
71
|
+
token = Rlint::Parser.new("[10][0]").parse[0]
|
72
|
+
|
73
|
+
token.class.should == Rlint::Token::Token
|
74
|
+
token.line.should == 1
|
75
|
+
token.column.should == 4
|
76
|
+
token.code.should == '[10][0]'
|
77
|
+
|
78
|
+
token.key.class.should == Array
|
79
|
+
token.key.length.should == 1
|
80
|
+
|
81
|
+
token.key[0].class.should == Rlint::Token::Token
|
82
|
+
token.key[0].type.should == :integer
|
83
|
+
token.key[0].value.should == '0'
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'Parse an Array index reference using a variable' do
|
87
|
+
token = Rlint::Parser.new("numbers = [10]\nnumbers[0]").parse[1]
|
88
|
+
|
89
|
+
token.class.should == Rlint::Token::VariableToken
|
90
|
+
token.line.should == 2
|
91
|
+
token.column.should == 0
|
92
|
+
token.name.should == 'numbers'
|
93
|
+
token.code.should == 'numbers[0]'
|
94
|
+
|
95
|
+
token.key.class.should == Array
|
96
|
+
token.key.length.should == 1
|
97
|
+
|
98
|
+
token.key[0].class.should == Rlint::Token::Token
|
99
|
+
token.key[0].type.should == :integer
|
100
|
+
token.key[0].value.should == '0'
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'Parse multiple Array index references' do
|
104
|
+
token = Rlint::Parser.new("numbers = [10]\nnumbers[0,1]").parse[1]
|
105
|
+
|
106
|
+
token.class.should == Rlint::Token::VariableToken
|
107
|
+
token.line.should == 2
|
108
|
+
token.column.should == 0
|
109
|
+
token.name.should == 'numbers'
|
110
|
+
token.code.should == 'numbers[0,1]'
|
111
|
+
|
112
|
+
token.key.class.should == Array
|
113
|
+
token.key.length.should == 2
|
114
|
+
|
115
|
+
token.key[0].class.should == Rlint::Token::Token
|
116
|
+
token.key[0].type.should == :integer
|
117
|
+
token.key[0].value.should == '0'
|
118
|
+
|
119
|
+
token.key[1].class.should == Rlint::Token::Token
|
120
|
+
token.key[1].type.should == :integer
|
121
|
+
token.key[1].value.should == '1'
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'Parse the assignment of a value to an array index' do
|
125
|
+
token = Rlint::Parser.new("numbers = []\nnumbers[0] = 10").parse[1]
|
126
|
+
|
127
|
+
token.class.should == Rlint::Token::AssignmentToken
|
128
|
+
|
129
|
+
token.line.should == 2
|
130
|
+
token.column.should == 12
|
131
|
+
token.code.should == 'numbers[0] = 10'
|
132
|
+
|
133
|
+
token.value.class.should == Rlint::Token::Token
|
134
|
+
token.value.type.should == :integer
|
135
|
+
token.value.value.should == '10'
|
136
|
+
|
137
|
+
token.receiver.class.should == Rlint::Token::VariableToken
|
138
|
+
token.receiver.name.should == 'numbers'
|
139
|
+
|
140
|
+
token.receiver.key.class.should == Array
|
141
|
+
token.receiver.key.length.should == 1
|
142
|
+
|
143
|
+
token.receiver.key[0].class.should == Rlint::Token::Token
|
144
|
+
token.receiver.key[0].type.should == :integer
|
145
|
+
token.receiver.key[0].value.should == '0'
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require File.expand_path('../../../helper', __FILE__)
|
2
|
+
|
3
|
+
describe 'Rlint::Parser' do
|
4
|
+
it 'Parse a class declaration' do
|
5
|
+
token = Rlint::Parser.new('class Foo; end').parse[0]
|
6
|
+
|
7
|
+
token.class.should == Rlint::Token::ClassToken
|
8
|
+
token.name.should == ['Foo']
|
9
|
+
token.type.should == :class
|
10
|
+
token.line.should == 1
|
11
|
+
token.column.should == 6
|
12
|
+
token.code.should == 'class Foo; end'
|
13
|
+
|
14
|
+
token.value.class.should == Array
|
15
|
+
token.value.length.should == 0
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'Parse a top level class declaration' do
|
19
|
+
token = Rlint::Parser.new('class ::Foo; end').parse[0]
|
20
|
+
|
21
|
+
token.class.should == Rlint::Token::ClassToken
|
22
|
+
token.name.should == ['Foo']
|
23
|
+
token.type.should == :class
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'Parse a class declaration with a parent class' do
|
27
|
+
token = Rlint::Parser.new('class Foo < Bar; end').parse[0]
|
28
|
+
|
29
|
+
token.class.should == Rlint::Token::ClassToken
|
30
|
+
token.name.should == ['Foo']
|
31
|
+
token.parent.should == ['Bar']
|
32
|
+
token.type.should == :class
|
33
|
+
token.line.should == 1
|
34
|
+
token.column.should == 6
|
35
|
+
token.code.should == 'class Foo < Bar; end'
|
36
|
+
|
37
|
+
token.value.class.should == Array
|
38
|
+
token.value.length.should == 0
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'Parse a class declaration with multiple name segments' do
|
42
|
+
token = Rlint::Parser.new('class Foo::Bar < A::B; end').parse[0]
|
43
|
+
|
44
|
+
token.class.should == Rlint::Token::ClassToken
|
45
|
+
token.type.should == :class
|
46
|
+
token.name.should == ['Foo', 'Bar']
|
47
|
+
|
48
|
+
token.parent.should == ['A', 'B']
|
49
|
+
token.line.should == 1
|
50
|
+
token.column.should == 6
|
51
|
+
token.code.should == 'class Foo::Bar < A::B; end'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'Parse a top level class declaration with multiple name segments' do
|
55
|
+
token = Rlint::Parser.new('class ::Foo::Bar; end').parse[0]
|
56
|
+
|
57
|
+
token.class.should == Rlint::Token::ClassToken
|
58
|
+
token.type.should == :class
|
59
|
+
token.name.should == ['Foo', 'Bar']
|
60
|
+
token.line.should == 1
|
61
|
+
token.column.should == 8
|
62
|
+
token.code.should == 'class ::Foo::Bar; end'
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'Parse the assignments of method visibilities' do
|
66
|
+
code = <<-CODE
|
67
|
+
class First
|
68
|
+
private
|
69
|
+
|
70
|
+
def private_method
|
71
|
+
return 'private method'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def public_method
|
76
|
+
return 'public method'
|
77
|
+
end
|
78
|
+
|
79
|
+
class Second
|
80
|
+
protected
|
81
|
+
|
82
|
+
def protected_method
|
83
|
+
return 'protected method'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
CODE
|
87
|
+
|
88
|
+
first, pub_method, second = Rlint::Parser.new(code).parse
|
89
|
+
|
90
|
+
first.class.should == Rlint::Token::ClassToken
|
91
|
+
first.name.should == ['First']
|
92
|
+
first.line.should == 1
|
93
|
+
first.column.should == 6
|
94
|
+
first.code.should == 'class First'
|
95
|
+
|
96
|
+
first.value[0].class.should == Rlint::Token::MethodDefinitionToken
|
97
|
+
first.value[0].name.should == 'private_method'
|
98
|
+
first.value[0].visibility.should == :private
|
99
|
+
first.value[0].line.should == 4
|
100
|
+
first.value[0].column.should == 6
|
101
|
+
first.value[0].code.should == ' def private_method'
|
102
|
+
|
103
|
+
pub_method.class.should == Rlint::Token::MethodDefinitionToken
|
104
|
+
pub_method.name.should == 'public_method'
|
105
|
+
pub_method.visibility.should == :public
|
106
|
+
|
107
|
+
second.class.should == Rlint::Token::ClassToken
|
108
|
+
second.name.should == ['Second']
|
109
|
+
|
110
|
+
second.value[0].class.should == Rlint::Token::MethodDefinitionToken
|
111
|
+
second.value[0].name.should == 'protected_method'
|
112
|
+
second.value[0].visibility.should == :protected
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'Parse the creation of methods using class << self' do
|
116
|
+
code = <<-CODE
|
117
|
+
class Person
|
118
|
+
class << self
|
119
|
+
def class_method_1
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
def class_method_2
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
CODE
|
129
|
+
|
130
|
+
token = Rlint::Parser.new(code).parse[0]
|
131
|
+
|
132
|
+
token.class.should == Rlint::Token::ClassToken
|
133
|
+
token.name.should == ['Person']
|
134
|
+
|
135
|
+
token.value.class.should == Array
|
136
|
+
token.value.length.should == 2
|
137
|
+
|
138
|
+
method_1, method_2 = token.value
|
139
|
+
|
140
|
+
method_1.class.should == Rlint::Token::MethodDefinitionToken
|
141
|
+
method_1.name.should == 'class_method_1'
|
142
|
+
|
143
|
+
method_1.receiver.class.should == Rlint::Token::VariableToken
|
144
|
+
method_1.receiver.name.should == 'self'
|
145
|
+
|
146
|
+
method_2.class.should == Rlint::Token::MethodDefinitionToken
|
147
|
+
method_2.name.should == 'class_method_2'
|
148
|
+
|
149
|
+
method_2.receiver.class.should == Rlint::Token::VariableToken
|
150
|
+
method_2.receiver.name.should == 'self'
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.expand_path('../../../helper', __FILE__)
|
2
|
+
|
3
|
+
describe 'Rlint::Parser' do
|
4
|
+
it 'Parse a syntax error' do
|
5
|
+
code = <<-CODE
|
6
|
+
def example
|
7
|
+
-
|
8
|
+
end
|
9
|
+
CODE
|
10
|
+
|
11
|
+
error = should.raise?(Rlint::ParserError) do
|
12
|
+
Rlint::Parser.new(code).parse
|
13
|
+
end
|
14
|
+
|
15
|
+
error.file.should == '(rlint)'
|
16
|
+
error.line.should == 3
|
17
|
+
error.column.should == 3
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require File.expand_path('../../../helper', __FILE__)
|
2
|
+
|
3
|
+
describe 'Rlint::Parser' do
|
4
|
+
it 'Parse a Hash' do
|
5
|
+
input = '{"name" => "Ruby", "Foo" => "Bar"}'
|
6
|
+
token = Rlint::Parser.new(input).parse[0]
|
7
|
+
|
8
|
+
token.class.should == Rlint::Token::Token
|
9
|
+
token.line.should == 1
|
10
|
+
token.column.should == 2
|
11
|
+
token.code.should == input
|
12
|
+
|
13
|
+
token.value.class.should == Array
|
14
|
+
token.value.length.should == 2
|
15
|
+
|
16
|
+
first = token.value[0]
|
17
|
+
last = token.value[1]
|
18
|
+
|
19
|
+
first.class.should == Rlint::Token::Token
|
20
|
+
first.name.should == 'name'
|
21
|
+
first.type.should == :string
|
22
|
+
|
23
|
+
first.value.class.should == Rlint::Token::Token
|
24
|
+
first.value.type.should == :string
|
25
|
+
first.value.value.should == 'Ruby'
|
26
|
+
|
27
|
+
last.class.should == Rlint::Token::Token
|
28
|
+
last.name.should == 'Foo'
|
29
|
+
last.type.should == :string
|
30
|
+
|
31
|
+
last.value.class.should == Rlint::Token::Token
|
32
|
+
last.value.type.should == :string
|
33
|
+
last.value.value.should == 'Bar'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'Parse a Hash using symbols' do
|
37
|
+
input = '{:name => "Ruby", :Foo => "Bar"}'
|
38
|
+
token = Rlint::Parser.new(input).parse[0]
|
39
|
+
|
40
|
+
token.class.should == Rlint::Token::Token
|
41
|
+
token.line.should == 1
|
42
|
+
token.column.should == 2
|
43
|
+
token.code.should == input
|
44
|
+
|
45
|
+
token.value.class.should == Array
|
46
|
+
token.value.length.should == 2
|
47
|
+
|
48
|
+
first = token.value[0]
|
49
|
+
last = token.value[1]
|
50
|
+
|
51
|
+
first.class.should == Rlint::Token::Token
|
52
|
+
first.name.should == 'name'
|
53
|
+
first.type.should == :symbol
|
54
|
+
|
55
|
+
first.value.class.should == Rlint::Token::Token
|
56
|
+
first.value.type.should == :string
|
57
|
+
first.value.value.should == 'Ruby'
|
58
|
+
|
59
|
+
last.class.should == Rlint::Token::Token
|
60
|
+
last.name.should == 'Foo'
|
61
|
+
last.type.should == :symbol
|
62
|
+
|
63
|
+
last.value.class.should == Rlint::Token::Token
|
64
|
+
last.value.type.should == :string
|
65
|
+
last.value.value.should == 'Bar'
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'Parse a Hash using symbols and the JSON syntax' do
|
69
|
+
input = '{name: "Ruby"}'
|
70
|
+
token = Rlint::Parser.new(input).parse[0]
|
71
|
+
|
72
|
+
token.class.should == Rlint::Token::Token
|
73
|
+
token.line.should == 1
|
74
|
+
token.column.should == 1
|
75
|
+
token.code.should == input
|
76
|
+
|
77
|
+
token.value.class.should == Array
|
78
|
+
token.value.length.should == 1
|
79
|
+
|
80
|
+
pair = token.value[0]
|
81
|
+
|
82
|
+
pair.name.should == 'name:'
|
83
|
+
pair.type.should == :symbol
|
84
|
+
|
85
|
+
pair.value.class.should == Rlint::Token::Token
|
86
|
+
pair.value.type.should == :string
|
87
|
+
pair.value.value.should == 'Ruby'
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'Parse a Hash key reference' do
|
91
|
+
input = '{:name => "Ruby"}[:name]'
|
92
|
+
token = Rlint::Parser.new(input).parse[0]
|
93
|
+
|
94
|
+
token.class.should == Rlint::Token::Token
|
95
|
+
token.type.should == :hash
|
96
|
+
token.line.should == 1
|
97
|
+
token.column.should == 2
|
98
|
+
token.code.should == input
|
99
|
+
|
100
|
+
token.key.class.should == Array
|
101
|
+
token.key.length.should == 1
|
102
|
+
|
103
|
+
token.key[0].class.should == Rlint::Token::Token
|
104
|
+
token.key[0].type.should == :symbol
|
105
|
+
token.key[0].value.should == 'name'
|
106
|
+
|
107
|
+
token.value.class.should == Array
|
108
|
+
token.value.length.should == 1
|
109
|
+
|
110
|
+
pair = token.value[0]
|
111
|
+
|
112
|
+
pair.class.should == Rlint::Token::Token
|
113
|
+
pair.type.should == :symbol
|
114
|
+
pair.name.should == 'name'
|
115
|
+
|
116
|
+
pair.value.class.should == Rlint::Token::Token
|
117
|
+
pair.value.value.should == 'Ruby'
|
118
|
+
pair.value.type.should == :string
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'Parse a Hash key reference using a variable' do
|
122
|
+
token = Rlint::Parser.new("hash = {:name => 'Ruby'}\nhash[:name]").parse[1]
|
123
|
+
|
124
|
+
token.class.should == Rlint::Token::VariableToken
|
125
|
+
token.line.should == 2
|
126
|
+
token.column.should == 0
|
127
|
+
token.code.should == 'hash[:name]'
|
128
|
+
|
129
|
+
token.key.class.should == Array
|
130
|
+
token.key.length.should == 1
|
131
|
+
|
132
|
+
token.key[0].class.should == Rlint::Token::Token
|
133
|
+
token.key[0].value.should == 'name'
|
134
|
+
token.key[0].type.should == :symbol
|
135
|
+
end
|
136
|
+
end
|