ruby-lint 0.0.1a
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/.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,28 @@
|
|
1
|
+
require File.expand_path('../../helper', __FILE__)
|
2
|
+
|
3
|
+
describe 'Rlint::Callback' do
|
4
|
+
it 'Add an error to a report using Rlint::Callback' do
|
5
|
+
report = Rlint::Report.new
|
6
|
+
callback = Rlint::Callback.new(report)
|
7
|
+
|
8
|
+
report.levels.each do |level|
|
9
|
+
report.messages[level].nil?.should == true
|
10
|
+
|
11
|
+
callback.send(level, "test #{level}", 1, 1)
|
12
|
+
|
13
|
+
report.messages[level].class.should == Array
|
14
|
+
report.messages[level].length.should == 1
|
15
|
+
|
16
|
+
report.messages[level][0][:message].should == "test #{level}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'Ignore errors (when disabled) when adding one using Rlint::Callback' do
|
21
|
+
report = Rlint::Report.new('(rlint)', [:warning])
|
22
|
+
callback = Rlint::Callback.new(report)
|
23
|
+
|
24
|
+
callback.send(:error, 'test error', 1, 1)
|
25
|
+
|
26
|
+
report.messages[:error].nil?.should == true
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path('../../helper', __FILE__)
|
2
|
+
|
3
|
+
describe 'Rlint::ConstantImporter' do
|
4
|
+
it 'Import methods from the Kernel constant' do
|
5
|
+
imported = Rlint::ConstantImporter.import([:Kernel])
|
6
|
+
|
7
|
+
imported.key?('Kernel').should == true
|
8
|
+
|
9
|
+
found = imported['Kernel'].lookup(:method, 'puts')
|
10
|
+
|
11
|
+
found.class.should == Rlint::Definition
|
12
|
+
|
13
|
+
found.token.class.should == Rlint::Token::MethodDefinitionToken
|
14
|
+
found.token.name.should == 'puts'
|
15
|
+
found.token.visibility.should == :public
|
16
|
+
|
17
|
+
found.token.parameters.class.should == Rlint::Token::ParametersToken
|
18
|
+
|
19
|
+
found.token.parameters.value.class.should == Array
|
20
|
+
found.token.parameters.value.length.should == 0
|
21
|
+
|
22
|
+
found.token.parameters.rest.class.should == Rlint::Token::VariableToken
|
23
|
+
found.token.parameters.rest.name.should == ''
|
24
|
+
found.token.parameters.rest.type.should == :local_variable
|
25
|
+
found.token.parameters.rest.event.should == :local_variable
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require File.expand_path('../../helper', __FILE__)
|
2
|
+
|
3
|
+
describe 'Rlint::Definition' do
|
4
|
+
it 'Look up a symbol in a scope' do
|
5
|
+
scope = Rlint::Definition.new
|
6
|
+
|
7
|
+
scope.lookup(:local_variable, 'number').should == nil
|
8
|
+
|
9
|
+
scope.add(:local_variable, 'number', 10)
|
10
|
+
|
11
|
+
scope.lookup(:local_variable, 'number').should == 10
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'Look up a symbol in a parent scope' do
|
15
|
+
parent = Rlint::Definition.new
|
16
|
+
child = Rlint::Definition.new(parent)
|
17
|
+
|
18
|
+
parent.add(:local_variable, 'number', 10)
|
19
|
+
parent.add(:global_variable, '$number', 20)
|
20
|
+
|
21
|
+
parent.lookup(:local_variable, 'number').should == 10
|
22
|
+
parent.lookup(:global_variable, '$number').should == 20
|
23
|
+
|
24
|
+
child.lookup(:local_variable, 'number').should == nil
|
25
|
+
child.lookup(:global_variable, '$number').should == 20
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'Create a scope with default Ruby constants and methods' do
|
29
|
+
scope = Rlint::Definition.new(nil, :lazy => true, :kernel => true)
|
30
|
+
found = scope.lookup(:constant, 'Kernel')
|
31
|
+
|
32
|
+
found.class.should == Rlint::Definition
|
33
|
+
|
34
|
+
method = found.lookup(:method, 'warn')
|
35
|
+
|
36
|
+
method.class.should == Rlint::Definition
|
37
|
+
|
38
|
+
method.token.class.should == Rlint::Token::MethodDefinitionToken
|
39
|
+
method.token.name.should == 'warn'
|
40
|
+
|
41
|
+
method.token.parameters.value.class.should == Array
|
42
|
+
method.token.parameters.value.length.should == 1
|
43
|
+
|
44
|
+
param = method.token.parameters.value[0]
|
45
|
+
|
46
|
+
param.class.should == Rlint::Token::VariableToken
|
47
|
+
param.name.should == ''
|
48
|
+
param.type.should == :local_variable
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'Lazy import the Time class' do
|
52
|
+
scope = Rlint::Definition.new
|
53
|
+
|
54
|
+
scope.lookup(:constant, 'Time').nil?.should == true
|
55
|
+
|
56
|
+
scope = Rlint::Definition.new(nil, :lazy => true)
|
57
|
+
|
58
|
+
scope.lookup(:constant, 'Time').class.should == Rlint::Definition
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'Lazy import the Encoding class and a child constant' do
|
62
|
+
scope = Rlint::Definition.new(nil, :lazy => true)
|
63
|
+
enc = scope.lookup(:constant, 'Encoding')
|
64
|
+
|
65
|
+
enc.class.should == Rlint::Definition
|
66
|
+
|
67
|
+
enc.lookup(:constant, 'BINARY').class.should == Rlint::Definition
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'Lazy import Rlint::Definition' do
|
71
|
+
scope = Rlint::Definition.new(nil, :lazy => true)
|
72
|
+
|
73
|
+
rlint = scope.lookup(:constant, 'Rlint')
|
74
|
+
|
75
|
+
rlint.class.should == Rlint::Definition
|
76
|
+
|
77
|
+
rlint_scope = rlint.lookup(:constant, 'Definition')
|
78
|
+
|
79
|
+
rlint_scope.class.should == Rlint::Definition
|
80
|
+
|
81
|
+
rlint_scope.lookup(:constant, 'LOOKUP_PARENT').class.should == Rlint::Definition
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'Create a scope with multiple parent scopes' do
|
85
|
+
scope_1 = Rlint::Definition.new
|
86
|
+
scope_2 = Rlint::Definition.new
|
87
|
+
|
88
|
+
scope_1.add(:method, 'method_1', true)
|
89
|
+
scope_2.add(:method, 'method_2', true)
|
90
|
+
|
91
|
+
scope_3 = Rlint::Definition.new([scope_1, scope_2])
|
92
|
+
|
93
|
+
scope_3.lookup(:method, 'method_1').should == true
|
94
|
+
scope_3.lookup(:method, 'method_2').should == true
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path('../../../helper', __FILE__)
|
2
|
+
|
3
|
+
describe 'Rlint::Formatter::Text' do
|
4
|
+
it 'Format a report in plain text' do
|
5
|
+
report_a = Rlint::Report.new('a.rb')
|
6
|
+
report_b = Rlint::Report.new('b.rb')
|
7
|
+
formatter = Rlint::Formatter::Text.new
|
8
|
+
|
9
|
+
report_a.add(:info, 'test info', 2, 1)
|
10
|
+
|
11
|
+
report_b.add(:error, 'test error', 1, 1)
|
12
|
+
report_b.add(:info, 'test info b.rb', 3, 1)
|
13
|
+
|
14
|
+
output_a = 'a.rb: info: line 2, column 1: test info'
|
15
|
+
output_b = "b.rb: error: line 1, column 1: test error\n" \
|
16
|
+
'b.rb: info: line 3, column 1: test info b.rb'
|
17
|
+
|
18
|
+
formatter.format(report_a).should == output_a
|
19
|
+
formatter.format(report_b).should == output_b
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,452 @@
|
|
1
|
+
require File.expand_path('../../helper', __FILE__)
|
2
|
+
|
3
|
+
describe 'Rlint::Iterator' do
|
4
|
+
it 'Iterate over a simple AST' do
|
5
|
+
code = <<-CODE
|
6
|
+
number = 10
|
7
|
+
number
|
8
|
+
CODE
|
9
|
+
|
10
|
+
tokens = Rlint::Parser.new(code).parse
|
11
|
+
iterator = Rlint::Iterator.new
|
12
|
+
|
13
|
+
callback = Class.new(Rlint::Callback) do
|
14
|
+
attr_reader :assigned
|
15
|
+
attr_reader :referenced
|
16
|
+
|
17
|
+
def on_assignment(token)
|
18
|
+
@assigned = true
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_local_variable(token)
|
22
|
+
@referenced = true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
iterator.bind(callback)
|
27
|
+
|
28
|
+
iterator.run(tokens)
|
29
|
+
|
30
|
+
iterator.callbacks[0].assigned.should == true
|
31
|
+
iterator.callbacks[0].referenced.should == true
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'Iterate over a multi dimensional AST' do
|
35
|
+
code = <<-CODE
|
36
|
+
class Foo
|
37
|
+
def initialize
|
38
|
+
@number = 10
|
39
|
+
end
|
40
|
+
end
|
41
|
+
CODE
|
42
|
+
|
43
|
+
tokens = Rlint::Parser.new(code).parse
|
44
|
+
iterator = Rlint::Iterator.new
|
45
|
+
callback = Class.new(Rlint::Callback) do
|
46
|
+
attr_reader :class_name
|
47
|
+
attr_reader :method_name
|
48
|
+
attr_reader :assigned
|
49
|
+
|
50
|
+
def on_class(token)
|
51
|
+
@class_name = token.name[0]
|
52
|
+
end
|
53
|
+
|
54
|
+
def on_method_definition(token)
|
55
|
+
@method_name = token.name
|
56
|
+
end
|
57
|
+
|
58
|
+
def on_assignment(token)
|
59
|
+
@assigned = true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
iterator.bind(callback)
|
64
|
+
|
65
|
+
iterator.run(tokens)
|
66
|
+
|
67
|
+
iterator.callbacks[0].class_name.should == 'Foo'
|
68
|
+
iterator.callbacks[0].method_name.should == 'initialize'
|
69
|
+
iterator.callbacks[0].assigned.should == true
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'Call an event after iterating over a node' do
|
73
|
+
code = <<-CODE
|
74
|
+
def some_method
|
75
|
+
return 10
|
76
|
+
end
|
77
|
+
CODE
|
78
|
+
|
79
|
+
tokens = Rlint::Parser.new(code).parse
|
80
|
+
iterator = Rlint::Iterator.new
|
81
|
+
callback = Class.new(Rlint::Callback) do
|
82
|
+
attr_reader :before
|
83
|
+
attr_reader :after
|
84
|
+
|
85
|
+
def on_method_definition(token)
|
86
|
+
@before = token.name
|
87
|
+
end
|
88
|
+
|
89
|
+
def after_method_definition(token)
|
90
|
+
@after = token.name
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
iterator.bind(callback)
|
95
|
+
iterator.run(tokens)
|
96
|
+
|
97
|
+
iterator.callbacks[0].before.should == 'some_method'
|
98
|
+
iterator.callbacks[0].after.should == 'some_method'
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'Iterate over a begin/rescue statement' do
|
102
|
+
code = <<-CODE
|
103
|
+
begin
|
104
|
+
raise
|
105
|
+
rescue RuntimeError => e
|
106
|
+
puts 'runtime error!'
|
107
|
+
end
|
108
|
+
CODE
|
109
|
+
|
110
|
+
tokens = Rlint::Parser.new(code).parse
|
111
|
+
iterator = Rlint::Iterator.new
|
112
|
+
callback = Class.new(Rlint::Callback) do
|
113
|
+
attr_reader :method_names
|
114
|
+
attr_reader :exception
|
115
|
+
attr_reader :exception_var
|
116
|
+
|
117
|
+
def initialize(*args)
|
118
|
+
super
|
119
|
+
|
120
|
+
@method_names = []
|
121
|
+
end
|
122
|
+
|
123
|
+
def on_method(token)
|
124
|
+
@method_names << token.name
|
125
|
+
end
|
126
|
+
|
127
|
+
def on_constant(token)
|
128
|
+
@exception = token.name
|
129
|
+
end
|
130
|
+
|
131
|
+
def on_identifier(token)
|
132
|
+
@exception_var = token.name
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
iterator.bind(callback)
|
137
|
+
iterator.run(tokens)
|
138
|
+
|
139
|
+
obj = iterator.callbacks[0]
|
140
|
+
|
141
|
+
obj.method_names.should == ['raise', 'puts']
|
142
|
+
obj.exception.should == 'RuntimeError'
|
143
|
+
obj.exception_var.should == 'e'
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'Iterate over an if statement' do
|
147
|
+
code = <<-CODE
|
148
|
+
a, b, c, d, e, f = [1, 2, 3, 4, 5, 6]
|
149
|
+
|
150
|
+
if a == b
|
151
|
+
first
|
152
|
+
elsif c == d
|
153
|
+
second
|
154
|
+
elsif e == f
|
155
|
+
third
|
156
|
+
else
|
157
|
+
fourth
|
158
|
+
end
|
159
|
+
CODE
|
160
|
+
|
161
|
+
tokens = Rlint::Parser.new(code).parse
|
162
|
+
iterator = Rlint::Iterator.new
|
163
|
+
callback = Class.new(Rlint::Callback) do
|
164
|
+
attr_reader :variables
|
165
|
+
attr_reader :methods
|
166
|
+
|
167
|
+
def initialize(*args)
|
168
|
+
super
|
169
|
+
|
170
|
+
@variables = []
|
171
|
+
@methods = []
|
172
|
+
end
|
173
|
+
|
174
|
+
def on_local_variable(token)
|
175
|
+
@variables << token.name
|
176
|
+
end
|
177
|
+
|
178
|
+
def on_method(token)
|
179
|
+
@methods << token.name
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
iterator.bind(callback)
|
184
|
+
iterator.run(tokens)
|
185
|
+
|
186
|
+
obj = iterator.callbacks[0]
|
187
|
+
|
188
|
+
obj.variables.should == %w{a b c d e f}
|
189
|
+
obj.methods.should == %w{first second third fourth}
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'Iterate over a case statement' do
|
193
|
+
code = <<-CODE
|
194
|
+
case number
|
195
|
+
when 10
|
196
|
+
first
|
197
|
+
when 20
|
198
|
+
second
|
199
|
+
when 30
|
200
|
+
third
|
201
|
+
else
|
202
|
+
fourth
|
203
|
+
end
|
204
|
+
CODE
|
205
|
+
|
206
|
+
tokens = Rlint::Parser.new(code).parse
|
207
|
+
iterator = Rlint::Iterator.new
|
208
|
+
callback = Class.new(Rlint::Callback) do
|
209
|
+
attr_reader :methods
|
210
|
+
attr_reader :numbers
|
211
|
+
|
212
|
+
def initialize(*args)
|
213
|
+
super
|
214
|
+
|
215
|
+
@methods = []
|
216
|
+
@numbers = []
|
217
|
+
end
|
218
|
+
|
219
|
+
def on_method(token)
|
220
|
+
@methods << token.name
|
221
|
+
end
|
222
|
+
|
223
|
+
def on_integer(token)
|
224
|
+
@numbers << token.value
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
iterator.bind(callback)
|
229
|
+
iterator.run(tokens)
|
230
|
+
|
231
|
+
obj = iterator.callbacks[0]
|
232
|
+
|
233
|
+
obj.numbers.should == %w{10 20 30}
|
234
|
+
obj.methods.should == %w{number first second third fourth}
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'Iterate over a for loop' do
|
238
|
+
code = <<-CODE
|
239
|
+
for key, value in {:name => 'Ruby'}
|
240
|
+
puts key
|
241
|
+
end
|
242
|
+
CODE
|
243
|
+
|
244
|
+
tokens = Rlint::Parser.new(code).parse
|
245
|
+
iterator = Rlint::Iterator.new
|
246
|
+
callback = Class.new(Rlint::Callback) do
|
247
|
+
attr_reader :symbol
|
248
|
+
attr_reader :string
|
249
|
+
attr_reader :names
|
250
|
+
|
251
|
+
def initialize(*args)
|
252
|
+
super
|
253
|
+
|
254
|
+
@names = []
|
255
|
+
end
|
256
|
+
|
257
|
+
def on_local_variable(token)
|
258
|
+
@names << token.name
|
259
|
+
end
|
260
|
+
|
261
|
+
def on_identifier(token)
|
262
|
+
@names << token.name
|
263
|
+
end
|
264
|
+
|
265
|
+
def on_symbol(token)
|
266
|
+
@symbol = token.name
|
267
|
+
end
|
268
|
+
|
269
|
+
def on_string(token)
|
270
|
+
@string = token.value
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
iterator.bind(callback)
|
275
|
+
iterator.run(tokens)
|
276
|
+
|
277
|
+
obj = iterator.callbacks[0]
|
278
|
+
|
279
|
+
obj.symbol.should == 'name'
|
280
|
+
obj.string.should == 'Ruby'
|
281
|
+
obj.names.should == %w{key value key}
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'Iterate over a while statement' do
|
285
|
+
code = <<-CODE
|
286
|
+
while foo == 10
|
287
|
+
puts 20
|
288
|
+
end
|
289
|
+
CODE
|
290
|
+
|
291
|
+
tokens = Rlint::Parser.new(code).parse
|
292
|
+
iterator = Rlint::Iterator.new
|
293
|
+
callback = Class.new(Rlint::Callback) do
|
294
|
+
attr_reader :numbers
|
295
|
+
attr_reader :methods
|
296
|
+
|
297
|
+
def initialize(*args)
|
298
|
+
super
|
299
|
+
|
300
|
+
@numbers = []
|
301
|
+
@methods = []
|
302
|
+
end
|
303
|
+
|
304
|
+
def on_identifier(token)
|
305
|
+
@methods << token.name
|
306
|
+
end
|
307
|
+
|
308
|
+
def on_method(token)
|
309
|
+
@methods << token.name
|
310
|
+
end
|
311
|
+
|
312
|
+
def on_integer(token)
|
313
|
+
@numbers << token.value
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
iterator.bind(callback)
|
318
|
+
iterator.run(tokens)
|
319
|
+
|
320
|
+
obj = iterator.callbacks[0]
|
321
|
+
|
322
|
+
obj.methods.should == %w{foo puts}
|
323
|
+
obj.numbers.should == %w{10 20}
|
324
|
+
end
|
325
|
+
|
326
|
+
it 'Iterate over a method definition' do
|
327
|
+
code = <<-CODE
|
328
|
+
def foobar(required, optional = 10, *rest, more, &block)
|
329
|
+
return 20
|
330
|
+
end
|
331
|
+
CODE
|
332
|
+
|
333
|
+
tokens = Rlint::Parser.new(code).parse
|
334
|
+
iterator = Rlint::Iterator.new
|
335
|
+
callback = Class.new(Rlint::Callback) do
|
336
|
+
attr_reader :variables
|
337
|
+
attr_reader :numbers
|
338
|
+
|
339
|
+
def initialize(*args)
|
340
|
+
super
|
341
|
+
|
342
|
+
@variables = []
|
343
|
+
@numbers = []
|
344
|
+
end
|
345
|
+
|
346
|
+
def on_local_variable(token)
|
347
|
+
@variables << token.name
|
348
|
+
end
|
349
|
+
|
350
|
+
def on_integer(token)
|
351
|
+
@numbers << token.value
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
iterator.bind(callback)
|
356
|
+
iterator.run(tokens)
|
357
|
+
|
358
|
+
obj = iterator.callbacks[0]
|
359
|
+
|
360
|
+
obj.numbers.should == %w{10 20}
|
361
|
+
obj.variables.should == %w{required optional rest more block}
|
362
|
+
end
|
363
|
+
|
364
|
+
it 'Iterate over a method call' do
|
365
|
+
tokens = Rlint::Parser.new('puts "Foo", "Bar"').parse
|
366
|
+
iterator = Rlint::Iterator.new
|
367
|
+
callback = Class.new(Rlint::Callback) do
|
368
|
+
attr_reader :params
|
369
|
+
|
370
|
+
def initialize(*args)
|
371
|
+
@params = []
|
372
|
+
end
|
373
|
+
|
374
|
+
def on_string(token)
|
375
|
+
@params << token.value
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
iterator.bind(callback)
|
380
|
+
iterator.run(tokens)
|
381
|
+
|
382
|
+
obj = iterator.callbacks[0]
|
383
|
+
|
384
|
+
obj.params.should == %w{Foo Bar}
|
385
|
+
end
|
386
|
+
|
387
|
+
it 'Call an event before and after iterating over all nodes' do
|
388
|
+
code = <<-CODE
|
389
|
+
class Person
|
390
|
+
def initialize
|
391
|
+
@name = 'Matz'
|
392
|
+
end
|
393
|
+
end
|
394
|
+
CODE
|
395
|
+
|
396
|
+
tokens = Rlint::Parser.new(code).parse
|
397
|
+
iterator = Rlint::Iterator.new
|
398
|
+
callback = Class.new(Rlint::Callback) do
|
399
|
+
attr_reader :start
|
400
|
+
attr_reader :finish
|
401
|
+
|
402
|
+
def initialize(*args)
|
403
|
+
super
|
404
|
+
|
405
|
+
@start = 0
|
406
|
+
@finish = 0
|
407
|
+
end
|
408
|
+
|
409
|
+
def on_start
|
410
|
+
@start += 1
|
411
|
+
end
|
412
|
+
|
413
|
+
def on_finish
|
414
|
+
@finish += 1
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
iterator.bind(callback)
|
419
|
+
iterator.run(tokens)
|
420
|
+
|
421
|
+
iterator.callbacks[0].start.should == 1
|
422
|
+
iterator.callbacks[0].finish.should == 1
|
423
|
+
end
|
424
|
+
|
425
|
+
it 'Share data between callback classes' do
|
426
|
+
code = <<-CODE
|
427
|
+
def example_method
|
428
|
+
return 10
|
429
|
+
end
|
430
|
+
CODE
|
431
|
+
|
432
|
+
tokens = Rlint::Parser.new(code).parse
|
433
|
+
iterator = Rlint::Iterator.new
|
434
|
+
|
435
|
+
setter = Class.new(Rlint::Callback) do
|
436
|
+
def on_method_definition(token)
|
437
|
+
@storage[:method_name] = token.name
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
getter = Class.new(Rlint::Callback) do
|
442
|
+
attr_reader :storage
|
443
|
+
end
|
444
|
+
|
445
|
+
iterator.bind(setter)
|
446
|
+
iterator.bind(getter)
|
447
|
+
iterator.run(tokens)
|
448
|
+
|
449
|
+
iterator.callbacks[1].storage.class.should == Hash
|
450
|
+
iterator.callbacks[1].storage[:method_name].should == 'example_method'
|
451
|
+
end
|
452
|
+
end
|