fasterer 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a9044b0734156a715894ea721ea8a13105c55fc
4
- data.tar.gz: 5cee39bd66ce0513d1fa3a6175d3b5f35de4ba70
3
+ metadata.gz: 9166a1cbd984ee3e8af00277252f430d7efcc817
4
+ data.tar.gz: 35ec0f0a4953e38f0145106c3523622461e9467c
5
5
  SHA512:
6
- metadata.gz: 2d89297fc809382f092941e12f52dd092e999af45d521d07c7bdca0350d070e096fe0235ddf7b56a6d82d5fbead89bbd3d1c9d177a4d5e6bda56d0efa80fd3c4
7
- data.tar.gz: 4f50e5a4512471e8f812541a432970712e0c94f3336a80400d5226e29553f50ccf4a74df53981d50d5b952161fa1686dd8e9b0b13e17f160d648212f5dadf2bd
6
+ metadata.gz: 8f9774ae496a60c30b619155a53e1cf306ee1beed19e63fb601e4de2a40e3c435c0352daafeeb6d3de19ee7b9fde694d3493089cf36901197be939d80e376ca5
7
+ data.tar.gz: 0bac8bc68e9f4d5032d12d9dd29a8b4cc99efc59338aefe15a262590f955fb97f2af2ed4cb6b25b0502992f48cc1b4e983d54aee2879789c81b9a1c9442073e3
@@ -16,5 +16,9 @@ speedups:
16
16
  block_vs_symbol_to_proc: true
17
17
  proc_call_vs_yield: true
18
18
  gsub_vs_tr: true
19
+ select_last_vs_reverse_detect: true
20
+ getter_vs_attr_reader: true
21
+ setter_vs_attr_writer: true
22
+
19
23
  exclude_paths:
20
24
  - 'vendor/**/*.rb'
data/README.md CHANGED
@@ -74,6 +74,9 @@ speedups:
74
74
  block_vs_symbol_to_proc: true
75
75
  proc_call_vs_yield: true
76
76
  gsub_vs_tr: true
77
+ select_last_vs_reverse_detect: true
78
+ getter_vs_attr_reader: true
79
+ setter_vs_attr_writer: true
77
80
 
78
81
  exclude_paths:
79
82
  - 'vendor/**/*.rb'
@@ -25,4 +25,5 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency 'rake', '~> 10.0'
26
26
  spec.add_development_dependency 'rspec', '~> 3.2'
27
27
  spec.add_development_dependency 'pry', '~> 0.10'
28
+ spec.add_development_dependency 'simplecov', '~> 0.9'
28
29
  end
@@ -7,50 +7,50 @@ require_relative 'analyzer'
7
7
  module Fasterer
8
8
  class FileTraverser
9
9
 
10
- CONFIG_FILE_NAME = '.fasterer.yml'
11
-
12
- SPEEDUPS_KEY = 'speedups'
13
-
10
+ CONFIG_FILE_NAME = '.fasterer.yml'
11
+ SPEEDUPS_KEY = 'speedups'
14
12
  EXCLUDE_PATHS_KEY = 'exclude_paths'
15
13
 
16
- attr_reader :ignored_speedups, :ignored_paths
17
-
18
14
  def initialize(path)
19
15
  @path = Pathname(path)
20
16
  @parse_error_paths = []
21
- set_ignored_speedups
22
- set_ignored_paths
23
17
  end
24
18
 
25
19
  def traverse
26
20
  if @path.directory?
27
- traverse_directory(@path)
21
+ scannable_files.each { |ruby_file| scan_file(ruby_file) }
28
22
  else
29
23
  scan_file(@path)
30
24
  end
31
25
  output_parse_errors if parse_error_paths.any?
32
26
  end
33
27
 
