Giter Site home page Giter Site logo

fasterer's People

Contributors

adam-szczombrowski avatar christhomson avatar damirsvrtan avatar dukaev avatar ferdinandrosario avatar hlascelles avatar jeroenj avatar jumanjiman avatar kiyot avatar marcotc avatar mmozuras avatar olleolleolle avatar packetmonkey avatar pdsmcgavin avatar petergoldstein avatar pisaacs avatar swiknaba avatar tjchambers avatar vk26 avatar volosh1n avatar yous avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fasterer's Issues

How to make fasterer work on .rb files only

I have a ruby project has a folder structure like,
token
token\token.rb
token\lib\base.rb
token\lib\parts.rb
...
I could not find a way to work fasterer on my project. It does work in my rails projects until receiving an error like,

"Fasterer was unable to process some files because the
internal parser is not able to read some characters or
has timed out. Unprocessable files were:"

I really liked the idea of this gem and want to use it, but maybe documentation is not enough or there is a problem using it on custom ruby projects. Thanks.

Filters and defaults.

This probably shouldn't look at what's in vendor, and arguably config by default, yet I see no configuration option for limiting matches. Is that on the radar, or am I missing something?

Failing specs for Ruby 3

Running the specs with Ruby 3.0, the following failures occur:

Failures:

  1) Fasterer::Analyzer should detect gsub 4 times
     Failure/Error: expect(analyzer.errors[:gsub_vs_tr].count).to eq(2)
     
       expected: 2
            got: 1
     
       (compared using ==)
     # ./spec/lib/fasterer/analyzer/24_gsub_vs_tr_spec.rb:9:in `block (2 levels) in <top (required)>'

Finished in 2.04 seconds (files took 0.78213 seconds to load)
92 examples, 1 failure, 1 pending

Failed examples:

rspec ./spec/lib/fasterer/analyzer/24_gsub_vs_tr_spec.rb:6 # Fasterer::Analyzer should detect gsub 4 times

-> Due to the current Ruby version restrictions (see also #84), this gem cannot be installed with Ruby 3. Restrictions are relaxed here: #85

Expectation: specs are not failing.

update: specs fixed in #85

Use tr instead of gsub when grepping plain strings...unneccesary/wrong

Most of the hits I get are for plain string substitution...

ex., my_string.gsub('www.', 'dev.') # => replaces www. with dev.

Yes, I could move that trivial example into a regular expression just to avoid this suggestion, but what's the point in that?

The use of tr is such that each character in the 1st argument is replaced by it's corresponding position in the 2nd argument. It isn't a simple find/replace on the entire string. So this suggestion by fasterer yields far too many false positives.

Don’t advise to use each_key if the receiver doesn’t support it

fasterer advises to use each_key instead of keys.each even on objects that don’t support each_key:

# keys_each.rb
class KeysProvider
  def keys; []; end
end

kp = KeysProvider.new
kp.keys.each do |k|
  puts k
end
$ fasterer keys_each.rb
keys_each.rb
Hash#keys.each is slower than Hash#each_key. Occurred at lines: 6.

Rescue block (without a begin) within define_method throws a parser error.

This is a source code from my rails app models concern

# frozen_string_literal: true

module RecordNotUniqueHandler
  extend ActiveSupport::Concern

  included do
    define_method :create_or_update do |*args|
      super(*args)

    rescue ActiveRecord::RecordNotUnique => e
      attr_name, *scope = e.message
                           .match(/Key \(([^\)]+)\)/)[1].split(/,\s*/)

      message = +(errors.generate_message(attr_name, :taken))
      message << " (scope: #{scope.to_sentence})" if scope.any?
      errors.add attr_name, message
      false
    end
  end
end

fasterer outputs this error in the console

Fasterer was unable to process some files because the
internal parser is not able to read some characters or
has timed out. Unprocessable files were:
-----------------------------------------------------
app/models/concerns/record_not_unique_handler.rb - Racc::ParseError - (string):10 :: parse error on value ["rescue", 10] (kRESCUE)

