did_you_mean 0.10.0 → 1.0.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -18
  3. data/CHANGELOG.md +28 -3
  4. data/Gemfile +0 -7
  5. data/README.md +2 -16
  6. data/Rakefile +1 -13
  7. data/benchmark/memory_usage.rb +4 -4
  8. data/did_you_mean.gemspec +2 -12
  9. data/evaluation/calculator.rb +5 -5
  10. data/lib/did_you_mean.rb +18 -26
  11. data/lib/did_you_mean/core_ext/name_error.rb +15 -25
  12. data/lib/did_you_mean/formatter.rb +5 -11
  13. data/lib/did_you_mean/jaro_winkler.rb +3 -4
  14. data/lib/did_you_mean/levenshtein.rb +1 -1
  15. data/lib/did_you_mean/{finders.rb → spell_checkable.rb} +4 -12
  16. data/lib/did_you_mean/spell_checkers/method_name_checker.rb +54 -0
  17. data/lib/did_you_mean/{finders/name_error_finders.rb → spell_checkers/name_error_checkers.rb} +7 -7
  18. data/lib/did_you_mean/{finders/name_error_finders/class_finder.rb → spell_checkers/name_error_checkers/class_name_checker.rb} +8 -26
  19. data/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb +20 -0
  20. data/lib/did_you_mean/spell_checkers/null_checker.rb +6 -0
  21. data/lib/did_you_mean/version.rb +1 -1
  22. data/test/core_ext/name_error_extension_test.rb +20 -23
  23. data/test/correctable/class_name_test.rb +14 -14
  24. data/test/correctable/method_name_test.rb +21 -21
  25. data/test/correctable/variable_name_test.rb +30 -25
  26. data/test/{word_collection_test.rb → spell_checker_test.rb} +20 -20
  27. data/test/test_helper.rb +5 -8
  28. metadata +15 -50
  29. data/ext/did_you_mean/extconf.rb +0 -2
  30. data/ext/did_you_mean/method_receiver.c +0 -20
  31. data/lib/did_you_mean/core_ext/no_method_error.rb +0 -46
  32. data/lib/did_you_mean/core_ext/rubinius.rb +0 -16
  33. data/lib/did_you_mean/finders/method_finder.rb +0 -62
  34. data/lib/did_you_mean/finders/name_error_finders/name_finder.rb +0 -18
  35. data/lib/did_you_mean/test_helper.rb +0 -7
  36. data/test/core_ext/no_method_error_extension_test.rb +0 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d6d3f969922420aa102b5ee43ea65bdacb2b4725
4
- data.tar.gz: f210a32c4570c5dd2e6945651f4151f79a6e3080
3
+ metadata.gz: 8b34cbc0ccdd5f3ad3b8edce86667a3cc74b5378
4
+ data.tar.gz: 876c524186e3e5874bd5e481e18aaa94287dad63
5
5
  SHA512:
6
- metadata.gz: 1c9c187c605e907ee58179f3087d062e33ef69e9b40849b6157eacf9f64c61feb8b1eaa19894ef8e62fcc4d9a5599295551800514dc5285e436ac96a80034ec2
7
- data.tar.gz: ad9976fcd8321fa17a083a7f701ff2bd0b143dd3647c1116d0e1a239e26e0f9e4d8bc4fae552320f030620f8fc5da6c9c048c19447a641388a8ee8224e99a423
6
+ metadata.gz: 76ad432f1fe5a9d346d415a5c09b47f7563c4e176a8b522272a426b7baabbf38b149cfad7c7bf846a991f7599e535a9c6781d8661a7c65f09a638f84edb298e0
7
+ data.tar.gz: 8b52260010d946d8e341a11cf0969570e3c590da11f65d3c7f920a418714b382e6da7acb30e398ddc55727cee848135c42b338caafd0aced87766357f22b1061
@@ -3,27 +3,9 @@ script: bundle exec rake test
3
3
  cache: bundler
4
4
  sudo: false
5
5
 
6
- before_install:
7
- - 'if [[ "$TRAVIS_RUBY_VERSION" =~ "jruby" ]]; then rvm get head && rvm use --install $TRAVIS_RUBY_VERSION; fi'
8
-
9
6
  after_success:
10
7
  - bundle exec rake test:accuracy
11
8
  - bundle exec rake benchmark:memory