34
- def set_ignored_speedups
35
- @ignored_speedups = if config_file && config_file[SPEEDUPS_KEY]
36
- config_file[SPEEDUPS_KEY].select {|_, value| value == false }.keys.map(&:to_sym)
37
- end || []
28
+ def ignored_speedups
29
+ @ignored_speedups ||=
30
+ config_file[SPEEDUPS_KEY].select { |_, value| value == false }.keys.map(&:to_sym)
38
31
  end
39
32
 
40
- def set_ignored_paths
41
- @ignored_paths = if config_file && config_file[EXCLUDE_PATHS_KEY]
42
- config_file[EXCLUDE_PATHS_KEY].flat_map {|path| Dir[path] }
43
- end || []
33
+ def ignored_files
34
+ @ignored_files ||=
35
+ config_file[EXCLUDE_PATHS_KEY].flat_map { |path| Dir[path] }
44
36
  end
45
37
 
46
38
  def config_file
47
- File.exists?(CONFIG_FILE_NAME) && YAML.load_file(CONFIG_FILE_NAME)
39
+ @config_file ||= if File.exists?(CONFIG_FILE_NAME)
40
+ YAML.load_file(CONFIG_FILE_NAME)
41
+ else
42
+ nil_config_file
43
+ end
48
44
  end
49
45
 
50
46
  private
51
47
 
52
48
  attr_reader :parse_error_paths
53
49
 
50
+ def nil_config_file
51
+ { SPEEDUPS_KEY => {}, EXCLUDE_PATHS_KEY => [] }
52
+ end
53
+
54
54
  def scan_file(path)
55
55
  analyzer = Analyzer.new(path)
56
56
  analyzer.scan
@@ -60,12 +60,13 @@ module Fasterer
60
60
  output(analyzer) if offenses_grouped_by_type(analyzer).any?
61
61
  end
62
62
 
63
- def traverse_directory(path)
64
- Dir["#{path}/**/*.rb"].each do |ruby_file_path|
65
- relative_ruby_file_path = Pathname(ruby_file_path).relative_path_from(path)
66
- unless ignored_paths.include?(relative_ruby_file_path.to_s)
67
- scan_file(relative_ruby_file_path)
68
- end
63
+ def scannable_files
64
+ all_files - ignored_files
65
+ end
66
+
67
+ def all_files
68
+ Dir["#{@path}/**/*.rb"].map do |ruby_file_path|
69
+ Pathname(ruby_file_path).relative_path_from(@path).to_s
69
70
  end
70
71
  end
71
72
 
@@ -73,20 +74,23 @@ module Fasterer
73
74
  puts analyzer.file_path.colorize(:red)
74
75
 
75
76
  offenses_grouped_by_type(analyzer).each do |error_group_name, error_occurences|
76
- puts "#{Fasterer::Offense::EXPLANATIONS[error_group_name]}. Occured at lines: #{error_occurences.map(&:line_number).join(', ')}."
77
+ puts "#{Fasterer::Offense::EXPLANATIONS[error_group_name]}."\
78
+ " Occurred at lines: #{error_occurences.map(&:line_number).join(', ')}."
77
79
  end
78
80
 
79
81
  puts
80
82
  end
81
83
 
82
84
  def offenses_grouped_by_type(analyzer)
83
- analyzer.errors.group_by(&:name).delete_if {|offense_name, _| ignored_speedups.include?(offense_name) }
85
+ analyzer.errors.group_by(&:name).delete_if do |offense_name, _|
86
+ ignored_speedups.include?(offense_name)
87
+ end
84
88
  end
85
89
 
86
90
  def output_parse_errors
87
91
  puts 'Fasterer was unable to process some files because the'
88
92
  puts 'internal parser is not able to read some characters or'
89
- puts 'has timeouted. Unprocessable files were:'
93
+ puts 'has timed out. Unprocessable files were:'
90
94
  puts '-----------------------------------------------------'
91
95
  puts parse_error_paths
92
96
  puts
@@ -42,8 +42,6 @@ module Fasterer
42
42
  @element
43
43
  when :iter
44
44
  @element[1]
45
- else
46
- fail '!!!!!!!'
47
45
  end