Looks like it fails on this line rescue ActiveRecord::RecordNotUnique => e

Run fasterer on specified files' list

Hey there.

I was wondering if support for specifying a list of files to run Fasterer on could be added.

It would be really nice if we could make it work with xargs, I had this use case in mind:

echo app/controllers/application_controller.rb config/routes.rb | xargs bundle exec fasterer

Sometime module_eval can not be changed to define_method.

I have play fasterer in my code.It point out Using module_eval is slower than define_method. Occured at lines: 50..But my code is something like that:

class Thing
 @foo = 'test'
end
Thing.module_eval {puts @foo}

It can not be changed to define_method in this situation.So, it think it should not give me the suggestion anywhere I using module_eval.

unrecognized RUBY_VERSION 2.3.0

bundle exec fasterer

/home/ubuntu/optimize_it/vendor/bundle/ruby/2.3.0/gems/ruby_parser-3.7.2/lib/ruby_parser_extras.rb:1393:in `for_current_ruby': unrecognized RUBY_VERSION 2.3.0 (RuntimeError)
    from /home/ubuntu/optimize_it/vendor/bundle/ruby/2.3.0/gems/fasterer-0.3.1/lib/fasterer/parser.rb:8:in `parse'
    from /home/ubuntu/optimize_it/vendor/bundle/ruby/2.3.0/gems/fasterer-0.3.1/lib/fasterer/analyzer.rb:21:in `scan'
    from /home/ubuntu/optimize_it/vendor/bundle/ruby/2.3.0/gems/fasterer-0.3.1/lib/fasterer/file_traverser.rb:58:in `scan_file'
    from /home/ubuntu/optimize_it/vendor/bundle/ruby/2.3.0/gems/fasterer-0.3.1/lib/fasterer/file_traverser.rb:50:in `block in traverse_files'
    from /home/ubuntu/optimize_it/vendor/bundle/ruby/2.3.0/gems/fasterer-0.3.1/lib/fasterer/file_traverser.rb:50:in `each'
    from /home/ubuntu/optimize_it/vendor/bundle/ruby/2.3.0/gems/fasterer-0.3.1/lib/fasterer/file_traverser.rb:50:in `traverse_files'
    from /home/ubuntu/optimize_it/vendor/bundle/ruby/2.3.0/gems/fasterer-0.3.1/lib/fasterer/file_traverser.rb:27:in `traverse'
    from /home/ubuntu/optimize_it/vendor/bundle/ruby/2.3.0/gems/fasterer-0.3.1/lib/fasterer/cli.rb:7:in `execute'
    from /home/ubuntu/optimize_it/vendor/bundle/ruby/2.3.0/gems/fasterer-0.3.1/bin/fasterer:5:in `<top (required)>'
    from /home/ubuntu/optimize_it/vendor/bundle/ruby/2.3.0/bin/fasterer:23:in `load'

from /home/ubuntu/optimize_it/vendor/bundle/ruby/2.3.0/bin/fasterer:23:in `<main>' bundle exec fasterer returned exit code 1

RUBY_ENGINE Specific Suggestions?

Hi, very nice program here :neckbeard: 👍. Just started using it and, being very familiar with the fast-ruby benchmarks, I thought that I would be nice to have RUBY_ENGINE specific suggestions.

I know you have your disclaimer -and certainly we should not blindly do whatever the machine tells us, but in the case of JRuby (maybe others) some of the suggestions are counterintuitive to what most people think is "fast ruby". Tailoring suggestions for the platform could be very helpful.

Thoughts?

Allow the user to run on a single file

Hello!