12
9
 
13
10
  rvm:
14
- - 1.9.3
15
- - 2.0.0
16
- - 2.1
17
- - 2.2
18
11
  - ruby-head
19
- - jruby-1.7.21
20
- - jruby-9.0.0.0
21
- - jruby-head
22
- - rbx-2.4.1
23
- - rbx-2.5.8
24
-
25
- matrix:
26
- allow_failures:
27
- - rvm: ruby-head
28
- - rvm: jruby-head
29
- fast_finish: true
@@ -1,3 +1,28 @@
1
+ ## [v0.10.0](https://github.com/yuki24/did_you_mean/tree/v0.10.0)
2
+
3
+ _<sup>released on 2015-08-21 06:44:11 UTC</sup>_
4
+
5
+ #### New Features
6
+
7
+ - Now it corrects an instance variable name if the ivar name is mistyped and `NoMethodError` is raised:
8
+
9
+ ```ruby
10
+ @number = 1
11
+ @nubmer.zero?
12
+ # => NoMethodError: undefined method `zero?' for nil:NilClass
13
+ #
14
+ # Did you mean? @number
15
+ #
16
+ ```
17
+
18
+ - Support for JRuby 9.0.0.0
19
+ - Prefix-based correction ( [@tjohn](https://github.com/tjohn), [#50](https://github.com/yuki24/did_you_mean/issues/50 "Match start of method name"), [#49](https://github.com/yuki24/did_you_mean/issues/49 "Use Jaro distance instead of Jaro-Winkler distance"))
20
+ - Correction search is about 75% faster than 0.9.10
21
+
22
+ #### Breaking Changes
23
+
24
+ - The ActiveRecord integration has been removed
25
+
1
26
  ## [v0.9.10](https://github.com/yuki24/did_you_mean/tree/v0.9.10)
2
27
 
3
28
  _<sup>released on 2015-05-14 03:04:47 UTC</sup>_
@@ -12,7 +37,7 @@ _<sup>released on 2015-05-13 03:48:19 UTC</sup>_
12
37
 
13
38
  #### Small/Internal Changes
14
39
 
15
- - Order word suggestions based on Levenshtein distance ( [@tleish](https://github.com/tleish), [#31](https://github.com/yuki24/did_you_mean/pull/31 "Order word suggestions based on Levenshtein.distance."))
40
+ - Order word corrections based on Levenshtein distance ( [@tleish](https://github.com/tleish), [#31](https://github.com/yuki24/did_you_mean/pull/31 "Order word corrections based on Levenshtein.distance."))
16
41
  - Reduce memory allocation by about 40%
17
42
  - Speed up Levenshtein distance calculation by about 40%
18
43
  - The Java extension has been replaced with a pure JRuby implementation
@@ -55,7 +80,7 @@ _<sup>released on 2014-11-19 20:00:00 UTC</sup>_
55
80
 
56
81
  #### Bug Fixes
57
82
 
58
- - Fixed a bug where no suggestions will be made on JRuby
83
+ - Fixed a bug where no corrections will be made on JRuby
59
84
 
60
85
  ## [v0.9.3](https://github.com/yuki24/did_you_mean/tree/v0.9.3)
61
86
 
@@ -150,7 +175,7 @@ _<sup>released on 2014-05-18 00:23:24 UTC</sup>_
150
175
 
151
176
  #### New Features
152
177
 
153
- - Added basic support for constants. Now you'll see class name suggestions when you misspelled a class names/module names:
178
+ - Added basic support for constants. Now you'll see class name corrections when you misspelled a class names/module names:
154
179
 
155
180
  ```ruby
156
181
  > Ocject
data/Gemfile CHANGED
@@ -6,10 +6,3 @@ gemspec
6
6
  gem 'benchmark-ips'
7
7
  gem 'memory_profiler'
8
8
  gem 'jaro_winkler', '~> 1.3.6'
9
-
10
- platforms :rbx do
11
- gem 'rubysl', '~> 2.0'
12
- gem 'rubysl-openssl', '2.2.1'
13
- gem 'racc'
14
- gem 'rubinius-developer_tools'
15
- end
data/README.md CHANGED
@@ -2,15 +2,9 @@
2
2
 
3
3
  'Did you mean?' experience in Ruby. No, Really.