48
46
  end
49
47
 
@@ -77,33 +75,17 @@ module Fasterer
77
75
  element[2].drop(1).map { |argument| argument }
78
76
  end || []
79
77
  end
80
-
81
- def token
82
- element[0]
83
- end
84
78
  end
85
79
 
86
- # For now, used for determening if
87
- # the receiver is a reference or not.
80
+ # For now, used for determening if the
81
+ # receiver is a reference or a method call.
88
82
  class ReceiverFactory
89
- attr_reader :name
90
- attr_reader :method
91
-
92
83
  def self.new(receiver_info)
93
- return if receiver_info.nil?
94
- token = receiver_info.first
84
+ return unless receiver_info.is_a?(Sexp)
95
85
 
96
- case token
86
+ case receiver_info.sexp_type
97
87
  when :lvar
98
88
  return VariableReference.new(receiver_info)
99
- when :method_add_arg, :method_add_block
100
- case receiver_info[1][0]
101
- when :call, :fcall
102
- return MethodCall.new(receiver_info[1])
103
- else
104
- # binding.pry watch out for :method_add_arg
105
- # raise 'nije ni metoda'
106
- end
107
89
  when :call, :iter
108
90
  return MethodCall.new(receiver_info)
109
91
  end
@@ -4,34 +4,40 @@ module Fasterer
4
4
  attr_reader :method_name
5
5
  attr_reader :block_argument_name
6
6
  attr_reader :body
7
+ attr_reader :arguments
8
+
9
+ alias_method :name, :method_name
7
10
 
8
11
  def initialize(element)
9
12
  @element = element # Ripper element
10
13
  set_method_name
11
14
  set_body
12
-
13
- if arguments_element.any?
14
- set_argument_names
15
- set_block_argument_name
16
- end
15
+ set_arguments
16
+ set_block_argument_name
17
17
  end
18
18
 
19
19
  def has_block?
20
20
  !!@block_argument_name
21
21
  end
22
22
 
23
+ def setter?
24
+ name.to_s.end_with?('=')
25
+ end
26
+
23
27
  private
24
28
 
25
29
  def arguments_element
26
- element[2].drop(1)
30
+ element[2].drop(1) || []
27
31
  end
28
32
 
29
33
  def set_method_name
30
34
  @method_name = @element[1]
31
35
  end
32
36
 
33
- def set_argument_names
34
- # TODO
37
+ def set_arguments
38
+ @arguments = arguments_element.map do |argument_element|
39
+ MethodDefinitionArgument.new(argument_element)
40
+ end
35
41
  end
36
42
 
37
43
  def set_body
@@ -39,13 +45,53 @@ module Fasterer
39
45
  end
40
46
 
41
47
  def set_block_argument_name
42
- if last_argument.to_s.start_with?('&')
43
- @block_argument_name = last_argument.to_s[1..-1].to_sym
48
+ if last_argument_element.to_s.start_with?('&')
49
+ @block_argument_name = last_argument_element.to_s[1..-1].to_sym
44
50
  end
45
51
  end
46
52
 
47
- def last_argument
53
+ def last_argument_element
48
54
  arguments_element.last
49
55
  end
50
56
  end
57
+
58
+ class MethodDefinitionArgument
59
+
60
+ attr_reader :element, :name, :type
61
+
62
+ def initialize(element)
63
+ @element = element
64
+ set_name
65
+ set_argument_type
66
+ end
67
+
68
+ def regular_argument?
69
+ @type == :regular_argument
70
+ end
71
+
72
+ def default_argument?
73
+ @type == :default_argument
74
+ end
75
+
76
+ def keyword_argument?
77
+ @type == :keyword_argument
78
+ end
79
+
80
+ private
81
+
82
+ def set_name
83
+ @name = element.is_a?(Symbol) ? element : element[1]
84
+ end
85
+
86
+ def set_argument_type
87
+ @type = if element.is_a?(Symbol)
88
+ :regular_argument
89
+ elsif element.is_a?(Sexp) && element.sexp_type == :lasgn
90
+ :default_argument
91
+ elsif element.is_a?(Sexp) && element.sexp_type == :kwarg
92
+ :keyword_argument
93
+ end
94
+ end
95
+ end
96
+
51
97
  end