I work on some rather large codebases, and running the very cool fasterer on them results in more information than is humanly manageable. It would be nice if I could run it on a single file (the one I'm working on). i.e.

$ fasterer app/controllers/users_controller.rb

Thanks,
Louis

Error message - please consider improving it

Hi,

I was trying to use fasterer on a single .rb file:

fasterer wlan.rb

I get the following error message:

Fasterer was unable to process some files because the
internal parser is not able to read some characters or
has timed out. Unprocessable files were:

wlan.rb


This error message does not tell me much. What are the
bad characters? Why can it not process?

For reference, the file wlan.rb is available at:

https://gist.github.com/shevegen/3fe9e1a35b1b9dd52fee

Advising to use each_key if the block modifies the hash

Let's say we're creating something like Rails' indifferent access for hashes:

> cat foo.rb
def my_with_indifferent_access(hash)
  hash.keys.each do |k|
    hash[k.to_sym] = hash[k] if k.is_a?(String)
  end

  hash
end

puts my_with_indifferent_access({ 'a' => 1 })[:a]

> ruby foo.rb
1

fasterer 0.3.2 says

Hash#keys.each is slower than Hash#each_key. Occurred at lines: 2.

but making that change gives a runtime error:

> ruby foo.rb
foo.rb:3:in `block in my_with_indifferent_access': can't add a new key into hash during iteration (RuntimeError)
        from foo.rb:2:in `each_key'
        from foo.rb:2:in `my_with_indifferent_access'
        from foo.rb:9:in `<main>'

While it would be great if fasterer could inspect the block of the each and attempt to determine if the hash is modified during the iteration (not outputting the warning if so), this isn't possible in general. Furthermore, looking at the current implementation, it doesn't look like any of the necessary context is available where the warning is raised.

A better solution might be to explicitly warn that blindly replacing keys.each with each_key is not safe in general, perhaps something like:

Hash#keys.each is slower than Hash#each_key. N.B. 'Hash#each_key' cannot be used if the hash is modified during theeachblock. Occurred at lines: 2.

Re fetch_with_argument_vs_block , is it really faster?

It doesn't seem faster when I tested:

Rehearsal -------------------------------------------------------------
hash with second argument   1.460000   0.010000   1.470000 (  1.504500)
hash with block             1.570000   0.010000   1.580000 (  1.575685)
---------------------------------------------------- total: 3.050000sec

                                user     system      total        real
hash with second argument   1.210000   0.000000   1.210000 (  1.216288)
hash with block             1.580000   0.000000   1.580000 (  1.583985)
› ruby --version
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]

Test Code:

require 'benchmark'
require 'json'

$hash  = {}
COUNTER = 5000000
Benchmark.bmbm do |repo|
  repo.report("hash with second argument") do
    0.upto(COUNTER) { $hash.fetch('moshe', 'default') }
  end
  repo.report("hash with block")  do
    0.upto(COUNTER) { $hash.fetch('moshe') {'default' } }
  end

end

Maybe it is something related to older version of ruby?

Is this tool still maintained?

Hey there, I can see, that there are some PRs and that the code haven't been updated for quite a while. Just wanted to know, whether or not it is still maintained.

Block vs Symbol to Proc rule

I've run into 2 issues with the Block vs Symbol to Proc offense.

  1. The following code is flagged correctly:
numbers.each { |number| number.to_s }

but, this is not flagged:

numbers = [1, 2, 3, 4, 5]
numbers.each { |number| number.to_s }

Both have the same each block, but the parser dismisses it once the previous code is added.

  1. This only detects each blocks and not any others. There are many other block methods names which should also be included (map, find, any?, etc). So, the following code is not flagged.
numbers.map { |number| number.to_s }

or

numbers.any? { |number| number.even? }

Redis #keys method shouldn't trigger Hash#each_key recommendation

Hi! First, thanks so much for fasterer -- it's super helpful!

I wanted to report a false-positive finding that I noticed. When using a Redis client, I'm using its keys method, which lists the names of the Redis server's keys. At least in this case, Fasterer makes a recommendation based on an incorrect presumption that the receiver is a Hash, not a Redis connection handle.

