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.
- checksums.yaml +7 -0
- data/.fasterer.yml +17 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.rubocop.yml +8 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +93 -0
- data/Rakefile +7 -0
- data/bin/fasterer +5 -0
- data/fasterer.gemspec +28 -0
- data/lib/fasterer.rb +7 -0
- data/lib/fasterer/analyzer.rb +99 -0
- data/lib/fasterer/binary_call.rb +4 -0
- data/lib/fasterer/cli.rb +10 -0
- data/lib/fasterer/file_traverser.rb +81 -0
- data/lib/fasterer/method_call.rb +138 -0
- data/lib/fasterer/method_definition.rb +51 -0
- data/lib/fasterer/offense.rb +69 -0
- data/lib/fasterer/offense_collector.rb +17 -0
- data/lib/fasterer/parse_error.rb +10 -0
- data/lib/fasterer/parser.rb +11 -0
- data/lib/fasterer/rescue_call.rb +36 -0
- data/lib/fasterer/scanners/method_call_scanner.rb +134 -0
- data/lib/fasterer/scanners/method_definition_scanner.rb +52 -0
- data/lib/fasterer/scanners/offensive.rb +25 -0
- data/lib/fasterer/scanners/rescue_call_scanner.rb +28 -0
- data/lib/fasterer/token.rb +27 -0
- data/lib/fasterer/version.rb +3 -0
- data/spec/lib/fasterer/analyzer/01_parallel_assignment_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/02_rescue_vs_respond_to_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/03_module_eval_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/04_find_vs_bsearch_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/06_shuffle_first_vs_sample_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/08_for_loop_vs_each_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/09_each_with_index_vs_while_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/10_map_flatten_vs_flat_map_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/11_reverse_each_vs_reverse_each_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/12_select_first_vs_detect_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/13_sort_vs_sort_by_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/14_fetch_with_argument_vs_block_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/15_keys_each_vs_each_key_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/16_hash_merge_bang_vs_hash_brackets_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/18_block_vs_symbol_to_proc_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/19_proc_call_vs_yield_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/24_gsub_vs_tr_spec.rb +12 -0
- data/spec/lib/fasterer/analyzer/98_misc_spec.rb +11 -0
- data/spec/lib/fasterer/analyzer/99_exceptional_files_spec.rb +11 -0
- data/spec/lib/fasterer/method_call_spec.rb +483 -0
- data/spec/lib/fasterer/method_definition_spec.rb +93 -0
- data/spec/lib/fasterer/rescue_call_spec.rb +76 -0
- data/spec/spec_helper.rb +99 -0
- data/spec/support/analyzer/01_parallel_assignment.rb +10 -0
- data/spec/support/analyzer/02_rescue_vs_respond_to.rb +36 -0
- data/spec/support/analyzer/03_module_eval.rb +11 -0
- data/spec/support/analyzer/04_find_vs_bsearch.rb +5 -0
- data/spec/support/analyzer/06_shuffle_first_vs_sample.rb +5 -0
- data/spec/support/analyzer/08_for_loop_vs_each.rb +8 -0
- data/spec/support/analyzer/09_each_with_index_vs_while.rb +3 -0
- data/spec/support/analyzer/10_map_flatten_vs_flat_map.rb +15 -0
- data/spec/support/analyzer/11_reverse_each_vs_reverse_each.rb +9 -0
- data/spec/support/analyzer/12_select_first_vs_detect.rb +7 -0
- data/spec/support/analyzer/13_sort_vs_sort_by.rb +9 -0
- data/spec/support/analyzer/14_fetch_with_argument_vs_block.rb +11 -0
- data/spec/support/analyzer/15_keys_each_vs_each_key.rb +15 -0
- data/spec/support/analyzer/16_hash_merge_bang_vs_hash_brackets.rb +21 -0
- data/spec/support/analyzer/18_block_vs_symbol_to_proc.rb +30 -0
- data/spec/support/analyzer/19_proc_call_vs_yield.rb +24 -0
- data/spec/support/analyzer/24_gsub_vs_tr.rb +14 -0
- data/spec/support/analyzer/98_misc.rb +15 -0
- data/spec/support/analyzer/99_exceptional_files.rb +7 -0
- data/spec/support/binary_call/simple_comparison.rb +0 -0
- data/spec/support/method_call/method_call_on_constant.rb +1 -0
- data/spec/support/method_call/method_call_on_integer.rb +1 -0
- data/spec/support/method_call/method_call_on_method_call.rb +1 -0
- data/spec/support/method_call/method_call_on_string.rb +1 -0
- data/spec/support/method_call/method_call_on_variable.rb +2 -0
- data/spec/support/method_call/method_call_with_a_block.rb +5 -0
- data/spec/support/method_call/method_call_with_a_integer_argument.rb +1 -0
- data/spec/support/method_call/method_call_with_a_regex_argument.rb +1 -0
- data/spec/support/method_call/method_call_with_an_argument_and_a_block.rb +2 -0
- data/spec/support/method_call/method_call_with_an_implicit_receiver.rb +1 -0
- data/spec/support/method_call/method_call_with_an_implicit_receiver_and_no_brackets.rb +1 -0
- data/spec/support/method_call/method_call_with_an_implicit_receiver_and_no_brackets_and_do_end.rb +3 -0
- data/spec/support/method_call/method_call_with_equals.rb +1 -0
- data/spec/support/method_call/method_call_with_one_argument.rb +1 -0
- data/spec/support/method_call/method_call_with_two_arguments.rb +2 -0
- data/spec/support/method_call/method_call_without_brackets.rb +1 -0
- data/spec/support/method_definition/method_with_argument_and_block.rb +3 -0
- data/spec/support/method_definition/method_with_block.rb +3 -0
- data/spec/support/method_definition/method_with_default_argument.rb +3 -0
- data/spec/support/method_definition/method_with_splat_and_block.rb +3 -0
- data/spec/support/method_definition/simple_method.rb +2 -0
- data/spec/support/method_definition/simple_method_omitted_parenthesis.rb +2 -0
- data/spec/support/method_definition/simple_method_with_argument.rb +3 -0
- data/spec/support/rescue_call/plain_rescue.rb +7 -0
- data/spec/support/rescue_call/rescue_with_class.rb +5 -0
- data/spec/support/rescue_call/rescue_with_class_and_variable.rb +5 -0
- data/spec/support/rescue_call/rescue_with_multiple_classes.rb +4 -0
- data/spec/support/rescue_call/rescue_with_multiple_classes_and_variable.rb +5 -0
- data/spec/support/rescue_call/rescue_with_variable.rb +6 -0
- 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,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
|