ruby-lint 0.0.1a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/.gitignore +5 -0
  2. data/.rbenv-version +1 -0
  3. data/.yardopts +10 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +19 -0
  6. data/MANIFEST +79 -0
  7. data/README.md +48 -0
  8. data/Rakefile +14 -0
  9. data/bin/rlint +6 -0
  10. data/doc/.gitkeep +0 -0
  11. data/doc/build/.gitkeep +0 -0
  12. data/doc/css/.gitkeep +0 -0
  13. data/doc/css/common.css +68 -0
  14. data/lib/rlint/analyze/coding_style.rb +407 -0
  15. data/lib/rlint/analyze/definitions.rb +244 -0
  16. data/lib/rlint/analyze/method_validation.rb +104 -0
  17. data/lib/rlint/analyze/shadowing_variables.rb +37 -0
  18. data/lib/rlint/analyze/undefined_variables.rb +99 -0
  19. data/lib/rlint/analyze/unused_variables.rb +103 -0
  20. data/lib/rlint/callback.rb +67 -0
  21. data/lib/rlint/cli.rb +167 -0
  22. data/lib/rlint/constant_importer.rb +102 -0
  23. data/lib/rlint/definition.rb +230 -0
  24. data/lib/rlint/formatter/text.rb +54 -0
  25. data/lib/rlint/helper/definition_resolver.rb +143 -0
  26. data/lib/rlint/helper/scoping.rb +138 -0
  27. data/lib/rlint/iterator.rb +193 -0
  28. data/lib/rlint/options.rb +58 -0
  29. data/lib/rlint/parser.rb +1252 -0
  30. data/lib/rlint/parser_error.rb +42 -0
  31. data/lib/rlint/report.rb +98 -0
  32. data/lib/rlint/token/assignment_token.rb +46 -0
  33. data/lib/rlint/token/begin_rescue_token.rb +57 -0
  34. data/lib/rlint/token/block_token.rb +17 -0
  35. data/lib/rlint/token/case_token.rb +44 -0
  36. data/lib/rlint/token/class_token.rb +24 -0
  37. data/lib/rlint/token/method_definition_token.rb +64 -0
  38. data/lib/rlint/token/method_token.rb +58 -0
  39. data/lib/rlint/token/parameters_token.rb +99 -0
  40. data/lib/rlint/token/regexp_token.rb +15 -0
  41. data/lib/rlint/token/statement_token.rb +69 -0
  42. data/lib/rlint/token/token.rb +162 -0
  43. data/lib/rlint/token/variable_token.rb +18 -0
  44. data/lib/rlint/version.rb +3 -0
  45. data/lib/rlint.rb +36 -0
  46. data/ruby-lint.gemspec +23 -0
  47. data/spec/benchmarks/memory.rb +52 -0
  48. data/spec/benchmarks/parse_parser.rb +16 -0
  49. data/spec/helper.rb +4 -0
  50. data/spec/rlint/analyze/coding_style.rb +224 -0
  51. data/spec/rlint/analyze/definitions/classes.rb +114 -0
  52. data/spec/rlint/analyze/definitions/methods.rb +91 -0
  53. data/spec/rlint/analyze/definitions/modules.rb +207 -0
  54. data/spec/rlint/analyze/definitions/variables.rb +103 -0
  55. data/spec/rlint/analyze/method_validation.rb +177 -0
  56. data/spec/rlint/analyze/shadowing_variables.rb +30 -0
  57. data/spec/rlint/analyze/undefined_variables.rb +230 -0
  58. data/spec/rlint/analyze/unused_variables.rb +225 -0
  59. data/spec/rlint/callback.rb +28 -0
  60. data/spec/rlint/constant_importer.rb +27 -0
  61. data/spec/rlint/definition.rb +96 -0
  62. data/spec/rlint/formatter/text.rb +21 -0
  63. data/spec/rlint/iterator.rb +452 -0
  64. data/spec/rlint/parser/arrays.rb +147 -0
  65. data/spec/rlint/parser/classes.rb +152 -0
  66. data/spec/rlint/parser/errors.rb +19 -0
  67. data/spec/rlint/parser/hashes.rb +136 -0
  68. data/spec/rlint/parser/methods.rb +249 -0
  69. data/spec/rlint/parser/modules.rb +49 -0
  70. data/spec/rlint/parser/objects.rb +39 -0
  71. data/spec/rlint/parser/operators.rb +75 -0
  72. data/spec/rlint/parser/procs.rb +113 -0
  73. data/spec/rlint/parser/ranges.rb +49 -0
  74. data/spec/rlint/parser/regexp.rb +31 -0
  75. data/spec/rlint/parser/scalars.rb +93 -0
  76. data/spec/rlint/parser/statements.rb +550 -0
  77. data/spec/rlint/parser/variables.rb +181 -0
  78. data/spec/rlint/report.rb +30 -0
  79. data/task/test.rake +6 -0
  80. metadata +188 -0