$ cat > foo.rb
@redis.keys('queue:*').each do |queue_name|
  puts queue_name
end
^D

$ bundle exec fasterer foo.rb
foo.rb:1 Hash#keys.each is slower than Hash#each_key. N.B. Hash#each_key cannot be used if the hash is modified during the each block.

1 file inspected, 1 offense detected

Error "Scan"

$ fasterer
app/controllers/data/charts_controller.rb
For loop is slower than using each. Occured at lines: 76, 87, 90, 102, 206, 240.

app/controllers/data_controller.rb
For loop is slower than using each. Occured at lines: 119, 146, 147.

app/models/country.rb
For loop is slower than using each. Occured at lines: 22, 26.

app/models/event.rb
For loop is slower than using each. Occured at lines: 445, 459, 472, 486, 498, 614.

app/models/user.rb
Calling argumentless methods within blocks is slower than using symbol to proc. Occured at lines: 21, 31.

/Users/dan/.rvm/gems/ruby-2.2.0/gems/ruby_parser-3.6.4/lib/ruby_lexer.rex.rb:288:in `scan': execution expired (Timeout::Error)
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/ruby_parser-3.6.4/lib/ruby_lexer.rex.rb:288:in `next_token'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/ruby_parser-3.6.4/lib/ruby_parser_extras.rb:919:in `next_token'
    from /Users/dan/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/racc/parser.rb:258:in `_racc_do_parse_c'
    from /Users/dan/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/racc/parser.rb:258:in `do_parse'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/ruby_parser-3.6.4/lib/ruby_parser_extras.rb:1036:in `block in process'
    from /Users/dan/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/timeout.rb:89:in `block in timeout'
    from /Users/dan/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/timeout.rb:34:in `block in catch'
    from /Users/dan/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/timeout.rb:34:in `catch'
    from /Users/dan/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/timeout.rb:34:in `catch'
    from /Users/dan/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/timeout.rb:104:in `timeout'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/ruby_parser-3.6.4/lib/ruby_parser_extras.rb:1024:in `process'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/ruby_parser-3.6.4/lib/ruby_parser_extras.rb:1357:in `block in process'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/ruby_parser-3.6.4/lib/ruby_parser_extras.rb:1355:in `each'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/ruby_parser-3.6.4/lib/ruby_parser_extras.rb:1355:in `process'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/fasterer-0.1.7/lib/fasterer/parser.rb:8:in `parse'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/fasterer-0.1.7/lib/fasterer/analyzer.rb:21:in `scan'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/fasterer-0.1.7/lib/fasterer/file_traverser.rb:56:in `scan_file'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/fasterer-0.1.7/lib/fasterer/file_traverser.rb:67:in `block in traverse_directory'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/fasterer-0.1.7/lib/fasterer/file_traverser.rb:64:in `each'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/fasterer-0.1.7/lib/fasterer/file_traverser.rb:64:in `traverse_directory'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/fasterer-0.1.7/lib/fasterer/file_traverser.rb:27:in `traverse'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/fasterer-0.1.7/lib/fasterer/cli.rb:7:in `execute'
    from /Users/dan/.rvm/gems/ruby-2.2.0/gems/fasterer-0.1.7/bin/fasterer:5:in `<top (required)>'
    from /Users/dan/.rvm/gems/ruby-2.2.0/bin/fasterer:23:in `load'
    from /Users/dan/.rvm/gems/ruby-2.2.0/bin/fasterer:23:in `<main>'
    from /Users/dan/.rvm/gems/ruby-2.2.0/bin/ruby_executable_hooks:15:in `eval'
    from /Users/dan/.rvm/gems/ruby-2.2.0/bin/ruby_executable_hooks:15:in `<main>'

Fasterer speedup for hash_update_vs_hash_brackets

Hash.update is an alias for Hash.merge!