@@ -38,7 +38,7 @@ module Fasterer
38
38
  'Array#map.flatten(1) is slower than Array#flat_map',
39
39
 
40
40
  reverse_each_vs_reverse_each:
41
- 'Array#reverese.each is slower than Array#reverse_each',
41
+ 'Array#reverse.each is slower than Array#reverse_each',
42
42
 
43
43
  select_first_vs_detect:
44
44
  'Array#select.first is slower than Array#detect',
@@ -65,7 +65,13 @@ module Fasterer
65
65
  'Using tr is faster than gsub when replacing a single character in a string with another single character',
66
66
 
67
67
  select_last_vs_reverse_detect:
68
- 'Array#select.last is slower than Array#reverse.detect'
68
+ 'Array#select.last is slower than Array#reverse.detect',
69
+
70
+ getter_vs_attr_reader:
71
+ 'Use attr_reader for reading ivars',
72
+
73
+ setter_vs_attr_writer:
74
+ 'Use attr_writer for writing to ivars'
69
75
  }
70
76
 
71
77
  end
@@ -21,16 +21,5 @@ module Fasterer
21
21
  end.compact
22
22
  end
23
23
 
24
- def set_multiple_rescue_classes
25
- @rescue_classes = element[1].drop(1).map do |rescue_reference|
26
- rescue_reference.flatten[2]
27
- end
28
- end
29
-
30
- def set_single_rescue_class
31
- if element[1][0][0] == :var_ref
32
- @rescue_classes = Array(element[1][0][1][1])
33
- end
34
- end
35
24
  end
36
25
  end
@@ -19,6 +19,8 @@ module Fasterer
19
19
  def check_offense
20
20
  if method_definition.has_block?
21
21
  scan_block_call_offense
22
+ else
23
+ scan_getter_and_setter_offense
22
24
  end
23
25
  end
24
26
 
@@ -48,5 +50,37 @@ module Fasterer
48
50
  traverse_tree(element, &block)
49
51
  end
50
52
  end
53
+
54
+ def scan_getter_and_setter_offense
55
+ method_definition.setter? ? scan_setter_offense : scan_getter_offense
56
+ end
57
+
58
+ def scan_setter_offense
59
+ return if method_definition.arguments.size != 1
60
+ return if method_definition.body.size != 1
61
+
62
+ first_argument = method_definition.arguments.first
63
+ return if first_argument.type != :regular_argument
64
+
65
+ if method_definition.body.first.sexp_type == :iasgn &&
66
+ method_definition.body.first[1].to_s == "@#{method_definition.name.to_s[0..-2]}" &&
67
+ method_definition.body.first[2][1] == first_argument.name
68
+
69
+ add_offense(:setter_vs_attr_writer)
70
+ end
71
+ end
72
+
73
+ def scan_getter_offense
74
+ return if method_definition.arguments.size > 0
75
+ return if method_definition.body.size != 1
76
+
77
+ if method_definition.body.first.sexp_type == :ivar &&
78
+ method_definition.body.first[1].to_s == "@#{method_definition.name}"
79
+
80
+ add_offense(:getter_vs_attr_reader)
81
+ end
82
+ end
83
+
51
84
  end
85
+
52
86
  end
@@ -1,3 +1,3 @@
1
1
  module Fasterer
2
- VERSION = '0.1.8'
2
+ VERSION = '0.1.9'
3
3
  end
@@ -2,11 +2,11 @@ require 'spec_helper'
2
2
 
3
3
  describe Fasterer::Analyzer do
4
4
 
