code_analyzer 0.4.8 → 0.5.3
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.
- checksums.yaml +5 -5
- data/.github/workflows/main.yml +31 -0
- data/.ruby-version +1 -0
- data/README.md +1 -7
- data/code_analyzer.gemspec +2 -1
- data/lib/code_analyzer/analyzer_exception.rb +2 -1
- data/lib/code_analyzer/checker.rb +5 -8
- data/lib/code_analyzer/checking_visitor/base.rb +3 -2
- data/lib/code_analyzer/checking_visitor/default.rb +9 -12
- data/lib/code_analyzer/checking_visitor/plain.rb +3 -4
- data/lib/code_analyzer/checking_visitor.rb +5 -4
- data/lib/code_analyzer/nil.rb +2 -1
- data/lib/code_analyzer/sexp.rb +132 -111
- data/lib/code_analyzer/version.rb +3 -2
- data/lib/code_analyzer/warning.rb +3 -2
- data/lib/code_analyzer.rb +10 -9
- data/spec/code_analyzer/checker_spec.rb +19 -17
- data/spec/code_analyzer/checking_visitor/base_spec.rb +2 -0
- data/spec/code_analyzer/checking_visitor/default_spec.rb +14 -12
- data/spec/code_analyzer/checking_visitor/plain_spec.rb +6 -4
- data/spec/code_analyzer/nil_spec.rb +12 -10
- data/spec/code_analyzer/sexp_spec.rb +469 -339
- data/spec/code_analyzer/warning_spec.rb +6 -6
- data/spec/spec_helper.rb +3 -1
- metadata +8 -8
- data/.travis.yml +0 -5
data/lib/code_analyzer/sexp.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'sexp'
|
3
4
|
|
4
5
|
class Sexp
|
@@ -13,22 +14,23 @@ class Sexp
|
|
13
14
|
#
|
14
15
|
# s(:@ident, "test", s(2, 12)
|
15
16
|
# => 2
|
17
|
+
|
16
18
|
def line_number
|
17
19
|
case sexp_type
|
18
|
-
when :def, :defs, :command, :command_call, :call, :fcall, :method_add_arg, :method_add_block,
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:alias, :symbol_literal, :symbol, :aref, :hash, :assoc_new, :string_literal,
|
22
|
-
:massign
|
20
|
+
when :def, :defs, :command, :command_call, :call, :fcall, :method_add_arg, :method_add_block, :var_ref, :vcall,
|
21
|
+
:const_ref, :top_const_ref, :const_path_ref, :class, :module, :if, :unless, :elsif, :ifop, :if_mod, :unless_mod, :binary, :alias,
|
22
|
+
:symbol_literal, :symbol, :aref, :hash, :assoc_new, :string_literal, :massign, :var_field, :assign, :paren, :dot2, :dot3
|
23
23
|
self[1].line_number
|
24
24
|
when :assoclist_from_args, :bare_assoc_hash
|
25
25
|
self[1][0].line_number
|
26
|
-
when :string_add, :opassign
|
26
|
+
when :string_add, :opassign, :unary, :stmts_add
|
27
27
|
self[2].line_number
|
28
28
|
when :array
|
29
29
|
array_values.first.line_number
|
30
30
|
when :mlhs_add
|
31
31
|
self.last.line_number
|
32
|
+
when :params
|
33
|
+
self[1][0].line_number if self[1].is_a? Array
|
32
34
|
else
|
33
35
|
self.last.first if self.last.is_a? Array
|
34
36
|
end
|
@@ -38,7 +40,7 @@ class Sexp
|
|
38
40
|
#
|
39
41
|
# @return [Array] child nodes.
|
40
42
|
def children
|
41
|
-
find_all { |
|
43
|
+
find_all { |sexp| Sexp === sexp }
|
42
44
|
end
|
43
45
|
|
44
46
|
# recursively find all child nodes, and yeild each child node.
|
@@ -68,10 +70,17 @@ class Sexp
|
|
68
70
|
message = options[:message]
|
69
71
|
to_s = options[:to_s]
|
70
72
|
self.recursive_children do |child|
|
71
|
-
if (
|
72
|
-
|
73
|
-
|
74
|
-
|
73
|
+
if (
|
74
|
+
!sexp_type || (sexp_type.is_a?(Array) ? sexp_type.include?(child.sexp_type) : sexp_type == child.sexp_type)
|
75
|
+
) &&
|
76
|
+
(
|
77
|
+
!receiver ||
|
78
|
+
(receiver.is_a?(Array) ? receiver.include?(child.receiver.to_s) : receiver == child.receiver.to_s)
|
79
|
+
) &&
|
80
|
+
(
|
81
|
+
!message || (message.is_a?(Array) ? message.include?(child.message.to_s) : message == child.message.to_s)
|
82
|
+
) &&
|
83
|
+
(!to_s || (to_s.is_a?(Array) ? to_s.include?(child.to_s) : to_s == child.to_s))
|
75
84
|
yield child
|
76
85
|
end
|
77
86
|
end
|
@@ -91,7 +100,10 @@ class Sexp
|
|
91
100
|
# the condition value can be Symbol, Array or Sexp.
|
92
101
|
def grep_node(options)
|
93
102
|
result = CodeAnalyzer::Nil.new
|
94
|
-
grep_nodes(options)
|
103
|
+
grep_nodes(options) do |node|
|
104
|
+
result = node
|
105
|
+
break
|
106
|
+
end
|
95
107
|
result
|
96
108
|
end
|
97
109
|
|
@@ -138,9 +150,7 @@ class Sexp
|
|
138
150
|
#
|
139
151
|
# @return [Sexp] module name node
|
140
152
|
def module_name
|
141
|
-
if :module == sexp_type
|
142
|
-
self[1]
|
143
|
-
end
|
153
|
+
self[1] if :module == sexp_type
|
144
154
|
end
|
145
155
|
|
146
156
|
# Get the class name of the class node.
|
@@ -154,9 +164,7 @@ class Sexp
|
|
154
164
|
#
|
155
165
|
# @return [Sexp] class name node
|
156
166
|
def class_name
|
157
|
-
if :class == sexp_type
|
158
|
-
self[1]
|
159
|
-
end
|
167
|
+
self[1] if :class == sexp_type
|
160
168
|
end
|
161
169
|
|
162
170
|
# Get the base class of the class node.
|
@@ -170,9 +178,7 @@ class Sexp
|
|
170
178
|
#
|
171
179
|
# @return [Sexp] base class of class node
|
172
180
|
def base_class
|
173
|
-
if :class == sexp_type
|
174
|
-
self[2]
|
175
|
-
end
|
181
|
+
self[2] if :class == sexp_type
|
176
182
|
end
|
177
183
|
|
178
184
|
# Get the left value of the assign node.
|
@@ -185,9 +191,7 @@ class Sexp
|
|
185
191
|
#
|
186
192
|
# @return [Symbol] left value of lasgn or iasgn node
|
187
193
|
def left_value
|
188
|
-
if :assign == sexp_type
|
189
|
-
self[1]
|
190
|
-
end
|
194
|
+
self[1] if :assign == sexp_type
|
191
195
|
end
|
192
196
|
|
193
197
|
# Get the right value of assign node.
|
@@ -200,9 +204,7 @@ class Sexp
|
|
200
204
|
#
|
201
205
|
# @return [Sexp] right value of assign node
|
202
206
|
def right_value
|
203
|
-
if :assign == sexp_type
|
204
|
-
self[2]
|
205
|
-
end
|
207
|
+
self[2] if :assign == sexp_type
|
206
208
|
end
|
207
209
|
|
208
210
|
# Get the message node.
|
@@ -277,9 +279,7 @@ class Sexp
|
|
277
279
|
#
|
278
280
|
# @return [Sexp] argument node
|
279
281
|
def argument
|
280
|
-
if :binary == sexp_type
|
281
|
-
self[3]
|
282
|
-
end
|
282
|
+
self[3] if :binary == sexp_type
|
283
283
|
end
|
284
284
|
|
285
285
|
# Get all arguments.
|
@@ -305,7 +305,7 @@ class Sexp
|
|
305
305
|
else
|
306
306
|
node = self[1]
|
307
307
|
while true
|
308
|
-
if [
|
308
|
+
if %i[args_add args_add_star].include? node.sexp_type
|
309
309
|
nodes.unshift node[2]
|
310
310
|
node = node[1]
|
311
311
|
elsif :args_new == node.sexp_type
|
@@ -330,9 +330,7 @@ class Sexp
|
|
330
330
|
#
|
331
331
|
# @return [Sexp] conditional statement of if node
|
332
332
|
def conditional_statement
|
333
|
-
if [
|
334
|
-
self[1]
|
335
|
-
end
|
333
|
+
self[1] if %i[if unless elsif ifop if_mod unless_mod].include? sexp_type
|
336
334
|
end
|
337
335
|
|
338
336
|
# Get all condition nodes.
|
@@ -366,13 +364,13 @@ class Sexp
|
|
366
364
|
# @return [Array] all condition nodes
|
367
365
|
def all_conditions
|
368
366
|
nodes = []
|
369
|
-
if :binary == sexp_type && %w
|
370
|
-
if :binary == self[1].sexp_type && %w
|
367
|
+
if :binary == sexp_type && %w[&& || and or].include?(self[2].to_s)
|
368
|
+
if :binary == self[1].sexp_type && %w[&& || and or].include?(self[1][2].to_s)
|
371
369
|
nodes += self[1].all_conditions
|
372
370
|
else
|
373
371
|
nodes << self[1]
|
374
372
|
end
|
375
|
-
if :binary == self[3].sexp_type && %w
|
373
|
+
if :binary == self[3].sexp_type && %w[&& || and or].include?(self[3][2].to_s)
|
376
374
|
nodes += self[3].all_conditions
|
377
375
|
else
|
378
376
|
nodes << self[3]
|
@@ -392,6 +390,7 @@ class Sexp
|
|
392
390
|
# => s(:@ident, "show", s(1, 4)),
|
393
391
|
#
|
394
392
|
# @return [Sexp] method name node
|
393
|
+
|
395
394
|
def method_name
|
396
395
|
case sexp_type
|
397
396
|
when :def
|
@@ -399,6 +398,7 @@ class Sexp
|
|
399
398
|
when :defs
|
400
399
|
self[3]
|
401
400
|
else
|
401
|
+
|
402
402
|
end
|
403
403
|
end
|
404
404
|
|
@@ -428,6 +428,7 @@ class Sexp
|
|
428
428
|
# )
|
429
429
|
#
|
430
430
|
# @return [Sexp] body node
|
431
|
+
|
431
432
|
def body
|
432
433
|
case sexp_type
|
433
434
|
when :else
|
@@ -506,13 +507,15 @@ class Sexp
|
|
506
507
|
# @return [Array] all statements
|
507
508
|
def statements
|
508
509
|
stmts = []
|
509
|
-
node =
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
510
|
+
node =
|
511
|
+
case sexp_type
|
512
|
+
when :do_block, :brace_block
|
513
|
+
self[2][1]
|
514
|
+
when :bodystmt
|
515
|
+
self[1]
|
516
|
+
else
|
517
|
+
|
518
|
+
end
|
516
519
|
if node
|
517
520
|
while true
|
518
521
|
if :stmts_add == node.sexp_type && s(:void_stmt) != node[2]
|
@@ -542,6 +545,7 @@ class Sexp
|
|
542
545
|
def exception_classes
|
543
546
|
if :rescue == sexp_type
|
544
547
|
return [] unless self[1]
|
548
|
+
|
545
549
|
if :mrhs_add == self[1].sexp_type
|
546
550
|
exceptions = Array.new(self[1][2])
|
547
551
|
arg_nodes = self[1][1][1]
|
@@ -566,9 +570,7 @@ class Sexp
|
|
566
570
|
# )
|
567
571
|
# => s(:var_field, s(:@ident, "e", s(1, 20)))
|
568
572
|
def exception_variable
|
569
|
-
if :rescue == sexp_type
|
570
|
-
self[2]
|
571
|
-
end
|
573
|
+
self[2] if :rescue == sexp_type
|
572
574
|
end
|
573
575
|
|
574
576
|
# Get hash value node.
|
@@ -585,20 +587,17 @@ class Sexp
|
|
585
587
|
#
|
586
588
|
# @return [Sexp] hash value node
|
587
589
|
def hash_value(key)
|
588
|
-
pair_nodes =
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
pair_nodes.size.times do |i|
|
597
|
-
if key == pair_nodes[i][1].to_s
|
598
|
-
return pair_nodes[i][2]
|
599
|
-
end
|
590
|
+
pair_nodes =
|
591
|
+
case sexp_type
|
592
|
+
when :bare_assoc_hash
|
593
|
+
self[1]
|
594
|
+
when :hash
|
595
|
+
self[1][1]
|
596
|
+
else
|
597
|
+
|
600
598
|
end
|
601
|
-
|
599
|
+
|
600
|
+
pair_nodes.size.times { |i| return pair_nodes[i][2] if key == pair_nodes[i][1].to_s } if pair_nodes
|
602
601
|
CodeAnalyzer::Nil.new
|
603
602
|
end
|
604
603
|
|
@@ -640,18 +639,18 @@ class Sexp
|
|
640
639
|
#
|
641
640
|
# @return [Array] hash keys
|
642
641
|
def hash_keys
|
643
|
-
pair_nodes =
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
642
|
+
pair_nodes =
|
643
|
+
case sexp_type
|
644
|
+
when :bare_assoc_hash
|
645
|
+
self[1]
|
646
|
+
when :hash
|
647
|
+
self[1][1]
|
648
|
+
else
|
649
|
+
|
650
|
+
end
|
650
651
|
if pair_nodes
|
651
652
|
keys = []
|
652
|
-
pair_nodes.size.times
|
653
|
-
keys << pair_nodes[i][1].to_s
|
654
|
-
end
|
653
|
+
pair_nodes.size.times { |i| keys << pair_nodes[i][1].to_s }
|
655
654
|
keys
|
656
655
|
end
|
657
656
|
end
|
@@ -673,22 +672,44 @@ class Sexp
|
|
673
672
|
#
|
674
673
|
# @return [Array] hash values
|
675
674
|
def hash_values
|
676
|
-
pair_nodes =
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
675
|
+
pair_nodes =
|
676
|
+
case sexp_type
|
677
|
+
when :bare_assoc_hash
|
678
|
+
self[1]
|
679
|
+
when :hash
|
680
|
+
self[1][1]
|
681
|
+
else
|
682
|
+
|
683
|
+
end
|
683
684
|
if pair_nodes
|
684
685
|
values = []
|
685
|
-
pair_nodes.size.times
|
686
|
-
values << pair_nodes[i][2]
|
687
|
-
end
|
686
|
+
pair_nodes.size.times { |i| values << pair_nodes[i][2] }
|
688
687
|
values
|
689
688
|
end
|
690
689
|
end
|
691
690
|
|
691
|
+
# Get the hash key
|
692
|
+
#
|
693
|
+
# s(:assoc_new, s(:@label, "first_name:", s(1, 1)), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Richard", s(1, 14)))))
|
694
|
+
# =>
|
695
|
+
# s(:@label, "first_name:", s(1, 1))
|
696
|
+
def key
|
697
|
+
if :assoc_new == sexp_type
|
698
|
+
self[1].to_s
|
699
|
+
end
|
700
|
+
end
|
701
|
+
|
702
|
+
# Get the hash value
|
703
|
+
#
|
704
|
+
# s(:assoc_new, s(:@label, "first_name:", s(1, 1)), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Richard", s(1, 14)))))
|
705
|
+
# =>
|
706
|
+
# s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Richard", s(1, 14))))
|
707
|
+
def value
|
708
|
+
if :assoc_new == sexp_type
|
709
|
+
self[2].to_s
|
710
|
+
end
|
711
|
+
end
|
712
|
+
|
692
713
|
# Get the array size.
|
693
714
|
#
|
694
715
|
# s(:array,
|
@@ -709,9 +730,7 @@ class Sexp
|
|
709
730
|
array_size += 1
|
710
731
|
first_node = s(:args_new) == first_node[1] ? first_node[2] : first_node[1]
|
711
732
|
if :args_add != first_node.sexp_type
|
712
|
-
if :array == first_node.sexp_type
|
713
|
-
array_size += first_node.array_size
|
714
|
-
end
|
733
|
+
array_size += first_node.array_size if :array == first_node.sexp_type
|
715
734
|
break
|
716
735
|
end
|
717
736
|
end
|
@@ -737,9 +756,9 @@ class Sexp
|
|
737
756
|
def array_values
|
738
757
|
case sexp_type
|
739
758
|
when :array
|
740
|
-
if nil == self[1] || [
|
759
|
+
if nil == self[1] || %i[words_new qwords_new symbols_new qsymbols_new].include?(self[1].sexp_type)
|
741
760
|
[]
|
742
|
-
elsif [
|
761
|
+
elsif %i[words_add qwords_add symbols_add qsymbols_add].include? self[1].sexp_type
|
743
762
|
self[1].array_values
|
744
763
|
else
|
745
764
|
arguments.all
|
@@ -748,10 +767,10 @@ class Sexp
|
|
748
767
|
values = []
|
749
768
|
node = self
|
750
769
|
while true
|
751
|
-
if [
|
770
|
+
if %i[words_add qwords_add symbols_add qsymbols_add].include? node.sexp_type
|
752
771
|
values.unshift node[2]
|
753
772
|
node = node[1]
|
754
|
-
elsif [
|
773
|
+
elsif %i[words_new qwords_new symbols_new qsymbols_new].include? node.sexp_type
|
755
774
|
break
|
756
775
|
end
|
757
776
|
end
|
@@ -808,22 +827,13 @@ class Sexp
|
|
808
827
|
# @return [String] to_s
|
809
828
|
def to_s
|
810
829
|
case sexp_type
|
811
|
-
when :string_literal, :xstring_literal, :string_content, :const_ref, :symbol_literal, :symbol,
|
812
|
-
:
|
813
|
-
:@ident, :@tstring_content, :@const, :@ivar, :@kw, :@gvar, :@cvar
|
830
|
+
when :string_literal, :xstring_literal, :string_content, :const_ref, :symbol_literal, :symbol, :args_add_block, :var_ref,
|
831
|
+
:vcall, :var_field, :@ident, :@tstring_content, :@const, :@ivar, :@kw, :@gvar, :@cvar, :@period
|
814
832
|
self[1].to_s
|
815
833
|
when :string_add
|
816
|
-
|
817
|
-
self[2].to_s
|
818
|
-
else
|
819
|
-
self[1].to_s
|
820
|
-
end
|
834
|
+
s(:string_content) == self[1] ? self[2].to_s : self[1].to_s
|
821
835
|
when :args_add
|
822
|
-
|
823
|
-
self[2].to_s
|
824
|
-
else
|
825
|
-
self[1].to_s
|
826
|
-
end
|
836
|
+
s(:args_new) == self[1] ? self[2].to_s : self[1].to_s
|
827
837
|
when :qwords_add
|
828
838
|
self[2].to_s
|
829
839
|
when :word_add
|
@@ -839,13 +849,13 @@ class Sexp
|
|
839
849
|
when :top_const_ref
|
840
850
|
"::#{self[1]}"
|
841
851
|
else
|
842
|
-
|
852
|
+
''
|
843
853
|
end
|
844
854
|
end
|
845
855
|
|
846
856
|
# check if the self node is a const.
|
847
857
|
def const?
|
848
|
-
:@const == self.sexp_type || ([
|
858
|
+
:@const == self.sexp_type || (%i[var_ref vcall].include?(self.sexp_type) && :@const == self[1].sexp_type)
|
849
859
|
end
|
850
860
|
|
851
861
|
# true
|
@@ -865,22 +875,33 @@ class Sexp
|
|
865
875
|
if Sexp === last_node && last_node.size == 2 && last_node.first.is_a?(Integer) && last_node.last.is_a?(Integer)
|
866
876
|
node.delete_at(-1)
|
867
877
|
end
|
868
|
-
node.sexp_body.each_with_index
|
869
|
-
if Sexp === child
|
870
|
-
node[index+1] = child.remove_line_and_column
|
871
|
-
end
|
872
|
-
end
|
878
|
+
node.sexp_body.each_with_index { |child, index| node[index + 1] = child.remove_line_and_column if Sexp === child }
|
873
879
|
node
|
874
880
|
end
|
875
881
|
|
876
882
|
# if the return value of these methods is nil, then return CodeAnalyzer::Nil.new instead
|
877
|
-
[
|
878
|
-
|
883
|
+
%i[
|
884
|
+
sexp_type
|
885
|
+
receiver
|
886
|
+
message
|
887
|
+
arguments
|
888
|
+
argument
|
889
|
+
class_name
|
890
|
+
base_class
|
891
|
+
method_name
|
892
|
+
body
|
893
|
+
block_node
|
894
|
+
conditional_statement
|
895
|
+
left_value
|
896
|
+
right_value
|
897
|
+
].each do |method|
|
879
898
|
class_eval <<-EOS
|
880
899
|
alias_method :origin_#{method}, :#{method}
|
881
900
|
|
882
901
|
def #{method}
|
883
|
-
ret = origin_#{
|
902
|
+
ret = origin_#{
|
903
|
+
method
|
904
|
+
}
|
884
905
|
ret.nil? ? CodeAnalyzer::Nil.new : ret
|
885
906
|
end
|
886
907
|
EOS
|
@@ -1,4 +1,5 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module CodeAnalyzer
|
3
4
|
# Warning is the violation.
|
4
5
|
#
|
@@ -6,7 +7,7 @@ module CodeAnalyzer
|
|
6
7
|
class Warning
|
7
8
|
attr_reader :filename, :line_number, :message
|
8
9
|
|
9
|
-
def initialize(options={})
|
10
|
+
def initialize(options = {})
|
10
11
|
@filename = options[:filename]
|
11
12
|
@line_number = options[:line_number].to_s
|
12
13
|
@message = options[:message]
|
data/lib/code_analyzer.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ripper'
|
4
|
+
require 'code_analyzer/version'
|
5
|
+
require 'code_analyzer/nil'
|
6
|
+
require 'code_analyzer/sexp'
|
6
7
|
|
7
8
|
module CodeAnalyzer
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
autoload :AnalyzerException, 'code_analyzer/analyzer_exception'
|
10
|
+
autoload :Checker, 'code_analyzer/checker'
|
11
|
+
autoload :CheckingVisitor, 'code_analyzer/checking_visitor'
|
12
|
+
autoload :Warning, 'code_analyzer/warning'
|
12
13
|
end
|
@@ -1,58 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
module CodeAnalyzer
|
4
6
|
describe Checker do
|
5
7
|
let(:checker) { Checker.new }
|
6
8
|
|
7
|
-
context
|
8
|
-
it
|
9
|
+
context 'interesting_nodes' do
|
10
|
+
it 'should get empty interesting nodes' do
|
9
11
|
expect(checker.interesting_nodes).to eq []
|
10
12
|
end
|
11
13
|
|
12
|
-
it
|
14
|
+
it 'should add interesting nodes' do
|
13
15
|
Checker.interesting_nodes :class, :def
|
14
|
-
expect(checker.interesting_nodes).to eq [
|
16
|
+
expect(checker.interesting_nodes).to eq %i[class def]
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
18
|
-
context
|
19
|
-
it
|
20
|
+
context 'interesting_files' do
|
21
|
+
it 'should match none of interesting files' do
|
20
22
|
expect(checker.interesting_files).to eq []
|
21
23
|
end
|
22
24
|
|
23
|
-
it
|
25
|
+
it 'should add interesting files' do
|
24
26
|
Checker.interesting_files /lib/, /spec/
|
25
27
|
expect(checker.interesting_files).to eq [/lib/, /spec/]
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
29
|
-
context
|
30
|
-
it
|
31
|
-
allow(checker).to receive(:interesting_files).and_return([
|
32
|
-
expect(checker.parse_file?(
|
31
|
+
context '#parse_file?' do
|
32
|
+
it 'should return true if node_file matches pattern' do
|
33
|
+
allow(checker).to receive(:interesting_files).and_return([%r{spec\/.*\.rb}, %r{lib\/.*\.rb}])
|
34
|
+
expect(checker.parse_file?('lib/code_analyzer.rb')).to be true
|
33
35
|
end
|
34
36
|
|
35
37
|
it "should return false if node_file doesn't match pattern" do
|
36
|
-
allow(checker).to receive(:interesting_files).and_return([
|
37
|
-
expect(checker.parse_file?(
|
38
|
+
allow(checker).to receive(:interesting_files).and_return([%r{spec\/.*\.rb}])
|
39
|
+
expect(checker.parse_file?('lib/code_analyzer.rb')).to be false
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
|
-
context
|
42
|
-
it
|
43
|
+
context 'callback' do
|
44
|
+
it 'should add callback to start_call' do
|
43
45
|
block = Proc.new {}
|
44
46
|
Checker.add_callback(:start_call, &block)
|
45
47
|
expect(Checker.get_callbacks(:start_call)).to eq [block]
|
46
48
|
end
|
47
49
|
|
48
|
-
it
|
50
|
+
it 'should add callback to both start_class and end_class' do
|
49
51
|
block = Proc.new {}
|
50
52
|
Checker.add_callback(:start_class, :end_class, &block)
|
51
53
|
expect(Checker.get_callbacks(:start_class)).to eq [block]
|
52
54
|
expect(Checker.get_callbacks(:end_class)).to eq [block]
|
53
55
|
end
|
54
56
|
|
55
|
-
it
|
57
|
+
it 'should add multiple callbacks to end_call' do
|
56
58
|
block1 = Proc.new {}
|
57
59
|
block2 = Proc.new {}
|
58
60
|
Checker.add_callback(:end_call, &block1)
|
@@ -1,14 +1,16 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
2
4
|
|
3
5
|
module CodeAnalyzer::CheckingVisitor
|
4
6
|
describe Default do
|
5
|
-
let(:checker1) { double(:checker, interesting_nodes: [
|
6
|
-
let(:checker2) { double(:checker, interesting_nodes: [
|
7
|
+
let(:checker1) { double(:checker, interesting_nodes: %i[class def]) }
|
8
|
+
let(:checker2) { double(:checker, interesting_nodes: %i[def call]) }
|
7
9
|
let(:visitor) { Default.new(checkers: [checker1, checker2]) }
|
8
10
|
|
9
|
-
it
|
10
|
-
filename =
|
11
|
-
content =
|
11
|
+
it 'should check def node by all checkers' do
|
12
|
+
filename = 'filename'
|
13
|
+
content = 'def test; end'
|
12
14
|
allow(checker1).to receive(:parse_file?).with(filename).and_return(true)
|
13
15
|
allow(checker2).to receive(:parse_file?).with(filename).and_return(true)
|
14
16
|
expect(checker1).to receive(:node_start)
|
@@ -19,9 +21,9 @@ module CodeAnalyzer::CheckingVisitor
|
|
19
21
|
visitor.check(filename, content)
|
20
22
|
end
|
21
23
|
|
22
|
-
it
|
23
|
-
filename =
|
24
|
-
content =
|
24
|
+
it 'should check class node by only checker1' do
|
25
|
+
filename = 'filename'
|
26
|
+
content = 'class Test; end'
|
25
27
|
allow(checker1).to receive(:parse_file?).with(filename).and_return(true)
|
26
28
|
expect(checker1).to receive(:node_start)
|
27
29
|
expect(checker1).to receive(:node_end)
|
@@ -29,9 +31,9 @@ module CodeAnalyzer::CheckingVisitor
|
|
29
31
|
visitor.check(filename, content)
|
30
32
|
end
|
31
33
|
|
32
|
-
it
|
33
|
-
filename =
|
34
|
-
content =
|
34
|
+
it 'should check call node by only checker2' do
|
35
|
+
filename = 'filename'
|
36
|
+
content = 'obj.message'
|
35
37
|
allow(checker2).to receive(:parse_file?).with(filename).and_return(true)
|
36
38
|
expect(checker2).to receive(:node_start)
|
37
39
|
expect(checker2).to receive(:node_end)
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
2
4
|
|
3
5
|
module CodeAnalyzer::CheckingVisitor
|
4
6
|
describe Plain do
|
@@ -6,9 +8,9 @@ module CodeAnalyzer::CheckingVisitor
|
|
6
8
|
let(:checker2) { double(:checker) }
|
7
9
|
let(:visitor) { Plain.new(checkers: [checker1, checker2]) }
|
8
10
|
|
9
|
-
it
|
10
|
-
filename =
|
11
|
-
content =
|
11
|
+
it 'should check by all checkers' do
|
12
|
+
filename = 'filename'
|
13
|
+
content = 'content'
|
12
14
|
expect(checker1).to receive(:parse_file?).and_return(false)
|
13
15
|
expect(checker2).to receive(:parse_file?).and_return(true)
|
14
16
|
expect(checker1).not_to receive(:check).with(filename, content)
|