fasterer 0.1.0

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.
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