@@ -0,0 +1,249 @@
1
+ require File.expand_path('../../../helper', __FILE__)
2
+
3
+ describe 'Rlint::Parser' do
4
+ it 'Parse a method definition' do
5
+ token = Rlint::Parser.new('def number; return 10; end').parse[0]
6
+
7
+ token.class.should == Rlint::Token::MethodDefinitionToken
8
+ token.line.should == 1
9
+ token.column.should == 4
10
+ token.name.should == 'number'
11
+ token.visibility.should == :public
12
+ token.type.should == :method_definition
13
+
14
+ token.parameters.class.should == Rlint::Token::ParametersToken
15
+
16
+ token.value.class.should == Array
17
+ token.value.length.should == 1
18
+
19
+ token.value[0].class.should == Rlint::Token::StatementToken
20
+ token.value[0].type.should == :return
21
+
22
+ token.value[0].value.class.should == Array
23
+ token.value[0].value.length.should == 1
24
+
25
+ value = token.value[0].value[0]
26
+
27
+ value.class.should == Rlint::Token::Token
28
+ value.type.should == :integer
29
+ value.value.should == '10'
30
+ end
31
+
32
+ it 'Parse a method definition with parameters' do
33
+ code = <<-CODE
34
+ def number(a, b = 10, *args, more, &block)
35
+ return num
36
+ end
37
+ CODE
38
+
39
+ token = Rlint::Parser.new(code).parse[0]
40
+
41
+ token.class.should == Rlint::Token::MethodDefinitionToken
42
+ token.name.should == 'number'
43
+ token.line.should == 1
44
+ token.column.should == 4
45
+
46
+ params = token.parameters
47
+
48
+ params.class.should == Rlint::Token::ParametersToken
49
+ params.value.class.should == Array
50
+
51
+ # Required parameters
52
+ params.value.length.should == 1
53
+ params.value[0].class.should == Rlint::Token::VariableToken
54
+ params.value[0].name.should == 'a'
55
+
56
+ # Optional parameters
57
+ params.optional.class.should == Array
58
+ params.optional.length.should == 1
59
+
60
+ optional = params.optional[0]
61
+
62
+ optional.class.should == Rlint::Token::VariableToken
63
+ optional.name.should == 'b'
64
+
65
+ optional.value.class.should == Rlint::Token::Token
66
+ optional.value.type.should == :integer
67
+ optional.value.value.should == '10'
68
+
69
+ # Rest parameters
70
+ params.rest.name.should == 'args'
71
+ params.rest.class.should == Rlint::Token::VariableToken
72
+
73
+ # More parameters
74
+ params.more.class.should == Array
75
+ params.more.length.should == 1
76
+ params.more[0].name.should == 'more'
77
+
78
+ # Block parameters
79
+ params.block.class.should == Rlint::Token::VariableToken
80
+ params.block.name.should == 'block'
81
+ end
82
+
83
+ it 'Parse a class method definition' do
84
+ code = <<-CODE
85
+ def self.example(number = 10)
86
+ return number
87
+ end
88
+ CODE
89
+
90
+ token = Rlint::Parser.new(code).parse[0]
91
+
92
+ token.class.should == Rlint::Token::MethodDefinitionToken
93
+ token.name.should == 'example'
94
+
95
+ token.receiver.class.should == Rlint::Token::VariableToken
96
+ token.receiver.name.should == 'self'
97
+ token.receiver.type.should == :keyword
98
+
99
+ token.operator.class.should == Rlint::Token::Token
100
+ token.operator.value.should == '.'
101
+ token.operator.type.should == :period
102
+
103
+ token.parameters.class.should == Rlint::Token::ParametersToken
104
+ token.parameters.optional.class.should == Array
105
+ token.parameters.optional.length.should == 1
106
+ end
107
+
108
+ it 'Parse a private method definition' do
109
+ code = <<-CODE
110
+ private
111
+
112
+ def example
113
+ return 10
114
+ end
115
+ CODE
116
+
117
+ token = Rlint::Parser.new(code).parse[1]
118
+
119
+ token.class.should == Rlint::Token::MethodDefinitionToken
120
+ token.name.should == 'example'
121
+ token.visibility.should == :private
122
+
123
+ token.value.class.should == Array
124
+ token.value.length.should == 1
125
+ end
126
+
127
+ it 'Parse a method call' do
128
+ token = Rlint::Parser.new('puts').parse[0]
129
+
130
+ token.class.should == Rlint::Token::MethodToken
131
+ token.name.should == 'puts'
132
+ end
133
+
134
+ it 'Parse a method call with parenthesis' do
135
+ token = Rlint::Parser.new('puts()').parse[0]
136
+
137
+ token.class.should == Rlint::Token::MethodToken
138
+ token.name.should == 'puts'
139
+ end
140
+
141
+ it 'Parse a method call with parenthesis and parameters' do
142
+ token = Rlint::Parser.new('puts(10)').parse[0]
143
+
144
+ token.class.should == Rlint::Token::MethodToken
145
+ token.name.should == 'puts'
146
+
147
+ token.parameters.class.should == Array
148
+ token.parameters.length.should == 1
149
+
150
+ param = token.parameters[0]
151
+
152
+ param.class.should == Rlint::Token::Token
153
+ param.type.should == :integer
154
+ param.value.should == '10'
155
+ end
156
+
157
+ it 'Parse a method call with parameters but without parenthesis' do
158
+ token = Rlint::Parser.new('puts 10').parse[0]
159
+
160
+ token.class.should == Rlint::Token::MethodToken
161
+ token.name.should == 'puts'
162
+
163
+ token.parameters.class.should == Array
164
+ token.parameters.length.should == 1
165
+
166
+ param = token.parameters[0]
167
+
168
+ param.class.should == Rlint::Token::Token
169
+ param.type.should == :integer
170
+ param.value.should == '10'
171
+ end
172
+
173
+ it 'Parse a method called on an object with parenthesis' do
174
+ token = Rlint::Parser.new('Struct.new(:name)').parse[0]
175
+
176
+ token.class.should == Rlint::Token::MethodToken
177
+ token.name.should == 'new'
178
+
179
+ token.receiver.class.should == Rlint::Token::VariableToken
180
+ token.receiver.type.should == :constant
181
+ token.receiver.name.should == 'Struct'
182
+
183
+ token.parameters.class.should == Array
184
+ token.parameters.length.should == 1
185
+
186
+ token.parameters[0].class.should == Rlint::Token::Token
187
+ token.parameters[0].type.should == :symbol
188
+ token.parameters[0].value.should == 'name'
189
+ end
190
+
191
+ it 'Parse a method called on an object without parenthesis' do
192
+ token = Rlint::Parser.new('Struct.new :name').parse[0]
193
+
194
+ token.class.should == Rlint::Token::MethodToken
195
+ token.name.should == 'new'
196
+
197
+ token.receiver.class.should == Rlint::Token::VariableToken
198
+ token.receiver.type.should == :constant
199
+ token.receiver.name.should == 'Struct'
200
+
201
+ token.parameters.class.should == Array
202
+ token.parameters.length.should == 1
203
+
204
+ token.parameters[0].class.should == Rlint::Token::Token
205
+ token.parameters[0].type.should == :symbol
206
+ token.parameters[0].value.should == 'name'
207
+ end
208
+
209
+ it 'Parse a method called on an object with a block passed' do
210
+ token = Rlint::Parser.new('Foo.bar { |example| example }').parse[0]
211
+
212
+ token.class.should == Rlint::Token::MethodToken
213
+ token.name.should == 'bar'
214
+
215
+ token.receiver.class.should == Rlint::Token::VariableToken
216
+ token.receiver.type.should == :constant
217
+ token.receiver.name.should == 'Foo'
218
+
219
+ token.block.class.should == Rlint::Token::BlockToken
220
+ token.block.parameters.class.should == Rlint::Token::ParametersToken
221
+
222
+ token.block.parameters.value.class.should == Array
223
+ token.block.parameters.value.length.should == 1
224
+ end
225
+
226
+ it 'Parse a method call with a bare Hash as a parameter' do
227
+ token = Rlint::Parser.new('language(:name => "Ruby")').parse[0]
228
+
229
+ token.class.should == Rlint::Token::MethodToken
230
+
231
+ token.parameters.class.should == Array
232
+ token.parameters.length.should == 1
233
+
234
+ token.parameters[0].class.should == Rlint::Token::Token
235
+ token.parameters[0].type.should == :hash
236
+ end
237
+
238
+ it 'Parse a method call with a bare JSON style Hash as a parameter' do
239
+ token = Rlint::Parser.new('language(name: "Ruby")').parse[0]
240
+
241
+ token.class.should == Rlint::Token::MethodToken
242
+
243
+ token.parameters.class.should == Array
244
+ token.parameters.length.should == 1
245
+
246
+ token.parameters[0].class.should == Rlint::Token::Token
247
+ token.parameters[0].type.should == :hash
248
+ end
249
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path('../../../helper', __FILE__)
2
+
3
+ describe 'Rlint::Parser' do
4
+ it 'Parse a module' do
5
+ code = <<-CODE
6
+ module Foo
7
+ def foo
8
+ return 'foo'
9
+ end
10
+ end
11
+ CODE
12
+
13
+ token = Rlint::Parser.new(code).parse[0]
14
+
15
+ token.class.should == Rlint::Token::Token
16
+ token.type.should == :module
17
+ token.name.should == ['Foo']
18
+ token.line.should == 1
19
+ token.column.should == 7
20
+
21
+ token.value.class.should == Array
22
+ token.value.length.should == 1
23
+
24
+ token.value[0].class.should == Rlint::Token::MethodDefinitionToken
25
+ token.value[0].name.should == 'foo'
26
+ end
27
+
28
+ it 'Parse a module with multiple name segments' do
29
+ token = Rlint::Parser.new('module A::B; end').parse[0]
30
+
31
+ token.class.should == Rlint::Token::Token
32
+ token.type.should == :module
33
+ token.name.should == ['A', 'B']
34
+
35
+ token.line.should == 1
36
+ token.column.should == 7
37
+ end
38
+
39
+ it 'Parse a top level module' do
40
+ token = Rlint::Parser.new('module ::A::B; end').parse[0]
41
+
42
+ token.class.should == Rlint::Token::Token
43
+ token.type.should == :module
44
+ token.name.should == ['A', 'B']
45
+
46
+ token.line.should == 1
47
+ token.column.should == 9
48
+ end
49
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path('../../../helper', __FILE__)
2
+
3
+ describe 'Rlint::Parser' do
4
+ it 'Parse the reference of an object attribute' do
5
+ code = <<-CODE
6
+ obj = Struct.new(:name).new('Ruby')
7
+ obj.name
8
+ CODE
9
+
10
+ token = Rlint::Parser.new(code).parse[1]
11
+
12
+ token.class.should == Rlint::Token::MethodToken
13
+ token.name.should == 'name'
14
+
15
+ token.receiver.class.should == Rlint::Token::VariableToken
16
+ token.receiver.name.should == 'obj'
17
+ token.receiver.type.should == :local_variable
18
+ end
19
+
20
+ it 'Parse the assignment of a value to an object attribute' do
21
+ code = <<-CODE
22
+ obj = Struct.new(:name).new('Ruby')
23
+ obj.name = 'Ruby'
24
+ CODE
25
+
26
+ token = Rlint::Parser.new(code).parse[1]
27
+
28
+ token.class.should == Rlint::Token::AssignmentToken
29
+ token.name.should == 'name'
30
+
31
+ token.value.class.should == Rlint::Token::Token
32
+ token.value.type.should == :string
33
+ token.value.value.should == 'Ruby'
34
+
35
+ token.receiver.class.should == Rlint::Token::VariableToken
36
+ token.receiver.name.should == 'obj'
37
+ token.receiver.type.should == :local_variable
38
+ end
39
+ end
@@ -0,0 +1,75 @@
1
+ require File.expand_path('../../../helper', __FILE__)
2
+
3
+ describe 'Rlint::Parser' do
4
+ it 'Parse the use of various operators' do
5
+ ['*', '-', '+', '/', '%', '^'].each do |operator|
6
+ token = Rlint::Parser.new("10 #{operator} 2").parse[0]
7
+
8
+ token.class.should == Rlint::Token::Token
9
+ token.type.should == :binary
10
+
11
+ token.value.class.should == Array
12
+ token.value.length.should == 3
13
+
14
+ left, op, right = token.value
15
+
16
+ left.class.should == Rlint::Token::Token
17
+ left.type.should == :integer
18
+ left.value.should == '10'
19
+
20
+ op.should == operator.to_sym
21
+
22
+ right.class.should == Rlint::Token::Token
23
+ right.type.should == :integer
24
+ right.value.should == '2'
25
+ end
26
+ end
27
+
28
+ it 'Parse the use of multiple operators' do
29
+ token = Rlint::Parser.new('10 and 20 and 30').parse[0]
30
+
31
+ token.class.should == Rlint::Token::Token
32
+ token.type.should == :binary
33
+
34
+ token.value.class.should == Array
35
+ token.value.length.should == 3
36
+
37
+ first = token.value[0]
38
+ last = token.value[2]
39
+
40
+ first.class.should == Rlint::Token::Token
41
+ first.type.should == :binary
42
+ first.value.length.should == 3
43
+
44
+ first.value[0].class.should == Rlint::Token::Token
45
+ first.value[0].type.should == :integer
46
+ first.value[0].value.should == '10'
47
+
48
+ first.value[1].should == :and
49
+
50
+ first.value[2].class.should == Rlint::Token::Token
51
+ first.value[2].type.should == :integer
52
+ first.value[2].value.should == '20'
53
+
54
+ token.value[1].should == :and
55
+
56
+ last.class.should == Rlint::Token::Token
57
+ last.type.should == :integer
58
+ last.value.should == '30'
59
+ end
60
+
61
+ it 'Parse unary operators' do
62
+ token = Rlint::Parser.new('!foobar').parse[0]
63
+
64
+ token.class.should == Rlint::Token::Token
65
+ token.type.should == :unary
66
+
67
+ token.value.class.should == Array
68
+ token.value.length.should == 2
69
+
70
+ token.value[0].should == :!
71
+
72
+ token.value[1].class.should == Rlint::Token::MethodToken
73
+ token.value[1].name.should == 'foobar'
74
+ end
75
+ end
@@ -0,0 +1,113 @@
1
+ require File.expand_path('../../../helper', __FILE__)
2
+
3
+ describe 'Rlint::Parser' do
4
+ it 'Parse a Proc' do
5
+ token = Rlint::Parser.new('proc { |example| example }').parse[0]
6
+
7
+ token.class.should == Rlint::Token::MethodToken
8
+ token.name.should == 'proc'
9
+
10
+ token.block.class.should == Rlint::Token::BlockToken
11
+ token.block.parameters.class.should == Rlint::Token::ParametersToken
12
+ token.block.type.should == :block
13
+
14
+ params = token.block.parameters
15
+
16
+ params.value.class.should == Array
17
+ params.value.length.should == 1
18
+
19
+ params.value[0].class.should == Rlint::Token::VariableToken
20
+ params.value[0].type.should == :local_variable
21
+ params.value[0].name.should == 'example'
22
+
23
+ token.block.value.class.should == Array
24
+ token.block.value.length.should == 1
25
+ end
26
+
27
+ it 'Parse a proc using do/end instead of curly braces' do
28
+ token = Rlint::Parser.new('proc do |example|; example; end').parse[0]
29
+
30
+ token.class.should == Rlint::Token::MethodToken
31
+ token.name.should == 'proc'
32
+
33
+ token.block.class.should == Rlint::Token::BlockToken
34
+ token.block.parameters.class.should == Rlint::Token::ParametersToken
35
+ token.block.type.should == :block
36
+
37
+ params = token.block.parameters
38
+
39
+ params.value.class.should == Array
40
+ params.value.length.should == 1
41
+
42
+ params.value[0].class.should == Rlint::Token::VariableToken
43
+ params.value[0].type.should == :local_variable
44
+ params.value[0].name.should == 'example'
45
+
46
+ token.block.value.class.should == Array
47
+ token.block.value.length.should == 1
48
+ end
49
+
50
+ it 'Parse a Proc using Proc.new' do
51
+ token = Rlint::Parser.new('Proc.new { |example| example }').parse[0]
52
+
53
+ token.class.should == Rlint::Token::MethodToken
54
+ token.name.should == 'new'
55
+
56
+ token.receiver.class.should == Rlint::Token::VariableToken
57
+ token.receiver.name.should == 'Proc'
58
+ token.receiver.type.should == :constant
59
+
60
+ token.block.class.should == Rlint::Token::BlockToken
61
+ token.block.parameters.class.should == Rlint::Token::ParametersToken
62
+ token.block.type.should == :block
63
+
64
+ token.block.parameters.value.class.should == Array
65
+ token.block.parameters.value.length.should == 1
66
+
67
+ param = token.block.parameters.value[0]
68
+
69
+ param.class.should == Rlint::Token::VariableToken
70
+ param.name.should == 'example'
71
+ param.type.should == :local_variable
72
+ end
73
+
74
+ it 'Parse a Lambda' do
75
+ token = Rlint::Parser.new('lambda { |example| example }').parse[0]
76
+
77
+ token.class.should == Rlint::Token::MethodToken
78
+ token.name.should == 'lambda'
79
+
80
+ token.block.class.should == Rlint::Token::BlockToken
81
+ token.block.type.should == :block
82
+
83
+ token.block.parameters.class.should == Rlint::Token::ParametersToken
84
+ token.block.parameters.value.class.should == Array
85
+ token.block.parameters.value.length.should == 1
86
+
87
+ param = token.block.parameters.value[0]
88
+
89
+ param.class.should == Rlint::Token::VariableToken
90
+ param.name.should == 'example'
91
+ param.type.should == :local_variable
92
+ end
93
+
94
+ it 'Parse a Lambda using the dash rocket syntax' do
95
+ token = Rlint::Parser.new('-> example { example }').parse[0]
96
+
97
+ token.class.should == Rlint::Token::BlockToken
98
+ token.type.should == :lambda
99
+
100
+ token.parameters.class.should == Rlint::Token::ParametersToken
101
+ token.parameters.value.class.should == Array
102
+ token.parameters.value.length.should == 1
103
+
104
+ param = token.parameters.value[0]
105
+
106
+ param.class.should == Rlint::Token::VariableToken
107
+ param.name.should == 'example'
108
+ param.type.should == :local_variable
109
+
110
+ token.value.class.should == Array
111
+ token.value.length.should == 1
112
+ end
113
+ end