fasterer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/.fasterer.yml +17 -0
  3. data/.gitignore +15 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +8 -0
  6. data/.travis.yml +6 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +93 -0
  10. data/Rakefile +7 -0
  11. data/bin/fasterer +5 -0
  12. data/fasterer.gemspec +28 -0
  13. data/lib/fasterer.rb +7 -0
  14. data/lib/fasterer/analyzer.rb +99 -0
  15. data/lib/fasterer/binary_call.rb +4 -0
  16. data/lib/fasterer/cli.rb +10 -0
  17. data/lib/fasterer/file_traverser.rb +81 -0
  18. data/lib/fasterer/method_call.rb +138 -0
  19. data/lib/fasterer/method_definition.rb +51 -0
  20. data/lib/fasterer/offense.rb +69 -0
  21. data/lib/fasterer/offense_collector.rb +17 -0
  22. data/lib/fasterer/parse_error.rb +10 -0
  23. data/lib/fasterer/parser.rb +11 -0
  24. data/lib/fasterer/rescue_call.rb +36 -0
  25. data/lib/fasterer/scanners/method_call_scanner.rb +134 -0
  26. data/lib/fasterer/scanners/method_definition_scanner.rb +52 -0
  27. data/lib/fasterer/scanners/offensive.rb +25 -0
  28. data/lib/fasterer/scanners/rescue_call_scanner.rb +28 -0
  29. data/lib/fasterer/token.rb +27 -0
  30. data/lib/fasterer/version.rb +3 -0
  31. data/spec/lib/fasterer/analyzer/01_parallel_assignment_spec.rb +12 -0
  32. data/spec/lib/fasterer/analyzer/02_rescue_vs_respond_to_spec.rb +12 -0
  33. data/spec/lib/fasterer/analyzer/03_module_eval_spec.rb +12 -0
  34. data/spec/lib/fasterer/analyzer/04_find_vs_bsearch_spec.rb +12 -0
  35. data/spec/lib/fasterer/analyzer/06_shuffle_first_vs_sample_spec.rb +12 -0
  36. data/spec/lib/fasterer/analyzer/08_for_loop_vs_each_spec.rb +12 -0
  37. data/spec/lib/fasterer/analyzer/09_each_with_index_vs_while_spec.rb +12 -0
  38. data/spec/lib/fasterer/analyzer/10_map_flatten_vs_flat_map_spec.rb +12 -0
  39. data/spec/lib/fasterer/analyzer/11_reverse_each_vs_reverse_each_spec.rb +12 -0
  40. data/spec/lib/fasterer/analyzer/12_select_first_vs_detect_spec.rb +12 -0
  41. data/spec/lib/fasterer/analyzer/13_sort_vs_sort_by_spec.rb +12 -0
  42. data/spec/lib/fasterer/analyzer/14_fetch_with_argument_vs_block_spec.rb +12 -0
  43. data/spec/lib/fasterer/analyzer/15_keys_each_vs_each_key_spec.rb +12 -0
  44. data/spec/lib/fasterer/analyzer/16_hash_merge_bang_vs_hash_brackets_spec.rb +12 -0
  45. data/spec/lib/fasterer/analyzer/18_block_vs_symbol_to_proc_spec.rb +12 -0
  46. data/spec/lib/fasterer/analyzer/19_proc_call_vs_yield_spec.rb +12 -0
  47. data/spec/lib/fasterer/analyzer/24_gsub_vs_tr_spec.rb +12 -0
  48. data/spec/lib/fasterer/analyzer/98_misc_spec.rb +11 -0
  49. data/spec/lib/fasterer/analyzer/99_exceptional_files_spec.rb +11 -0
  50. data/spec/lib/fasterer/method_call_spec.rb +483 -0
  51. data/spec/lib/fasterer/method_definition_spec.rb +93 -0
  52. data/spec/lib/fasterer/rescue_call_spec.rb +76 -0
  53. data/spec/spec_helper.rb +99 -0
  54. data/spec/support/analyzer/01_parallel_assignment.rb +10 -0
  55. data/spec/support/analyzer/02_rescue_vs_respond_to.rb +36 -0
  56. data/spec/support/analyzer/03_module_eval.rb +11 -0
  57. data/spec/support/analyzer/04_find_vs_bsearch.rb +5 -0
  58. data/spec/support/analyzer/06_shuffle_first_vs_sample.rb +5 -0
  59. data/spec/support/analyzer/08_for_loop_vs_each.rb +8 -0
  60. data/spec/support/analyzer/09_each_with_index_vs_while.rb +3 -0
  61. data/spec/support/analyzer/10_map_flatten_vs_flat_map.rb +15 -0
  62. data/spec/support/analyzer/11_reverse_each_vs_reverse_each.rb +9 -0
  63. data/spec/support/analyzer/12_select_first_vs_detect.rb +7 -0
  64. data/spec/support/analyzer/13_sort_vs_sort_by.rb +9 -0
  65. data/spec/support/analyzer/14_fetch_with_argument_vs_block.rb +11 -0
  66. data/spec/support/analyzer/15_keys_each_vs_each_key.rb +15 -0
  67. data/spec/support/analyzer/16_hash_merge_bang_vs_hash_brackets.rb +21 -0
  68. data/spec/support/analyzer/18_block_vs_symbol_to_proc.rb +30 -0
  69. data/spec/support/analyzer/19_proc_call_vs_yield.rb +24 -0
  70. data/spec/support/analyzer/24_gsub_vs_tr.rb +14 -0
  71. data/spec/support/analyzer/98_misc.rb +15 -0
  72. data/spec/support/analyzer/99_exceptional_files.rb +7 -0
  73. data/spec/support/binary_call/simple_comparison.rb +0 -0
  74. data/spec/support/method_call/method_call_on_constant.rb +1 -0
  75. data/spec/support/method_call/method_call_on_integer.rb +1 -0
  76. data/spec/support/method_call/method_call_on_method_call.rb +1 -0
  77. data/spec/support/method_call/method_call_on_string.rb +1 -0
  78. data/spec/support/method_call/method_call_on_variable.rb +2 -0
  79. data/spec/support/method_call/method_call_with_a_block.rb +5 -0
  80. data/spec/support/method_call/method_call_with_a_integer_argument.rb +1 -0
  81. data/spec/support/method_call/method_call_with_a_regex_argument.rb +1 -0
  82. data/spec/support/method_call/method_call_with_an_argument_and_a_block.rb +2 -0
  83. data/spec/support/method_call/method_call_with_an_implicit_receiver.rb +1 -0
  84. data/spec/support/method_call/method_call_with_an_implicit_receiver_and_no_brackets.rb +1 -0
  85. data/spec/support/method_call/method_call_with_an_implicit_receiver_and_no_brackets_and_do_end.rb +3 -0
  86. data/spec/support/method_call/method_call_with_equals.rb +1 -0
  87. data/spec/support/method_call/method_call_with_one_argument.rb +1 -0
  88. data/spec/support/method_call/method_call_with_two_arguments.rb +2 -0
  89. data/spec/support/method_call/method_call_without_brackets.rb +1 -0
  90. data/spec/support/method_definition/method_with_argument_and_block.rb +3 -0
  91. data/spec/support/method_definition/method_with_block.rb +3 -0
  92. data/spec/support/method_definition/method_with_default_argument.rb +3 -0
  93. data/spec/support/method_definition/method_with_splat_and_block.rb +3 -0
  94. data/spec/support/method_definition/simple_method.rb +2 -0
  95. data/spec/support/method_definition/simple_method_omitted_parenthesis.rb +2 -0
  96. data/spec/support/method_definition/simple_method_with_argument.rb +3 -0
  97. data/spec/support/rescue_call/plain_rescue.rb +7 -0
  98. data/spec/support/rescue_call/rescue_with_class.rb +5 -0
  99. data/spec/support/rescue_call/rescue_with_class_and_variable.rb +5 -0
  100. data/spec/support/rescue_call/rescue_with_multiple_classes.rb +4 -0
  101. data/spec/support/rescue_call/rescue_with_multiple_classes_and_variable.rb +5 -0
  102. data/spec/support/rescue_call/rescue_with_variable.rb +6 -0
  103. metadata +303 -0