4
4
 
5
- **For those who are still using 0.6.0, 0.7.0 and 0.8.0, please upgrade to the latest version (0.9.6) as they have a serious bug with Ruby 2.1.3 and 2.1.4 installed on Mac OS X.**
6
-
7
5
  ## Installation
8
6
 
9
- Add this line to your application's Gemfile:
10
-
11
- ```ruby
12
- gem 'did_you_mean', group: [:development, :test]
13
- ```
7
+ This gem will automatically be activated when a Ruby process starts up. No special setup is required.
14
8
 
15
9
  ## Examples
16
10
 
@@ -74,18 +68,10 @@ params.with_inddiferent_access
74
68
 
75
69
  ## 'Did You Mean' Experience is Everywhere
76
70
 
77
- _did\_you\_mean_ gem automagically puts method suggestions into the error message. This means you'll have the "Did you mean?" experience almost everywhere:
71
+ _did\_you\_mean_ gem automagically puts method corrections into the error message. This means you'll have the "Did you mean?" experience almost everywhere:
78
72
 
79
73
  ![Did you mean? on BetterErrors](https://raw.githubusercontent.com/yuki24/did_you_mean/master/doc/did_you_mean_example.png)
80
74
 
81
- ## Support
82
-
83
- _did\_you\_mean_ gem supports the following implementations:
84
-
85
- * MRI 1.9.3, 2.0.0, 2.1.x, 2.2.x and ruby-head
86
- * JRuby 1.7.21, 9.0.0.0 and jruby-head
87
- * Rubinius 2.4.1 and 2.5.8
88
-
89
75
  ## Contributing
90
76
 
91
77
  1. Fork it (http://github.com/yuki24/did_you_mean/fork)
data/Rakefile CHANGED
@@ -1,25 +1,13 @@
1
1
  require 'bundler/gem_tasks'
2
-
3
- if RUBY_ENGINE == "ruby"
4
- require 'rake/extensiontask'
5
-
6
- Rake::ExtensionTask.new 'did_you_mean' do |ext|
7
- ext.name = "method_receiver"
8
- ext.lib_dir = "lib/did_you_mean"
9
- end
10
- end
11
-
12
2
  require 'rake/testtask'
13
3
 
14
4
  Rake::TestTask.new do |task|
15
5
  task.libs << "test"
16
6
  task.pattern = 'test/**/*_test.rb'
17
7
  task.verbose = true
18
- # task.warning = true
8
+ task.warning = true
19
9
  end
20
10
 
21
- desc "Run tests"
22
- task test: [:clobber, :compile] if RUBY_ENGINE == 'ruby'
23
11
  task default: :test
24
12
 
25
13
  namespace :test do
@@ -6,18 +6,18 @@ require 'did_you_mean'
6
6
  # executable = -> { error.to_s }
7
7
 
8
8
  class DidYouMean::WordCollection
9
- include DidYouMean::BaseFinder
9
+ include DidYouMean::SpellCheckable
10
10
 
11
11
  def initialize(words)
12
12
  @words = words
13
13
  end
14
14
 
15
15
  def similar_to(input, filter = EMPTY)
16
- @suggestions, @input = nil, input
17
- suggestions
16
+ @corrections, @input = nil, input
17
+ corrections
18
18
  end
19
19
 
20
- def searches
20
+ def candidates
21
21
  { @input => @words }
22
22
  end
23
23
  end if !defined?(DidYouMean::WordCollection)
@@ -15,22 +15,12 @@ Gem::Specification.new do |spec|
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.test_files = spec.files.grep(%r{^(test)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.required_ruby_version = '>= 1.9.3'
22
-
23
- case RUBY_ENGINE
24
- when 'ruby'
25
- spec.extensions = ["ext/did_you_mean/extconf.rb"]
26
- when 'jruby'
27
- spec.platform = 'java'
28
- end
29
-
30
- spec.add_dependency "interception"
21
+ spec.required_ruby_version = '>= 2.3.0dev'
31
22
 
32
23
  spec.add_development_dependency "bundler", "~> 1.5"
33
24
  spec.add_development_dependency "rake"
34
- spec.add_development_dependency "rake-compiler"
35
25
  spec.add_development_dependency "minitest"
36
26
  end
@@ -38,18 +38,18 @@ report "loading program" do
38
38
  end
39
39
 
40
40
  class DidYouMean::WordCollection
41
- include DidYouMean::BaseFinder
41
+ include DidYouMean::SpellCheckable
42
42
 
43
43
  def initialize(words)
44
44
  @words = words
45
45
  end
46
46
 
47
47
  def similar_to(input, filter = EMPTY)
48
- @suggestions, @input = nil, input
49
- suggestions
48
+ @corrections, @input = nil, input
49
+ corrections
50
50
  end
51
51
 
52
- def searches
52
+ def candidates
53
53
  { @input => @words }
54
54
  end
55
55
 
@@ -119,4 +119,4 @@ File.open(filename, 'w') do |file|
119
119
  file.write(words_not_corrected.to_yaml)
120
120
  end
121
121
 
122
- puts "Incorrect suggestions were logged to #{filename}."
122
+ puts "Incorrect corrections were logged to #{filename}."
@@ -1,36 +1,28 @@
1
- require "interception"
2
-
3
1
  require "did_you_mean/version"
4
2
  require "did_you_mean/core_ext/name_error"
5
- require "did_you_mean/core_ext/no_method_error"
6
- require "did_you_mean/finders"
3
+
4
+ require "did_you_mean/spell_checkable"
5
+ require 'did_you_mean/spell_checkers/name_error_checkers'
6
+ require 'did_you_mean/spell_checkers/method_name_checker'
7
+ require 'did_you_mean/spell_checkers/null_checker'
8
+
7
9
  require "did_you_mean/formatter"
8
10
 
9
11
  module DidYouMean
10
- Interception.listen do |exception, binding|
11
- # On IRB/pry console, this event is called twice. In the second event,
12
- # we get IRB/pry binding. So it shouldn't override @frame_binding if
13
- # it's already defined.
14
- if DidYouMean.finders.include?(exception.class.to_s) && !exception.instance_variable_defined?(:@frame_binding)
15
- exception.instance_variable_set(:@frame_binding, binding)
16
- end
17
- end
12
+ @@trace = TracePoint.new(:raise) do |tp|
13
+ e, b = tp.raised_exception, tp.binding
18
14
 
19
- def self.finders
20
- @@finders ||= Hash.new(NullFinder)
15
+ if SPELL_CHECKERS.include?(e.class.to_s) && !e.instance_variable_defined?(:@frame_binding)
16
+ e.instance_variable_set(:@frame_binding, b)
17
+ end
21
18
  end
19
+ @@trace.enable
22
20
 
23
- finders.merge!("NameError" => NameErrorFinders)
21
+ IGNORED_CALLERS = []
24
22
 
25
- case RUBY_ENGINE
26
- when 'ruby', 'jruby'
27
- finders["NoMethodError"] = MethodFinder
28
- when 'rbx'
29
- finders["NoMethodError"] =
30
- if (___ rescue $!).class.to_s == "NameError" # For rbx > 2.5.0
31
- MethodFinder
32
- else
33
- MethodFinder::RubiniusSupport # For rbx < 2.5.0
34
- end
35
- end
23
+ SPELL_CHECKERS = Hash.new(NullChecker)
24
+ SPELL_CHECKERS.merge!({
25
+ "NameError" => NameErrorCheckers,
26
+ "NoMethodError" => MethodNameChecker
27
+ })
36
28
  end
@@ -1,38 +1,28 @@
1
1
  module DidYouMean
2
2
  module Correctable
3
+ prepend_features NameError
3
4
  attr_reader :frame_binding
4
5
 
5
- IGNORED_CALLERS = [
6
- /( |`)missing_name'/,
7
- /( |`)safe_constantize'/
8
- ].freeze
9
- private_constant :IGNORED_CALLERS
10
-
11
- def self.included(klass)
12
- klass.class_eval do
13
- __to_s__ = klass.instance_method(:to_s)
14
- define_method(:original_message){ __to_s__.bind(self).call }
6
+ def original_message
7
+ method(:to_s).super_method.call
8
+ end
15
9
 
16
- def to_s
17
- msg = original_message.dup
18
- bt = caller.first(6)
10
+ def to_s
11
+ msg = super.dup
12
+ bt = caller(1, 6)
19
13
 
20
- msg << Formatter.new(suggestions).to_s if IGNORED_CALLERS.all? {|ignored| bt.grep(ignored).empty? }
21
- msg
22
- rescue
23
- original_message
24
- end
25
- end
14
+ msg << Formatter.new(corrections).to_s if IGNORED_CALLERS.all? {|ignored| bt.grep(ignored).empty? }
15
+ msg
16
+ rescue
17
+ super
26
18
  end
27
19
 
28
- def suggestions
29
- finder.suggestions
20
+ def corrections
21
+ spell_checker.corrections
30
22
  end
31
23
 
32
- def finder
33
- @finder ||= DidYouMean.finders[self.class.to_s].new(self)
24
+ def spell_checker
25
+ @spell_checker ||= SPELL_CHECKERS[self.class.to_s].new(self)
34
26
  end
35
27
  end
36
28
  end
37
-
38
- NameError.send(:include, DidYouMean::Correctable)
@@ -1,20 +1,14 @@
1
1
  module DidYouMean
2
2
  class Formatter
3
- def initialize(suggestions = [])
4
- @suggestions = suggestions
3
+ def initialize(corrections = [])
4
+ @corrections = corrections
5
5
  end
6
6
 
7
7
  def to_s
8
- return "" if @suggestions.empty?
8
+ return "".freeze if @corrections.empty?
9
9
 
10
- output = "\n\n"
11
- output << " Did you mean? #{format(@suggestions.first)}\n"
12
- output << @suggestions.drop(1).map{|word| "#{' ' * 18}#{format(word)}\n" }.join
13
- output << " " # for rspec
14
- end
15
-
16
- def format(name)
17
- name
10
+ output = "\nDid you mean? "
11
+ output << @corrections.join("\n" << ' '.freeze * 15)
18
12
  end
19
13
  end
20
14
  end
@@ -13,9 +13,8 @@ module DidYouMean
13
13
  flags2 = 0
14
14
 
15
15
  # Avoid duplicating enumerable objects
16
- # Also, call #to_a since #codepoints returns an Enumerator on Ruby 1.9.3.
17
- str1_codepoints = str1.codepoints.to_a
18
- str2_codepoints = str2.codepoints.to_a
16
+ str1_codepoints = str1.codepoints
17
+ str2_codepoints = str2.codepoints
19
18
 
20
19
  i = 0
21
20
  while i < length1
@@ -69,7 +68,7 @@ module DidYouMean
69
68
  jaro_distance = Jaro.distance(str1, str2)
70
69
 
71
70
  if jaro_distance > THRESHOLD
72
- codepoints2 = str2.codepoints.to_a
71
+ codepoints2 = str2.codepoints
73
72
  prefix_bonus = 0
74
73
 
75
74
  i = 0
@@ -12,7 +12,7 @@ module DidYouMean
12
12
  x = nil
13
13
 
14
14
  # to avoid duplicating an enumerable object, create it outside of the loop
15
- str2_codepoints = str2.codepoints.to_a
15
+ str2_codepoints = str2.codepoints
16
16
 
17
17
  str1.each_codepoint.with_index(1) do |char1, i|
18
18
  j = 0
@@ -2,12 +2,12 @@ require "did_you_mean/levenshtein"
2
2
  require "did_you_mean/jaro_winkler"
3
3
 
4
4
  module DidYouMean
5
- module BaseFinder
5
+ module SpellCheckable
6
6
  AT = "@".freeze
7
7
  EMPTY = "".freeze
8
8
 
9
- def suggestions
10
- @suggestions ||= searches.flat_map do |input, candidates|
9
+ def corrections
10
+ @corrections ||= candidates.flat_map do |input, candidates|
11
11
  input = normalize(input)
12
12
  threshold = input.length > 3 ? 0.834 : 0.77
13
13
 
@@ -33,7 +33,7 @@ module DidYouMean
33
33
  end
34
34
  end
35
35
 
36
- def searches
36
+ def candidates
37
37
  raise NotImplementedError
38
38
  end
39
39
 
@@ -51,12 +51,4 @@ module DidYouMean
51
51
  str
52
52
  end
53
53
  end
54
-
55
- class NullFinder
56
- def initialize(*); end
57
- def suggestions; [] end
58
- end
59
54
  end
60
-
61
- require 'did_you_mean/finders/name_error_finders'
62
- require 'did_you_mean/finders/method_finder'