Currently we have hash_merge_bang_vs_hash_brackets which suggests us to replace Hash#merge!() with Hash#[] but it doesn't suggest for Hash#update().

Example

  • hash.merge!({"key" => "value"}) -> offensive
  • hash.update({"key" => value}) -> not offensive

Can we extend this to Hash.update()?

Add support for json output

It'd be nice to have JSON output, maybe something like --format json or even --json. This would make the integration with editors like VSCode way easier.

Feature Request: Line-level Inline Exclusions

I think it would be a great enhancement if I was able to disable/exclude a speed suggestion for a specific line via a magic comment (much like how Rubocop does single-instance cop-disablement; # rubocop:disable Metrics/LineLength).

There are times where a single speedup in a given line of code is not applicable and I want to disable the speedup for the line but I don't want to have to add the entire file to the exclude_paths block of .fasterer.yml.

For example, if I have instance whereby I've used Hash#keys.each two times in a single file and one of those two times the hash is modified during the .each block (but the other time, the hash is not modified during the .each block) then I would want fasterer to ignore that singular instance of Hash#keys.each where the hash is modified (while still letting fasterer analyze the other instance of Hash#keys.each where the hash is not modified).

Hopefully this makes sense and seems reasonable!

Thanks for all the work put into fasterer over the years; it has certainly made some of my code... well... fasterer. 😄

fasterer doesn't work with file matrix.rb of standard library

$ fasterer /usr/lib/ruby/2.7.0/matrix.rb 
NOTE: RubyParser::V27 undefined, using RubyParser::V26.
Fasterer was unable to process some files because the
internal parser is not able to read some characters or
has timed out. Unprocessable files were:
-----------------------------------------------------
/usr/lib/ruby/2.7.0/matrix.rb - Racc::ParseError - (string):2256 :: parse error on value "," (tCOMMA)

1 file inspected, 0 offenses detected, 1 unparsable file found

Autocorrect

Rubocop has an auto correct method. It would be nice to see something similar within fasterer (with an appropriate warning)

Feature Request: JUnit.xml output format

It is widely accepted by CI services to integrate with their UI. I think it'd be nice. I'd like it to be used this way:

bundle exec fasterer --format junit --output fasterer.xml

Thanks, keep up the good work.

Array#last.reverse is faster than Array#reverse.first and viceversa

Running this code:

#!/usr/bin/env ruby

require 'benchmark/ips'

ARR1 = [ 1, 2, 3 ] * 1_000_000

Benchmark.ips do |b|
  b.report('.reverse.first') do
    ARR1.reverse.first(1_000)
  end

  b.report('.last.reverse') do
    ARR1.last(1_000).reverse
  end

  b.compare!
end

Benchmark.ips do |b|
  b.report('.reverse.last') do
    ARR1.reverse.last(1_000)
  end

  b.report('.first.reverse') do
    ARR1.first(1_000).reverse
  end

  b.compare!
end

we see a huge speed difference for this simple synthetic benchmark:

Calculating -------------------------------------
      .reverse.first        24 i/100ms
       .last.reverse     80711 i/100ms
-------------------------------------------------
      .reverse.first      153.7 (±3.3%) i/s -        792 in   5.157104s
       .last.reverse  1155593.4 (±2.0%) i/s -    5811192 in   5.030946s

Comparison:
       .last.reverse:  1155593.4 i/s
      .reverse.first:      153.7 i/s - 7516.20x slower

Calculating -------------------------------------
       .reverse.last        25 i/100ms
      .first.reverse     83388 i/100ms
-------------------------------------------------
       .reverse.last      259.5 (±4.6%) i/s -       1300 in   5.022875s
      .first.reverse  1050525.6 (±8.4%) i/s -    5253444 in   5.047410s

Comparison:
      .first.reverse:  1050525.6 i/s
       .reverse.last:      259.5 i/s - 4048.21x slower

It's pretty intuitive that it works this way:
Let's say our array has N elements, and we want the last n but reversed.
We can either reverse it first, making N swaps (i.e. copies) and then copy the first n elements, making N+n copies, or we can take the last n elements, making n copies and then swap them n times, performing 2*n copies.

I'm working in a detector for these opportunities, but I don't know if I'll make it.

%I[] notation parser error

I seems there is a bug in support for interpolated array of symbols separated by whitespace (Ruby > 2.X)

test.rb file:

#!/usr/bin/env ruby

puts %I[#{42}].inspect

Code works:

> ruby --version
ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-linux]
> ruby test.rb 
[:"42"]

fasterer parser error:

> fasterer test.rb
~/.gem/ruby/2.4.2/gems/ruby_parser-3.10.1/lib/ruby_parser_extras.rb:23:in `debug20': not yet 24 nil => nil (RuntimeError)
	from ~/.gem/ruby/2.4.2/gems/ruby_parser-3.10.1/lib/ruby_parser_extras.rb:883:in `new_symbol_list_entry'
	from ~/.gem/ruby/2.4.2/gems/ruby_parser-3.10.1/lib/ruby24_parser.rb:5950:in `_reduce_467'
	from ~/.rubies/ruby-2.4.2/lib/ruby/2.4.0/racc/parser.rb:259:in `_racc_do_parse_c'
	from ~/.rubies/ruby-2.4.2/lib/ruby/2.4.0/racc/parser.rb:259:in `do_parse'
	from ~/.gem/ruby/2.4.2/gems/ruby_parser-3.10.1/lib/ruby_parser_extras.rb:1087:in `block in process'
	from ~/.rubies/ruby-2.4.2/lib/ruby/2.4.0/timeout.rb:93:in `block in timeout'
	from ~/.rubies/ruby-2.4.2/lib/ruby/2.4.0/timeout.rb:33:in `block in catch'
	from ~/.rubies/ruby-2.4.2/lib/ruby/2.4.0/timeout.rb:33:in `catch'
	from ~/.rubies/ruby-2.4.2/lib/ruby/2.4.0/timeout.rb:33:in `catch'
	from ~/.rubies/ruby-2.4.2/lib/ruby/2.4.0/timeout.rb:108:in `timeout'
	from ~/.gem/ruby/2.4.2/gems/ruby_parser-3.10.1/lib/ruby_parser_extras.rb:1075:in `process'
	from ~/.gem/ruby/2.4.2/gems/fasterer-0.3.2/lib/fasterer/parser.rb:8:in `parse'
	from ~/.gem/ruby/2.4.2/gems/fasterer-0.3.2/lib/fasterer/analyzer.rb:21:in `scan'
	from ~/.gem/ruby/2.4.2/gems/fasterer-0.3.2/lib/fasterer/file_traverser.rb:57:in `scan_file'
	from ~/.gem/ruby/2.4.2/gems/fasterer-0.3.2/lib/fasterer/file_traverser.rb:49:in `block in traverse_files'
	from ~/.gem/ruby/2.4.2/gems/fasterer-0.3.2/lib/fasterer/file_traverser.rb:49:in `each'
	from ~/.gem/ruby/2.4.2/gems/fasterer-0.3.2/lib/fasterer/file_traverser.rb:49:in `traverse_files'
	from ~/.gem/ruby/2.4.2/gems/fasterer-0.3.2/lib/fasterer/file_traverser.rb:26:in `traverse'
	from ~/.gem/ruby/2.4.2/gems/fasterer-0.3.2/lib/fasterer/cli.rb:7:in `execute'
	from ~/.gem/ruby/2.4.2/gems/fasterer-0.3.2/bin/fasterer:5:in `<top (required)>'
	from ~/.gem/ruby/2.4.2/bin/fasterer:23:in `load'
	from ~/.gem/ruby/2.4.2/bin/fasterer:23:in `<main>'

undefined method `name' for #<Fasterer::Primitive:0x00007f9a2092afd8>

I just installed fasterer 0.8.1 and got the following error on running it:

% fasterer
app/models/freelancers/freelancer.rb:149 Array#reverse.each is slower than Array#reverse_each.

app/models/concerns/has_phone_numbers.rb:100 Using tr is faster than gsub when replacing a single character in a string with another single character.

app/dashboards/freelancers/freelancer_dashboard.rb:102 Hash#keys.each is slower than Hash#each_key. N.B. Hash#each_key cannot be used if the hash is modified during the each block.

app/controllers/admin/freelancers_controller.rb:137 Array#select.last is slower than Array#reverse.detect.

Traceback (most recent call last):
	34: from /Users/manuel/.rbenv/versions/2.6.5/bin/fasterer:23:in `<main>'
	33: from /Users/manuel/.rbenv/versions/2.6.5/bin/fasterer:23:in `load'
	32: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/bin/fasterer:5:in `<top (required)>'
	31: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/cli.rb:7:in `execute'
	30: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/file_traverser.rb:26:in `traverse'
	29: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/file_traverser.rb:49:in `traverse_files'
	28: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/file_traverser.rb:49:in `each'
	27: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/file_traverser.rb:49:in `block in traverse_files'
	26: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/file_traverser.rb:57:in `scan_file'
	25: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:22:in `scan'
	24: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `traverse_sexp_tree'
	23: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `each'
	22: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `block in traverse_sexp_tree'
	21: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `traverse_sexp_tree'
	20: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `each'
	19: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `block in traverse_sexp_tree'
	18: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `traverse_sexp_tree'
	17: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `each'
	16: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `block in traverse_sexp_tree'
	15: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `traverse_sexp_tree'
	14: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `each'
	13: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `block in traverse_sexp_tree'
	12: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `traverse_sexp_tree'
	11: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `each'
	10: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `block in traverse_sexp_tree'
	 9: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `traverse_sexp_tree'
	 8: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `each'
	 7: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:45:in `block in traverse_sexp_tree'
	 6: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:36:in `traverse_sexp_tree'
	 5: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:54:in `scan_by_token'
	 4: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:71:in `scan_method_calls'
	 3: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/analyzer.rb:71:in `new'
	 2: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/scanners/method_call_scanner.rb:13:in `initialize'
	 1: from /Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/scanners/method_call_scanner.rb:48:in `check_offense'
/Users/manuel/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/fasterer-0.8.1/lib/fasterer/scanners/method_call_scanner.rb:135:in `check_symbol_to_proc': undefined method `name' for #<Fasterer::Primitive:0x00007f9a2092afd8> (NoMethodError)

False positive for select_first_vs_detect when `first` is `first(N)`

With this example code:

(1..100).select { |i| i >= 50 }.first(5)

fasterer 0.10.0 reports Array#select.first is slower than Array#detect..

However, this is only true when Enumerable#first takes no argument; here we want the first 5 matching elements and detect does not support that functionality.

I suggest that this detector only fires when first is passed no argument

Required ruby version

Did 0.8.3 version really requires ruby ~> 2.2? Can this requirements relaxed to >= 2.2?

Does not work if there are Ruby 3.0 one line methods in the code

Got Racc::ParseError - (string):3 :: parse error on value "=" (tEQL)

Code example that break execution:

module ToBoolean
  refine Object do
    def to_bool = ActiveRecord::Type::Boolean.new.cast(self)
  end

  refine TrueClass do
    def to_bool = self
  end

  refine FalseClass do
    def to_bool = self
  end

  refine NilClass do
    def to_bool = self
  end

  refine Numeric do
    def to_bool = !zero?
  end
end

Ruby 2.6 support

  1. Install Ruby stable version 2.6.0
  2. Run fasterer
NOTE: RubyParser::V26 undefined, using RubyParser::V25.

Encoding::CompatibilityError: incompatible character encodings: UTF-8 and ASCII-8BIT

when running fasterer I get:

bundler: failed to load command: fasterer (/home/mencio/.rbenv/versions/2.6.5/bin/fasterer)
Encoding::CompatibilityError: incompatible character encodings: UTF-8 and ASCII-8BIT
  gems/ruby_parser-3.14.0/lib/ruby_lexer.rex.rb:163:in `gsub'
  gems/ruby_parser-3.14.0/lib/ruby_lexer.rex.rb:163:in `block in next_token'
  gems/ruby_parser-3.14.0/lib/ruby_lexer.rex.rb:68:in `action'
  gems/ruby_parser-3.14.0/lib/ruby_lexer.rex.rb:163:in `next_token'
  gems/ruby_parser-3.14.0/lib/ruby_parser_extras.rb:1266:in `next_token'
  /home/mencio/.rbenv/versions/2.6.5/lib/ruby/2.6.0/racc/parser.rb:259:in `_racc_do_parse_c'
  /home/mencio/.rbenv/versions/2.6.5/lib/ruby/2.6.0/racc/parser.rb:259:in `do_parse'
  gems/ruby_parser-3.14.0/lib/ruby_parser_extras.rb:1301:in `block in process'
  /home/mencio/.rbenv/versions/2.6.5/lib/ruby/2.6.0/timeout.rb:93:in `block in timeout'
  /home/mencio/.rbenv/versions/2.6.5/lib/ruby/2.6.0/timeout.rb:33:in `block in catch'
  /home/mencio/.rbenv/versions/2.6.5/lib/ruby/2.6.0/timeout.rb:33:in `catch'
  /home/mencio/.rbenv/versions/2.6.5/lib/ruby/2.6.0/timeout.rb:33:in `catch'
  /home/mencio/.rbenv/versions/2.6.5/lib/ruby/2.6.0/timeout.rb:108:in `timeout'
  gems/ruby_parser-3.14.0/lib/ruby_parser_extras.rb:1289:in `process'
  gems/fasterer-0.7.1/lib/fasterer/parser.rb:8:in `parse'
  gems/fasterer-0.7.1/lib/fasterer/analyzer.rb:21:in `scan'
  gems/fasterer-0.7.1/lib/fasterer/file_traverser.rb:57:in `scan_file'
  gems/fasterer-0.7.1/lib/fasterer/file_traverser.rb:49:in `block in traverse_files'
  gems/fasterer-0.7.1/lib/fasterer/file_traverser.rb:49:in `each'
  gems/fasterer-0.7.1/lib/fasterer/file_traverser.rb:49:in `traverse_files'
  gems/fasterer-0.7.1/lib/fasterer/file_traverser.rb:26:in `traverse'
  gems/fasterer-0.7.1/lib/fasterer/cli.rb:7:in `execute'
  gems/fasterer-0.7.1/bin/fasterer:5:in `<top (required)>'
  /home/mencio/.rbenv/versions/2.6.5/bin/fasterer:23:in `load'
  /home/mencio/.rbenv/versions/2.6.5/bin/fasterer:23:in `<top (required)>'

repro:

git clone https://github.com/mensfeld/broken-fasterer.git
cd broken-fasterer
./run.sh

Output with directly in line

👋Hi
With this output, we can faster go to files directly in line.
I checked in RubyMine and Sublime Text, Visual Studio Code, also it works in vim.
Output:

code.rb:5 Using each_with_index is slower than while loop.
code.rb:21 Using each_with_index is slower than while loop.
code.rb:37 Enumerable#sort is slower than Enumerable#sort_by.

What do you think about this? If you like it I can do it :)

Report with links

Report with links will be more informative.

lib/code.rb:9 Use attr_reader for reading ivars [https://github.com/DamirSvrtan/fasterer/docs/attr_reader_vs_ivars.md]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.