@@ -0,0 +1,52 @@
1
+ require 'fasterer/method_definition'
2
+ require 'fasterer/method_call'
3
+ require 'fasterer/offense'
4
+ require 'fasterer/scanners/offensive'
5
+
6
+ module Fasterer
7
+ class MethodDefinitionScanner
8
+ include Fasterer::Offensive
9
+
10
+ attr_reader :element
11
+
12
+ def initialize(element)
13
+ @element = element
14
+ check_offense
15
+ end
16
+
17
+ private
18
+
19
+ def check_offense
20
+ if method_definition.has_block?
21
+ scan_block_call_offense
22
+ end
23
+ end
24
+
25
+ def scan_block_call_offense
26
+ traverse_tree(method_definition.body) do |element|
27
+ next unless element.sexp_type == :call
28
+
29
+ method_call = MethodCall.new(element)
30
+
31
+ if method_call.receiver.is_a?(Fasterer::VariableReference) &&
32
+ method_call.receiver.name == method_definition.block_argument_name &&
33
+ method_call.method_name == :call
34
+
35
+ add_offense(:proc_call_vs_yield) && return
36
+ end
37
+ end
38
+ end
39
+
40
+ def method_definition
41
+ @method_definition ||= MethodDefinition.new(element)
42
+ end
43
+
44
+ def traverse_tree(sexp_tree, &block)
45
+ sexp_tree.each do |element|
46
+ next unless element.is_a?(Array)
47
+ yield element
48
+ traverse_tree(element, &block)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,25 @@
1
+ require 'fasterer/offense'
2
+
3
+ module Fasterer
4
+ module Offensive
5
+
6
+ attr_accessor :offense
7
+
8
+ def offensive?
9
+ !!offense
10
+ end
11
+
12
+ alias_method :offense_detected?, :offensive?
13
+
14
+ private
15
+
16
+ def add_offense(offense_name, element_line_number = element.line)
17
+ self.offense = Fasterer::Offense.new(offense_name, element_line_number)
18
+ end
19
+
20
+ def check_offense
21
+ raise NotImplementedError
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+ require 'fasterer/rescue_call'
2
+ require 'fasterer/offense'
3
+ require 'fasterer/scanners/offensive'
4
+
5
+ module Fasterer
6
+ class RescueCallScanner
7
+ include Fasterer::Offensive
8
+
9
+ attr_reader :element
10
+
11
+ def initialize(element)
12
+ @element = element
13
+ check_offense
14
+ end
15
+
16
+ private
17
+
18
+ def check_offense
19
+ if rescue_call.rescue_classes.include? :NoMethodError
20
+ add_offense(:rescue_vs_respond_to)
21
+ end
22
+ end
23
+
24
+ def rescue_call
25
+ @rescue_call ||= RescueCall.new(element)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ module Fasterer
2
+ class Token
3
+ def initialize(name)
4
+ @name = name
5
+ end
6
+
7
+ def method_definition?
8
+ name == :def
9
+ end
10
+
11
+ def method_call?
12
+ name == :call
13
+ end
14
+
15
+ def command_call?
16
+ name == :command
17
+ end
18
+
19
+ def parallel_assignment?
20
+ name == :massign
21
+ end
22
+
23
+ def for_loop?
24
+ name == :for
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module Fasterer
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '01_parallel_assignment.rb') }
6
+
7
+ it 'should detect parallel assignment 2 times' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:parallel_assignment].count).to eq(2)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '02_rescue_vs_respond_to.rb') }
6
+
7
+ it 'should detect rescue NoMethodError' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:rescue_vs_respond_to].count).to eq(3)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '03_module_eval.rb') }
6
+
7
+ it 'should detect module eval' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:module_eval].count).to eq(1)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '04_find_vs_bsearch.rb') }
6
+
7
+ xit 'should detect Array#find' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ # expect(analyzer.error_occurrence[:module_eval]).to eq(1)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '06_shuffle_first_vs_sample.rb') }
6
+
7
+ it 'should detect a for loop' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:shuffle_first_vs_sample].count).to eq(5)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '08_for_loop_vs_each.rb') }
6
+
7
+ it 'should detect a for loop' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:for_loop_vs_each].count).to eq(1)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '09_each_with_index_vs_while.rb') }
6
+
7
+ it 'should detect a for loop' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:each_with_index_vs_while].count).to eq(1)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '10_map_flatten_vs_flat_map.rb') }
6
+
7
+ it 'should detect a map{}.flatten(1) ' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:map_flatten_vs_flat_map].count).to eq(2)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '11_reverse_each_vs_reverse_each.rb') }
6
+
7
+ it 'should detect a for loop' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:reverse_each_vs_reverse_each].count).to eq(2)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '12_select_first_vs_detect.rb') }
6
+
7
+ it 'should detect sort once' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:select_first_vs_detect].count).to eq(2)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '13_sort_vs_sort_by.rb') }
6
+
7
+ it 'should detect sort once' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:sort_vs_sort_by].count).to eq(1)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '14_fetch_with_argument_vs_block.rb') }
6
+
7
+ it 'should detect keys fetch with argument once' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:fetch_with_argument_vs_block].count).to eq(1)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '15_keys_each_vs_each_key.rb') }
6
+
7
+ it 'should detect keys each 3 times' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:keys_each_vs_each_key].count).to eq(3)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '16_hash_merge_bang_vs_hash_brackets.rb') }
6
+
7
+ it 'should detect keys each 3 times' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:hash_merge_bang_vs_hash_brackets].count).to eq(3)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '18_block_vs_symbol_to_proc.rb') }
6
+
7
+ it 'should block that could be called with symbol 2 times' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:block_vs_symbol_to_proc].count).to eq(2)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '19_proc_call_vs_yield.rb') }
6
+
7
+ it 'should detect sort once' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:proc_call_vs_yield].count).to eq(3)
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '24_gsub_vs_tr.rb') }
6
+
7
+ it 'should detect gsub 4 times' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:gsub_vs_tr].count).to eq(4)
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '98_misc.rb') }
6
+
7
+ it 'should detect gsub 4 times' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::Analyzer do
4
+
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '99_exceptional_files.rb') }
6
+
7
+ it 'diacritics should not raise an error' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ expect { analyzer.scan }.not_to raise_error
10
+ end
11
+ end
@@ -0,0 +1,483 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fasterer::MethodCall do
4
+
5
+ let(:ripper) do
6
+ Fasterer::Parser.parse(code)
7
+ end
8
+
9
+ let(:method_call) do
10
+ Fasterer::MethodCall.new(call_element)
11
+ end
12
+
13
+ describe 'with explicit receiver' do
14
+ describe 'without arguments, without block, called with parentheses' do
15
+ describe 'method call on a constant' do
16
+
17
+ let(:code) { 'User.hello()' }
18
+
19
+ # This is where the :call token will be recognized.
20
+ let(:call_element) { ripper }
21
+
22
+ it 'should detect constant' do
23
+ expect(method_call.method_name).to eq(:hello)
24
+ expect(method_call.arguments).to be_empty
25
+ end
26
+
27
+ end
28
+
29
+ describe 'method call on a integer' do
30
+
31
+ let(:code) { '1.hello()' }
32
+
33
+ # This is where the :call token will be recognized.
34
+ let(:call_element) { ripper }
35
+
36
+ it 'should detect integer' do
37
+ expect(method_call.method_name).to eq(:hello)
38
+ expect(method_call.arguments).to be_empty
39
+ end
40
+
41
+ end
42
+
43
+ describe 'method call on a string' do
44
+
45
+ let(:code) { "'hello'.hello()" }
46
+
47
+ let(:call_element) { ripper }
48
+
49
+ it 'should detect string' do
50
+ expect(method_call.method_name).to eq(:hello)
51
+ expect(method_call.arguments).to be_empty
52
+ end
53
+
54
+ end
55
+
56
+ describe 'method call on a variable' do
57
+
58
+ let(:code) do
59
+ "number_one = 1\n"\
60
+ 'number_one.hello()'
61
+ end
62
+
63
+ let(:call_element) { ripper[2] }
64
+
65
+ it 'should detect variable' do
66
+ expect(method_call.method_name).to eq(:hello)
67
+ expect(method_call.arguments).to be_empty
68
+ expect(method_call.receiver).to be_a(Fasterer::VariableReference)
69
+ expect(method_call.receiver.name).to eq(:number_one)
70
+ end
71
+
72
+ end
73
+
74
+ describe 'method call on a method' do
75
+
76
+ let(:code) { '1.hi(2).hello()' }
77
+
78
+ let(:call_element) { ripper }
79
+
80
+ it 'should detect method' do
81
+ expect(method_call.method_name).to eq(:hello)
82
+ expect(method_call.receiver).to be_a(Fasterer::MethodCall)
83
+ expect(method_call.receiver.name).to eq(:hi)
84
+ expect(method_call.arguments).to be_empty
85
+ end
86
+
87
+ end
88
+ end
89
+
90
+ describe 'without arguments, without block, called without parentheses' do
91
+ describe 'method call on a constant' do
92
+
93
+ let(:code) { 'User.hello' }
94
+
95
+ let(:call_element) { ripper }
96
+
97
+ it 'should detect constant' do
98
+ expect(method_call.method_name).to eq(:hello)
99
+ expect(method_call.arguments).to be_empty
100
+ end
101
+
102
+ end
103
+
104
+ describe 'method call on a integer' do
105
+
106
+ let(:code) { '1.hello' }
107
+
108
+ # This is where the :call token will be recognized.
109
+ let(:call_element) { ripper }
110
+
111
+ it 'should detect integer' do
112
+ expect(method_call.method_name).to eq(:hello)
113
+ expect(method_call.arguments).to be_empty
114
+ end
115
+
116
+ end
117
+
118
+ describe 'method call on a string' do
119
+
120
+ let(:code) { "'hello'.hello" }
121
+
122
+ let(:call_element) { ripper }
123
+
124
+ it 'should detect string' do
125
+ expect(method_call.method_name).to eq(:hello)
126
+ expect(method_call.arguments).to be_empty
127
+ end
128
+
129
+ end
130
+
131
+ describe 'method call on a variable' do
132
+
133
+ let(:code) do
134
+ "number_one = 1\n"\
135
+ 'number_one.hello'
136
+ end
137
+
138
+ let(:call_element) { ripper[2] }
139
+
140
+ it 'should detect variable' do
141
+ expect(method_call.method_name).to eq(:hello)
142
+ expect(method_call.arguments).to be_empty
143
+ expect(method_call.receiver).to be_a(Fasterer::VariableReference)
144
+ expect(method_call.receiver.name).to eq(:number_one)
145
+ end
146
+
147
+ end
148
+
149
+ describe 'method call on a method' do
150
+
151
+ let(:code) { '1.hi(2).hello' }
152
+
153
+ let(:call_element) { ripper }
154
+
155
+ it 'should detect method' do
156
+ expect(method_call.method_name).to eq(:hello)
157
+ expect(method_call.receiver).to be_a(Fasterer::MethodCall)
158
+ expect(method_call.receiver.name).to eq(:hi)
159
+ expect(method_call.arguments).to be_empty
160
+ end
161
+
162
+ end
163
+ end
164
+
165
+ describe 'with do end block' do
166
+
167
+ describe 'and no arguments, without block parameter' do
168
+
169
+ let(:code) do
170
+ <<-code
171
+ number_one.fetch do
172
+ number_two = 2
173
+ number_three = 3
174
+ end
175
+ code
176
+ end
177
+
178
+ let(:call_element) { ripper }
179
+
180
+ it 'should detect block' do
181
+ expect(method_call.method_name).to eq(:fetch)
182
+ expect(method_call.arguments).to be_empty
183
+ expect(method_call.has_block?).to be
184
+ expect(method_call.block_argument_names.count).to be(0)
185
+ expect(method_call.receiver).to be_a(Fasterer::MethodCall)
186
+ end
187
+
188
+ end
189
+
190
+ describe 'and no arguments, with block parameter' do
191
+
192
+ let(:code) do
193
+ <<-code
194
+ number_one.fetch do |el|
195
+ number_two = 2
196
+ number_three = 3
197
+ end
198
+ code
199
+ end
200
+
201
+ let(:call_element) { ripper }
202
+
203
+ it 'should detect block' do
204
+ expect(method_call.method_name).to eq(:fetch)
205
+ expect(method_call.arguments).to be_empty
206
+ expect(method_call.has_block?).to be
207
+ expect(method_call.block_argument_names.count).to be(1)
208
+ expect(method_call.block_argument_names.first).to be(:el)
209
+ expect(method_call.receiver).to be_a(Fasterer::MethodCall)
210
+ end
211
+
212
+ end
213
+
214
+ describe 'and no arguments, with block parameter' do
215
+
216
+ let(:code) do
217
+ <<-code
218
+ number_one.fetch do |el, tip|
219
+ number_two = 2
220
+ number_three = 3
221
+ end
222
+ code
223
+ end
224
+
225
+ let(:call_element) { ripper }
226
+
227
+ it 'should detect block' do
228
+ expect(method_call.method_name).to eq(:fetch)
229
+ expect(method_call.arguments).to be_empty
230
+ expect(method_call.has_block?).to be
231
+ expect(method_call.block_argument_names.count).to be(2)
232
+ expect(method_call.block_argument_names.first).to be(:el)
233
+ expect(method_call.block_argument_names.last).to be(:tip)
234
+ expect(method_call.receiver).to be_a(Fasterer::MethodCall)
235
+ end
236
+
237
+ end
238
+
239
+ describe 'and one argument within parentheses' do
240
+
241
+ let(:code) do
242
+ <<-code
243
+ number_one = 1
244
+ number_one.fetch(100) do |el|
245
+ number_two = 2
246
+ number_three = 3
247
+ end
248
+ code
249
+ end
250
+
251
+ let(:call_element) { ripper[2] }
252
+
253
+ it 'should detect block' do
254
+ expect(method_call.method_name).to eq(:fetch)
255
+ expect(method_call.arguments.count).to be(1)
256
+ expect(method_call.has_block?).to be
257
+ expect(method_call.receiver).to be_a(Fasterer::VariableReference)
258
+ end
259
+
260
+ end
261
+ end
262
+
263
+ describe 'with curly block' do
264
+ describe 'in one line' do
265
+
266
+ let(:code) do
267
+ <<-code
268
+ number_one = 1
269
+ number_one.fetch { |el| number_two = 2 }
270
+ code
271
+ end
272
+
273
+ let(:call_element) { ripper[2] }
274
+
275
+ it 'should detect block' do
276
+ expect(method_call.method_name).to eq(:fetch)
277
+ expect(method_call.arguments).to be_empty
278
+ expect(method_call.has_block?).to be
279
+ expect(method_call.receiver).to be_a(Fasterer::VariableReference)
280
+ end
281
+
282
+ end
283
+
284
+ describe 'multi lined' do
285
+
286
+ let(:code) do
287
+ <<-code
288
+ number_one = 1
289
+ number_one.fetch { |el|
290
+ number_two = 2
291
+ number_three = 3
292
+ }
293
+ code
294
+ end
295
+
296
+ let(:call_element) { ripper[2] }
297
+
298
+ it 'should detect block' do
299
+ expect(method_call.method_name).to eq(:fetch)
300
+ expect(method_call.arguments).to be_empty
301
+ expect(method_call.has_block?).to be
302
+ expect(method_call.receiver).to be_a(Fasterer::VariableReference)
303
+ end
304
+
305
+ end
306
+ end
307
+
308
+ describe 'with arguments, without block, called with parentheses' do
309
+
310
+ describe 'method call with an argument' do
311
+
312
+ let(:code) { '{}.fetch(:writing)' }
313
+
314
+ let(:call_element) { ripper }
315
+
316
+ it 'should detect argument' do
317
+ expect(method_call.method_name).to eq(:fetch)
318
+ expect(method_call.arguments.count).to eq(1)
319
+ expect(method_call.arguments.first.type).to eq(:lit)
320
+ end
321
+
322
+ end
323
+ end
324
+
325
+ describe 'arguments without parenthesis' do
326
+ describe 'method call with an argument' do
327
+
328
+ let(:code) { '{}.fetch :writing, :listening' }
329
+
330
+ let(:call_element) { ripper }
331
+
332
+ it 'should detect argument' do
333
+ expect(method_call.method_name).to eq(:fetch)
334
+ expect(method_call.arguments.count).to eq(2)
335
+ expect(method_call.arguments[0].type).to eq(:lit)
336
+ expect(method_call.arguments[1].type).to eq(:lit)
337
+ end
338
+
339
+ end
340
+ end
341
+ end
342
+
343
+ describe 'with implicit receiver' do
344
+ end
345
+
346
+ describe 'method call with an argument and a block' do
347
+
348
+ let(:code) do
349
+ <<-code
350
+ number_one = 1
351
+ number_one.fetch(:writing) { [*1..100] }
352
+ code
353
+ end
354
+
355
+ let(:call_element) { ripper[2] }
356
+
357
+ it 'should detect argument and a block' do
358
+ expect(method_call.method_name).to eq(:fetch)
359
+ expect(method_call.arguments.count).to eq(1)
360
+ expect(method_call.arguments.first.type).to eq(:lit)
361
+ expect(method_call.has_block?).to be
362
+ expect(method_call.receiver).to be_a(Fasterer::VariableReference)
363
+ end
364
+
365
+ end
366
+
367
+ describe 'method call without an explicit receiver' do
368
+
369
+ let(:code) { 'fetch(:writing, :listening)' }
370
+
371
+ let(:call_element) { ripper }
372
+
373
+ it 'should detect two arguments' do
374
+ expect(method_call.method_name).to eq(:fetch)
375
+ expect(method_call.arguments.count).to eq(2)
376
+ expect(method_call.arguments[0].type).to eq(:lit)
377
+ expect(method_call.arguments[1].type).to eq(:lit)
378
+ expect(method_call.receiver).to be_nil
379
+ end
380
+
381
+ end
382
+
383
+ describe 'method call without an explicit receiver and without brackets' do
384
+
385
+ let(:code) { 'fetch :writing, :listening' }
386
+
387
+ let(:call_element) { ripper }
388
+
389
+ it 'should detect two arguments' do
390
+ expect(method_call.method_name).to eq(:fetch)
391
+ expect(method_call.arguments.count).to eq(2)
392
+ expect(method_call.arguments[0].type).to eq(:lit)
393
+ expect(method_call.arguments[1].type).to eq(:lit)
394
+ expect(method_call.receiver).to be_nil
395
+ end
396
+
397
+ end
398
+
399
+ describe 'method call without an explicit receiver and without brackets and do end' do
400
+
401
+ let(:code) do
402
+ <<-code
403
+ "fetch :writing do\n"\
404
+ "end"
405
+ code
406
+ end
407
+
408
+ let(:call_element) { ripper.drop(1).first.first }
409
+
410
+ it 'should detect argument and a block' do
411
+ # expect(method_call.method_name).to eq('fetch')
412
+ # expect(method_call.arguments.count).to eq(2)
413
+ # expect(method_call.arguments[0].type).to eq(:symbol_literal)
414
+ # expect(method_call.arguments[1].type).to eq(:symbol_literal)
415
+ # expect(method_call.receiver).to be_nil
416
+ end
417
+
418
+ end
419
+
420
+ describe 'method call with two arguments' do
421
+
422
+ let(:code) do
423
+ "number_one = 1\n"\
424
+ 'number_one.fetch(:writing, :zumba)'
425
+ end
426
+
427
+ let(:call_element) { ripper[2] }
428
+
429
+ it 'should detect arguments' do
430
+ expect(method_call.method_name).to eq(:fetch)
431
+ expect(method_call.arguments.count).to eq(2)
432
+ expect(method_call.arguments[0].type).to eq(:lit)
433
+ expect(method_call.arguments[1].type).to eq(:lit)
434
+ expect(method_call.receiver).to be_a(Fasterer::VariableReference)
435
+ end
436
+
437
+ end
438
+
439
+ describe 'method call with a regex argument' do
440
+
441
+ let(:code) { '{}.fetch(/.*/)' }
442
+
443
+ let(:call_element) { ripper }
444
+
445
+ it 'should detect regex argument' do
446
+ expect(method_call.method_name).to eq(:fetch)
447
+ expect(method_call.arguments.count).to eq(1)
448
+ expect(method_call.arguments[0].type).to eq(:lit)
449
+ expect(method_call.arguments[0].value).to be_a(Regexp)
450
+ end
451
+
452
+ end
453
+
454
+ describe 'method call with a integer argument' do
455
+
456
+ let(:code) { '[].flatten(1)' }
457
+
458
+ let(:call_element) { ripper }
459
+
460
+ it 'should detect regex argument' do
461
+ expect(method_call.method_name).to eq(:flatten)
462
+ expect(method_call.arguments.count).to eq(1)
463
+ expect(method_call.arguments[0].type).to eq(:lit)
464
+ expect(method_call.arguments[0].value).to eq(1)
465
+ end
466
+
467
+ end
468
+
469
+ describe 'method call with equals operator' do
470
+
471
+ let(:code) { 'method_call_with_equals.rb' }
472
+
473
+ let(:call_element) { ripper.drop(1).first.first[1] }
474
+
475
+ xit 'should recognize receiver' do
476
+ # expect(method_call.method_name).to eq('hello')
477
+ # expect(method_call.receiver).to be_a(Fasterer::MethodCall)
478
+ # expect(method_call.receiver.name).to eq('hi')
479
+ end
480
+
481
+ end
482
+
483
+ end