fasterer 0.1.8 → 0.1.9

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