5
- let(:test_file_path) { RSpec.root.join('support', 'analyzer', '04_find_vs_bsearch.rb') }
5
+ let(:test_file_path) { RSpec.root.join('support', 'analyzer', '26_getter_vs_attr_reader.rb') }
6
6
 
7
- xit 'should detect Array#find' do
7
+ it 'should detect 2 getters' do
8
8
  analyzer = Fasterer::Analyzer.new(test_file_path)
9
9
  analyzer.scan
10
- # expect(analyzer.error_occurrence[:module_eval]).to eq(1)
10
+ expect(analyzer.errors[:getter_vs_attr_reader].count).to eq(2)
11
11
  end
12
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', '27_setter_vs_attr_writer.rb') }
6
+
7
+ it 'should detect 2 setters' do
8
+ analyzer = Fasterer::Analyzer.new(test_file_path)
9
+ analyzer.scan
10
+ expect(analyzer.errors[:setter_vs_attr_writer].count).to eq(2)
11
+ end
12
+ end
@@ -1,5 +1,6 @@
1
1
  require 'bundler/setup'
2
- Bundler.setup
2
+ require 'simplecov'
3
+ SimpleCov.start
3
4
 
4
5
  require 'fasterer'
5
6
  require 'pry'
@@ -0,0 +1,16 @@
1
+ def name
2
+ @name
3
+ end
4
+
5
+
6
+ class User
7
+
8
+ def name
9
+ @name
10
+ end
11
+ end
12
+
13
+
14
+ def name
15
+ @name = rand(1..100)
16
+ end
@@ -0,0 +1,13 @@
1
+ def name=(value)
2
+ @name = value
3
+ end
4
+
5
+ class User
6
+ def name=(value)
7
+ @name = value
8
+ end
9
+ end
10
+
11
+ def name=(value)
12
+ @name = [value]
13
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fasterer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damir Svrtan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-27 00:00:00.000000000 Z
11
+ date: 2015-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0.10'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.9'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.9'
97
111
  description: Use Fasterer to check various places in your code that could be faster.
98
112
  email:
99
113
  - damir.svrtan@gmail.com
@@ -133,7 +147,6 @@ files:
133
147
  - spec/lib/fasterer/analyzer/01_parallel_assignment_spec.rb
134
148
  - spec/lib/fasterer/analyzer/02_rescue_vs_respond_to_spec.rb
135
149
  - spec/lib/fasterer/analyzer/03_module_eval_spec.rb
136
- - spec/lib/fasterer/analyzer/04_find_vs_bsearch_spec.rb
137
150
  - spec/lib/fasterer/analyzer/06_shuffle_first_vs_sample_spec.rb
138
151
  - spec/lib/fasterer/analyzer/08_for_loop_vs_each_spec.rb
139
152
  - spec/lib/fasterer/analyzer/09_each_with_index_vs_while_spec.rb
@@ -148,6 +161,8 @@ files:
148
161
  - spec/lib/fasterer/analyzer/19_proc_call_vs_yield_spec.rb
149
162
  - spec/lib/fasterer/analyzer/24_gsub_vs_tr_spec.rb
150
163
  - spec/lib/fasterer/analyzer/25_select_last_vs_reverse_detect_spec.rb
164
+ - spec/lib/fasterer/analyzer/26_getter_vs_attr_reader_spec.rb
165
+ - spec/lib/fasterer/analyzer/27_setter_vs_attr_writer_spec.rb
151
166
  - spec/lib/fasterer/analyzer/98_misc_spec.rb
152
167
  - spec/lib/fasterer/analyzer/99_exceptional_files_spec.rb
153
168
  - spec/lib/fasterer/method_call_spec.rb
@@ -157,7 +172,6 @@ files:
157
172
  - spec/support/analyzer/01_parallel_assignment.rb
158
173
  - spec/support/analyzer/02_rescue_vs_respond_to.rb
159
174
  - spec/support/analyzer/03_module_eval.rb
160
- - spec/support/analyzer/04_find_vs_bsearch.rb
161
175
  - spec/support/analyzer/06_shuffle_first_vs_sample.rb
162
176
  - spec/support/analyzer/08_for_loop_vs_each.rb
163
177
  - spec/support/analyzer/09_each_with_index_vs_while.rb
@@ -172,6 +186,8 @@ files:
172
186
  - spec/support/analyzer/19_proc_call_vs_yield.rb
173
187
  - spec/support/analyzer/24_gsub_vs_tr.rb
174
188
  - spec/support/analyzer/25_select_last_vs_reverse_detect.rb
189
+ - spec/support/analyzer/26_getter_vs_attr_reader.rb
190
+ - spec/support/analyzer/27_setter_vs_attr_writer.rb
175
191
  - spec/support/analyzer/98_misc.rb
176
192
  - spec/support/analyzer/99_exceptional_files.rb
177
193
  - spec/support/binary_call/simple_comparison.rb
@@ -232,7 +248,6 @@ test_files:
232
248
  - spec/lib/fasterer/analyzer/01_parallel_assignment_spec.rb
233
249
  - spec/lib/fasterer/analyzer/02_rescue_vs_respond_to_spec.rb
234
250
  - spec/lib/fasterer/analyzer/03_module_eval_spec.rb
235
- - spec/lib/fasterer/analyzer/04_find_vs_bsearch_spec.rb
236
251
  - spec/lib/fasterer/analyzer/06_shuffle_first_vs_sample_spec.rb
237
252
  - spec/lib/fasterer/analyzer/08_for_loop_vs_each_spec.rb
238
253
  - spec/lib/fasterer/analyzer/09_each_with_index_vs_while_spec.rb
@@ -247,6 +262,8 @@ test_files:
247
262
  - spec/lib/fasterer/analyzer/19_proc_call_vs_yield_spec.rb
248
263
  - spec/lib/fasterer/analyzer/24_gsub_vs_tr_spec.rb
249
264
  - spec/lib/fasterer/analyzer/25_select_last_vs_reverse_detect_spec.rb
265
+ - spec/lib/fasterer/analyzer/26_getter_vs_attr_reader_spec.rb
266
+ - spec/lib/fasterer/analyzer/27_setter_vs_attr_writer_spec.rb
250
267
  - spec/lib/fasterer/analyzer/98_misc_spec.rb
251
268
  - spec/lib/fasterer/analyzer/99_exceptional_files_spec.rb
252
269
  - spec/lib/fasterer/method_call_spec.rb
@@ -256,7 +273,6 @@ test_files:
256
273
  - spec/support/analyzer/01_parallel_assignment.rb
257
274
  - spec/support/analyzer/02_rescue_vs_respond_to.rb
258
275
  - spec/support/analyzer/03_module_eval.rb
259
- - spec/support/analyzer/04_find_vs_bsearch.rb
260
276
  - spec/support/analyzer/06_shuffle_first_vs_sample.rb
261
277
  - spec/support/analyzer/08_for_loop_vs_each.rb
262
278
  - spec/support/analyzer/09_each_with_index_vs_while.rb
@@ -271,6 +287,8 @@ test_files:
271
287
  - spec/support/analyzer/19_proc_call_vs_yield.rb
272
288
  - spec/support/analyzer/24_gsub_vs_tr.rb
273
289
  - spec/support/analyzer/25_select_last_vs_reverse_detect.rb
290
+ - spec/support/analyzer/26_getter_vs_attr_reader.rb
291
+ - spec/support/analyzer/27_setter_vs_attr_writer.rb
274
292
  - spec/support/analyzer/98_misc.rb
275
293
  - spec/support/analyzer/99_exceptional_files.rb
276
294
  - spec/support/binary_call/simple_comparison.rb
@@ -1,5 +0,0 @@
1
- data = [1,2,3]
2
-
3
- data.bsearch { |number| number > 77_777_777 }
4
- data.find { |number| number > 77_777_777 }
5
-