did_you_mean 1.0.4 → 1.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/.travis.yml +0 -6
  4. data/CHANGELOG.md +28 -2
  5. data/Gemfile +1 -1
  6. data/README.md +12 -2
  7. data/Rakefile +3 -8
  8. data/benchmark/memory_usage.rb +1 -1
  9. data/did_you_mean.gemspec +3 -4
  10. data/evaluation/calculator.rb +4 -3
  11. data/evaluation/incorrect_words.yaml +1 -1
  12. data/lib/did_you_mean/core_ext/name_error.rb +3 -6
  13. data/lib/did_you_mean/experimental/initializer_name_correction.rb +1 -1
  14. data/lib/did_you_mean/formatter.rb +1 -1
  15. data/lib/did_you_mean/levenshtein.rb +2 -0
  16. data/lib/did_you_mean/spell_checker.rb +12 -14
  17. data/lib/did_you_mean/spell_checkers/method_name_checker.rb +8 -5
  18. data/lib/did_you_mean/spell_checkers/name_error_checkers.rb +4 -1
  19. data/lib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb +3 -6
  20. data/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb +5 -2
  21. data/lib/did_you_mean/verbose_formatter.rb +1 -1
  22. data/lib/did_you_mean/version.rb +1 -1
  23. data/test/core_ext/name_error_extension_test.rb +1 -13
  24. data/test/edit_distance/jaro_winkler_test.rb +1 -0
  25. data/test/spell_checker_test.rb +0 -1
  26. data/test/spell_checking/class_name_test.rb +0 -12
  27. data/test/spell_checking/method_name_test.rb +9 -24
  28. data/test/spell_checking/variable_name_test.rb +15 -6
  29. data/test/test_helper.rb +4 -2
  30. data/test/verbose_formatter_test.rb +4 -3
  31. metadata +10 -16
  32. data/lib/did_you_mean/extra_features.rb +0 -3
  33. data/test/experimental/deprecated_features_test.rb +0 -13
  34. data/test/fixtures/book.rb +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 95c8a3e5873fe852e2de4de33e70ada6b4695bf5
4
- data.tar.gz: ab23c8333c2fb0c3df66b804a1fc1274eb21674c
3
+ metadata.gz: 70f21af56b6f4e14b5c5984d3ce5180a779c81c9
4
+ data.tar.gz: 1f73d774f056a90eadace8401876b6f35ea54177
5
5
  SHA512:
6
- metadata.gz: 7b1d6d10f8e658fa070c97752ff09b961b57b53f71a434546a81b522f87a32129c25a398efc55a3076ed617ac9b3a6414c0005d7c0492c89d55f1398de618c23
7
- data.tar.gz: 47631c99fab406a57242310173b0f4154c00b70bc8ca113f665f0b93710625c3d3811f3e352e2d181a4ffd8ca89d855b792775919d98ffec68700b4dab5a40a0
6
+ metadata.gz: 17fbd60b5fd5a951b241b1b0277b1888c3495849825fd699dd1da24a8ac9b4b0a7366505f3584a3a41c125e785b6be556ae0a7f736168e39cb3b6d6b36a3cfa5
7
+ data.tar.gz: 6a63b180eb98df8cfd4c59c209e9ff676d07e80b548d3d07c05e5e619cacd2725097d9f3da0037b34b517fcedb6c605229c0c4ab5c4fd68a68f124e03d85e9c1
@@ -0,0 +1 @@
1
+ 2.4.0-dev
@@ -11,10 +11,4 @@ after_success:
11
11
  - bundle exec rake benchmark:memory
12
12
 
13
13
  rvm:
14
- - 2.3.1
15
14
  - ruby-head
16
- - jruby-head
17
-
18
- matrix:
19
- allow_failures:
20
- - rvm: jruby-head
@@ -1,3 +1,29 @@
1
+ ## [v1.0.2](https://github.com/yuki24/did_you_mean/tree/v1.0.2)
2
+
3
+ _<sup>released on 2016-06-20 18:03:07 UTC</sup>_
4
+
5
+ #### Features
6
+
7
+ - Experimental features are officially available through `require 'did_you_mean/experimental'`
8
+
9
+ #### Deprecations
10
+
11
+ - `require 'did_you_mean/extra_features'` is now deprecated in favor of `require 'did_you_mean/experimental'`
12
+
13
+ #### Internal Changes
14
+
15
+ - Replaced the `DidYouMean::SpellCheckable` module with the `DidYouMean::SpellChecker` class. This is a slower implementation but close to the model explained in [this talk](https://speakerdeck.com/yuki24/saving-people-from-typos), more reusable and possibly makes it easier to expose the class as a public interface.
16
+
17
+ ## [v1.0.1](https://github.com/yuki24/did_you_mean/tree/v1.0.1)
18
+
19
+ _<sup>released on 2016-05-15 05:17:22 UTC</sup>_
20
+
21
+ #### Bug Fixes
22
+
23
+ - Fixed a bug where the gem suggests what is actually typed by the user: [<tt>1c52c88</tt>](https://github.com/yuki24/did_you_mean/commit/1c52c887c62b0921e799f94bcc4a846dc7cbc057)
24
+ - Fixed features that didn't work on JRuby 9.1.0.0: [<tt>dc48dde</tt>](https://github.com/yuki24/did_you_mean/commit/dc48dde1b2a8f05aab1fcf897e1cb3075a206f53), [<tt>4de23f8</tt>](https://github.com/yuki24/did_you_mean/commit/4de23f880502c80c5f321371d39c08bb0fa34040), [<tt>00e3059</tt>](https://github.com/yuki24/did_you_mean/commit/00e305971060d150fae4817b5e895d6478b37579). The local variable name correction is still disabled. Also see: [jruby/jruby#3480](https://github.com/jruby/jruby/issues/3480)
25
+
26
+
1
27
  ## [v1.0.0](https://github.com/yuki24/did_you_mean/tree/v1.0.0)
2
28
 
3
29
  _<sup>released on 2015-12-25 05:13:04 UTC</sup>_
@@ -9,7 +35,7 @@ _<sup>released on 2015-12-25 05:13:04 UTC</sup>_
9
35
 
10
36
  #### Bug Fixes
11
37
 
12
- - Fixed a bug where the Jaro-Winkler implementation returns the wrong distance when 2 identical strings are given
38
+ - Fixed a bug where the Jaro-Winkler implementation returns the wrong distance when 2 identical strings are given. fixes [#58](https://github.com/yuki24/did_you_mean/pull/58)
13
39
 
14
40
  #### Internal Changes
15
41
 
@@ -29,7 +55,7 @@ _<sup>released on 2015-12-25 04:56:13 UTC</sup>_
29
55
 
30
56
  #### Internal Changes
31
57
 
32
- - Enable the `frozen-string-literal` pragma rather than calling `.freeze` everywhere
58
+ - Use the `frozen-string-literal` pragma rather than calling `.freeze` everywhere
33
59
  - Use the `NameError#receiver` method in `DidYouMean:: ClassNameChecker` to know the namespace where the constant call is made
34
60
  - Refactored the `SpellCheckerTest`
35
61
 
data/Gemfile CHANGED
@@ -5,4 +5,4 @@ gemspec
5
5
 
6
6
  gem 'benchmark-ips'
7
7
  gem 'memory_profiler'
8
- gem 'jaro_winkler', '>= 1.4.0' if RUBY_VERSION < '2.4.0'
8
+ gem 'jaro_winkler', '>= 1.4.0'
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Installation
4
4
 
5
- Ruby 2.3 ships with this gem and it will automatically be `require`d when a Ruby process starts up. No special setup is required.
5
+ Ruby 2.3 and later ships with this gem and it will automatically be `require`d when a Ruby process starts up. No special setup is required.
6
6
 
7
7
  ## Examples
8
8
 
@@ -56,7 +56,7 @@ full_name.starts_with?("Y")
56
56
 
57
57
  Aside from the basic features above, the `did_you_mean` gem comes with experimental features. They can be enabled by calling `require 'did_you_mean/experimental'`.
58
58
 
59
- **Keep in mind that these experimental features should never be enabled in production as they would impact Ruby's performance and uses an unstable Ruby API.**
59
+ **Keep in mind that these experimental features should never be enabled in production as they would impact Ruby's performance and use some unstable Ruby APIs.**
60
60
 
61
61
  ### Correcting an Instance Variable When It's Incorrectly Typed
62
62
 
@@ -69,7 +69,17 @@ require 'did_you_mean/experimental'
69
69
  # Did you mean? @full_name
70
70
  ```
71
71
 
72
+ ### Correcting a Hash Key Name
73
+
74
+ ```ruby
75
+ hash = {foo: 1, bar: 2, baz: 3}
76
+ hash.fetch(:fooo)
77
+ # KeyError: key not found: :fooo
78
+ # Did you mean? :foo
79
+ ```
80
+
72
81
  ### Displaying a Warning When `initialize` is Incorrectly Typed
82
+
73
83
  ```ruby
74
84
  require 'did_you_mean/experimental'
75
85
 
data/Rakefile CHANGED
@@ -28,12 +28,7 @@ Rake::TestTask.new("test:experimental") do |task|
28
28
  task.ruby_opts << "-rdid_you_mean/experimental"
29
29
  end
30
30
 
31
- if RUBY_ENGINE != 'jruby'
32
- task default: %i(test test:verbose_formatter test:experimental)
33
- else
34
- task default: %i(test test:verbose_formatter)
35
- end
36
-
31
+ task default: %i(test test:verbose_formatter test:experimental)
37
32
 
38
33
  namespace :test do
39
34
  namespace :accuracy do
@@ -51,13 +46,13 @@ namespace :test do
51
46
  puts "\n"
52
47
  end
53
48
 
54
- sh 'bundle exec ruby evaluation/calculator.rb'
49
+ sh 'ruby evaluation/calculator.rb'
55
50
  end
56
51
  end
57
52
 
58
53
  namespace :benchmark do
59
54
  desc "Measure memory usage by the did_you_mean gem"
60
55
  task :memory do
61
- sh 'bundle exec ruby benchmark/memory_usage.rb'
56
+ sh 'ruby benchmark/memory_usage.rb'
62
57
  end
63
58
  end
@@ -1,4 +1,4 @@
1
- # -*- frozen-string-literal: true -*-
1
+ # frozen-string-literal: true
2
2
 
3
3
  require 'memory_profiler'
4
4
  require 'did_you_mean'
@@ -9,18 +9,17 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Yuki Nishijima"]
10
10
  spec.email = ["mail@yukinishijima.net"]
11
11
  spec.summary = '"Did you mean?" experience in Ruby'
12
- spec.description = '"did you mean?" experience in Ruby: the error message will tell you the right one when you misspelled something.'
12
+ spec.description = 'The gem that has been saving people from typos since 2014.'
13
13
  spec.homepage = "https://github.com/yuki24/did_you_mean"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
17
  spec.test_files = spec.files.grep(%r{^(test)/})
19
18
  spec.require_paths = ["lib"]
20
19
 
21
- spec.required_ruby_version = '>= 2.3.0'
20
+ spec.required_ruby_version = '>= 2.4.0dev'
22
21
 
23
- spec.add_development_dependency "bundler", "~> 1.10"
22
+ spec.add_development_dependency "bundler"
24
23
  spec.add_development_dependency "rake"
25
24
  spec.add_development_dependency "minitest"
26
25
  end
@@ -1,4 +1,4 @@
1
- # -*- frozen-string-literal: true -*-
1
+ # frozen-string-literal: true
2
2
 
3
3
  require 'benchmark'
4
4
  require 'did_you_mean'
@@ -36,7 +36,8 @@ report "loading program" do
36
36
  ::JaroWinkler.distance(str1, str2)
37
37
  end if RUBY_ENGINE != 'jruby'
38
38
  end
39
- rescue LoadError, NameError
39
+ rescue LoadError, NameError => e
40
+ puts "couldn't load the jaro_winkler gem: #{e.message}\n\n"
40
41
  end
41
42
  end
42
43
 
@@ -47,7 +48,7 @@ report "loading dictionary" do
47
48
  DICTIONARY = Set.new(yaml)
48
49
  end
49
50
 
50
- report "loading corrent/incorrect words" do
51
+ report "loading correct/incorrect words" do
51
52
  SPELL_CHECKER = DidYouMean::SpellChecker.new(dictionary: DICTIONARY)
52
53
  INCORRECT_WORDS = YAML.load(open("evaluation/incorrect_words.yaml").read)
53
54
  end
@@ -1,5 +1,5 @@
1
1
  # This data is based on Birkbeck Spelling Error Corpus: http://ota.ox.ac.uk/headers/0643.xml
2
- # More specifically, this is a yaml version of the data in FAWTHROP1DAT.643 and FAWTHROP1DAT.643.
2
+ # More specifically, this is a yaml version of the data in FAWTHROP1DAT.643 and FAWTHROP2DAT.643.
3
3
  ---
4
4
  abattoir: abbatoir
5
5
  abhorrence: abhorence
@@ -10,21 +10,18 @@ module DidYouMean
10
10
  msg = super.dup
11
11
  bt = caller(1, 6)
12
12
 
13
- if IGNORED_CALLERS.all? {|ignored| bt.grep(ignored).empty? } && (!cause.respond_to?(:corrections) || cause.corrections.empty?)
14
- msg << Formatter.new(corrections).to_s
15
- end
16
-
13
+ msg << Formatter.new(corrections).to_s if IGNORED_CALLERS.all? {|ignored| bt.grep(ignored).empty? }
17
14
  msg
18
15
  rescue
19
16
  super
20
17
  end
21
18
 
22
19
  def corrections
23
- @corrections ||= spell_checker.corrections
20
+ spell_checker.corrections
24
21
  end
25
22
 
26
23
  def spell_checker
27
- SPELL_CHECKERS[self.class.to_s].new(self)
24
+ @spell_checker ||= SPELL_CHECKERS[self.class.to_s].new(self)
28
25
  end
29
26
  end
30
27
  end
@@ -1,4 +1,4 @@
1
- # -*- frozen-string-literal: true -*-
1
+ # frozen-string-literal: true
2
2
 
3
3
  module DidYouMean
4
4
  module Experimental
@@ -1,4 +1,4 @@
1
- # -*- frozen-string-literal: true -*-
1
+ # frozen-string-literal: true
2
2
 
3
3
  module DidYouMean
4
4
  class Formatter
@@ -1,6 +1,8 @@
1
1
  module DidYouMean
2
2
  module Levenshtein # :nodoc:
3
3
  # This code is based directly on the Text gem implementation
4
+ # Copyright (c) 2006-2013 Paul Battley, Michael Neumann, Tim Fletcher.
5
+ #
4
6
  # Returns a value representing the "cost" of transforming str1 into str2
5
7
  def distance(str1, str2)
6
8
  n = str1.length
@@ -1,4 +1,4 @@
1
- # -*- frozen-string-literal: true -*-
1
+ # frozen-string-literal: true
2
2
 
3
3
  require "did_you_mean/levenshtein"
4
4
  require "did_you_mean/jaro_winkler"
@@ -13,24 +13,22 @@ module DidYouMean
13
13
  input = normalize(input)
14
14
  threshold = input.length > 3 ? 0.834 : 0.77
15
15
 
16
- seed = @dictionary.select {|candidate| JaroWinkler.distance(normalize(candidate), input) >= threshold }
17
- seed.reject! {|candidate| input == candidate.to_s }
18
- seed.sort_by! {|candidate| JaroWinkler.distance(candidate.to_s, input) }
19
- seed.reverse!
16
+ words = @dictionary.select {|word| JaroWinkler.distance(normalize(word), input) >= threshold }
17
+ words.reject! {|word| input == word.to_s }
18
+ words.sort_by! {|word| JaroWinkler.distance(word.to_s, input) }
19
+ words.reverse!
20
20
 
21
21
  # Correct mistypes
22
22
  threshold = (input.length * 0.25).ceil
23
- has_mistype = seed.rindex {|c| Levenshtein.distance(normalize(c), input) <= threshold }
23
+ corrections = words.select {|c| Levenshtein.distance(normalize(c), input) <= threshold }
24
24
 
25
- corrections = if has_mistype
26
- seed.take(has_mistype + 1)
27
- else
28
- # Correct misspells
29
- seed.select do |candidate|
30
- candidate = normalize(candidate)
31
- length = input.length < candidate.length ? input.length : candidate.length
25
+ # Correct misspells
26
+ if corrections.empty?
27
+ corrections = words.select do |word|
28
+ word = normalize(word)
29
+ length = input.length < word.length ? input.length : word.length
32
30
 
33
- Levenshtein.distance(candidate, input) < length
31
+ Levenshtein.distance(word, input) < length
34
32
  end.first(1)
35
33
  end
36
34
 
@@ -2,19 +2,22 @@ module DidYouMean
2
2
  class MethodNameChecker
3
3
  attr_reader :method_name, :receiver
4
4
 
5
+ NAMES_TO_EXCLUDE = { NilClass => nil.methods }
6
+ NAMES_TO_EXCLUDE.default = []
7
+
5
8
  def initialize(exception)
6
- @method_name = exception.name
7
- @receiver = exception.receiver
8
- @has_args = !exception.args&.empty?
9
+ @method_name = exception.name
10
+ @receiver = exception.receiver
11
+ @private_call = exception.respond_to?(:private_call?) ? exception.private_call? : false
9
12
  end
10
13
 
11
14
  def corrections
12
- @corrections ||= SpellChecker.new(dictionary: method_names).correct(method_name)
15
+ @corrections ||= SpellChecker.new(dictionary: method_names).correct(method_name) - NAMES_TO_EXCLUDE[@receiver.class]
13
16
  end
14
17
 
15
18
  def method_names
16
19
  method_names = receiver.methods + receiver.singleton_methods
17
- method_names += receiver.private_methods if @has_args
20
+ method_names += receiver.private_methods if @private_call
18
21
  method_names.uniq!
19
22
  method_names
20
23
  end
@@ -11,7 +11,10 @@ module DidYouMean
11
11
  case exception.original_message
12
12
  when /uninitialized constant/
13
13
  ClassNameChecker
14
- when /undefined local variable or method/, /undefined method/, /uninitialized class variable/
14
+ when /undefined local variable or method/,
15
+ /undefined method/,
16
+ /uninitialized class variable/,
17
+ /no member '.*' in struct/
15
18
  VariableNameChecker
16
19
  else
17
20
  NullChecker
@@ -1,4 +1,4 @@
1
- # -*- frozen-string-literal: true -*-
1
+ # frozen-string-literal: true
2
2
  require 'delegate'
3
3
 
4
4
  module DidYouMean
@@ -6,14 +6,11 @@ module DidYouMean
6
6
  attr_reader :class_name
7
7
 
8
8
  def initialize(exception)
9
- @class_name, @receiver, @original_message = exception.name, exception.receiver, exception.original_message
9
+ @class_name, @receiver = exception.name, exception.receiver
10
10
  end
11
11
 
12
12
  def corrections
13
- @corrections ||= SpellChecker.new(dictionary: class_names)
14
- .correct(class_name)
15
- .map(&:full_name)
16
- .reject {|qualified_name| @original_message.include?(qualified_name) }
13
+ @corrections ||= SpellChecker.new(dictionary: class_names).correct(class_name).map(&:full_name)
17
14
  end
18
15
 
19
16
  def class_names
@@ -1,9 +1,12 @@
1
- # -*- frozen-string-literal: true -*-
1
+ # frozen-string-literal: true
2
2
 
3
3
  module DidYouMean
4
4
  class VariableNameChecker
5
5
  attr_reader :name, :method_names, :lvar_names, :ivar_names, :cvar_names
6
6
 
7
+ NAMES_TO_EXCLUDE = { 'foo' => [:fork] }
8
+ NAMES_TO_EXCLUDE.default = []
9
+
7
10
  def initialize(exception)
8
11
  @name = exception.name.to_s.tr("@", "")
9
12
  @lvar_names = exception.respond_to?(:local_variables) ? exception.local_variables : []
@@ -18,7 +21,7 @@ module DidYouMean
18
21
  def corrections
19
22
  @corrections ||= SpellChecker
20
23
  .new(dictionary: (lvar_names + method_names + ivar_names + cvar_names))
21
- .correct(name)
24
+ .correct(name) - NAMES_TO_EXCLUDE[@name]
22
25
  end
23
26
  end
24
27
  end
@@ -1,4 +1,4 @@
1
- # -*- frozen-string-literal: true -*-
1
+ # frozen-string-literal: true
2
2
  require 'did_you_mean/formatter'
3
3
 
4
4
  module DidYouMean
@@ -1,3 +1,3 @@
1
1
  module DidYouMean
2
- VERSION = "1.0.4"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -20,7 +20,7 @@ class NameErrorExtensionTest < Minitest::Test
20
20
 
21
21
  def test_message
22
22
  message = <<~MESSAGE.chomp
23
- undefined local variable or method `doesnt_exist' for #{to_s}
23
+ undefined local variable or method `doesnt_exist' for #{method(:to_s).super_method.call}
24
24
  Did you mean? does_exist
25
25
  MESSAGE
26
26
 
@@ -36,18 +36,6 @@ class NameErrorExtensionTest < Minitest::Test
36
36
  error.to_s
37
37
  assert_equal 1, error.to_s.scan("Did you mean?").count
38
38
  end
39
-
40
- def test_correctable_error_objects_are_dumpable
41
- error = begin
42
- File.open('/tmp/file').sizee
43
- rescue NoMethodError => e
44
- e
45
- end
46
-
47
- error.to_s
48
-
49
- assert_equal "undefined method `sizee' for #<File:/tmp/file>", Marshal.load(Marshal.dump(error)).original_message
50
- end
51
39
  end
52
40
 
53
41
  class IgnoreCallersTest < Minitest::Test
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require 'test_helper'
2
3
 
3
4
  class JaroWinklerTest < Minitest::Test
@@ -13,7 +13,6 @@ class SpellCheckerTest < Minitest::Test
13
13
 
14
14
  assert_spell %w(gsub! gsub), input: 'gsuv!', dictionary: %w(sub gsub gsub!)
15
15
  assert_spell %w(sub! sub gsub!), input: 'ssub!', dictionary: %w(sub sub! gsub gsub!)
16
- assert_spell %i(read rand), input: 'raed', dictionary: File.methods + File.private_methods
17
16
 
18
17
  group_methods = %w(groups group_url groups_url group_path)
19
18
  assert_spell 'groups', input: 'group', dictionary: group_methods
@@ -62,16 +62,4 @@ class ClassNameTest < Minitest::Test
62
62
  error = assert_raises(NameError) { ::Book::Page.new.tableof_contents }
63
63
  assert_correction "Book::TableOfContents", error.corrections
64
64
  end
65
-
66
- def test_does_not_suggest_user_input
67
- error = assert_raises(NameError) { ::Book::Cover }
68
-
69
- # This is a weird require, but in a multi-threaded condition, a constant may
70
- # be loaded between when a NameError occurred and when the spell checker
71
- # attemps to find a possible suggestion. The manual require here simulates
72
- # a race condition a single test.
73
- require_relative '../fixtures/book'
74
-
75
- assert_empty error.corrections
76
- end
77
65
  end
@@ -9,12 +9,6 @@ class MethodNameTest < Minitest::Test
9
9
  raiae NoMethodError
10
10
  end
11
11
 
12
- def raise_no_method_error
13
- self.firstname
14
- rescue NoMethodError => e
15
- raise e, e.message, e.backtrace
16
- end
17
-
18
12
  protected
19
13
  def the_protected_method; end
20
14
 
@@ -78,27 +72,18 @@ class MethodNameTest < Minitest::Test
78
72
  assert_match "Did you mean? raise", error.to_s
79
73
  end
80
74
 
81
- def test_does_not_append_suggestions_twice
82
- error = assert_raises NoMethodError do
83
- begin
84
- @user.firstname
85
- rescue NoMethodError => e
86
- raise e, e.message, e.backtrace
87
- end
88
- end
89
-
90
- assert_equal 1, error.to_s.scan(/Did you mean/).count
75
+ def test_exclude_methods_on_nil
76
+ error = assert_raises(NoMethodError){ nil.map }
77
+ assert_empty error.corrections
91
78
  end
92
79
 
93
- def test_does_not_append_suggestions_three_times
94
- error = assert_raises NoMethodError do
95
- begin
96
- @user.raise_no_method_error
97
- rescue NoMethodError => e
98
- raise e, e.message, e.backtrace
99
- end
80
+ def test_does_not_exclude_custom_methods_on_nil
81
+ def nil.empty?
100
82
  end
101
83
 
102
- assert_equal 1, error.to_s.scan(/Did you mean/).count
84
+ error = assert_raises(NoMethodError){ nil.empty }
85
+ assert_correction :empty?, error.corrections
86
+ ensure
87
+ NilClass.class_eval { undef empty? }
103
88
  end
104
89
  end
@@ -53,12 +53,8 @@ class VariableNameTest < Minitest::Test
53
53
  person = person = nil
54
54
  error = (eprson rescue $!) # Do not use @assert_raises here as it changes a scope.
55
55
 
56
- if RUBY_ENGINE != 'jruby'
57
- assert_correction :person, error.corrections
58
- assert_match "Did you mean? person", error.to_s
59
- else
60
- assert_empty error.corrections
61
- end
56
+ assert_correction :person, error.corrections
57
+ assert_match "Did you mean? person", error.to_s
62
58
  end
63
59
 
64
60
  def test_corrections_include_instance_variable_name
@@ -85,4 +81,17 @@ class VariableNameTest < Minitest::Test
85
81
  assert_correction :@@does_exist, error.corrections
86
82
  assert_match "Did you mean? @@does_exist", error.to_s
87
83
  end
84
+
85
+ def test_struct_name_error
86
+ value = Struct.new(:does_exist).new
87
+ error = assert_raises(NameError){ value[:doesnt_exist] }
88
+
89
+ assert_correction [:does_exist, :does_exist=], error.corrections
90
+ assert_match "Did you mean? does_exist", error.to_s
91
+ end
92
+
93
+ def test_exclude_typical_incorrect_suggestions
94
+ error = assert_raises(NameError){ foo }
95
+ assert_empty error.corrections
96
+ end
88
97
  end
@@ -1,10 +1,12 @@
1
1
  require 'minitest/autorun'
2
- require 'minitest/unit'
2
+ require 'minitest/pride'
3
3
  require 'did_you_mean'
4
4
 
5
+ puts "DidYouMean version: #{DidYouMean::VERSION}"
6
+
5
7
  module DidYouMean::TestHelper
6
8
  def assert_correction(expected, array)
7
- assert_equal [expected], array, "Expected #{array.inspect} to only include #{expected.inspect}"
9
+ assert_equal Array(expected), array, "Expected #{array.inspect} to only include #{expected.inspect}"
8
10
  end
9
11
  end
10
12
 
@@ -2,14 +2,15 @@ require 'test_helper'
2
2
 
3
3
  class VerboseFormatterTest < Minitest::Test
4
4
  def setup
5
- @error = assert_raises(NoMethodError){ self.inspectt }
5
+ does_exist = does_exist = nil
6
+ @error = assert_raises(NameError){ doesnt_exist }
6
7
  end
7
8
 
8
9
  def test_message
9
10
  assert_equal <<~MESSAGE.chomp, @error.message
10
- undefined method `inspectt' for #{to_s}
11
+ undefined local variable or method `doesnt_exist' for #{method(:to_s).super_method.call}
11
12
 
12
- Did you mean? inspect
13
+ Did you mean? does_exist
13
14
 
14
15
  MESSAGE
15
16
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: did_you_mean
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuki Nishijima
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-09 00:00:00.000000000 Z
11
+ date: 2016-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.10'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.10'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,8 +52,7 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- description: '"did you mean?" experience in Ruby: the error message will tell you
56
- the right one when you misspelled something.'
55
+ description: The gem that has been saving people from typos since 2014.
57
56
  email:
58
57
  - mail@yukinishijima.net
59
58
  executables: []
@@ -61,6 +60,7 @@ extensions: []
61
60
  extra_rdoc_files: []
62
61
  files:
63
62
  - ".gitignore"
63
+ - ".ruby-version"
64
64
  - ".travis.yml"
65
65
  - CHANGELOG.md
66
66
  - Gemfile
@@ -84,7 +84,6 @@ files:
84
84
  - lib/did_you_mean/experimental/initializer_name_correction.rb
85
85
  - lib/did_you_mean/experimental/ivar_name_correction.rb
86
86
  - lib/did_you_mean/experimental/key_error_name_correction.rb
87
- - lib/did_you_mean/extra_features.rb
88
87
  - lib/did_you_mean/formatter.rb
89
88
  - lib/did_you_mean/jaro_winkler.rb
90
89
  - lib/did_you_mean/levenshtein.rb
@@ -98,11 +97,9 @@ files:
98
97
  - lib/did_you_mean/version.rb
99
98
  - test/core_ext/name_error_extension_test.rb
100
99
  - test/edit_distance/jaro_winkler_test.rb
101
- - test/experimental/deprecated_features_test.rb
102
100
  - test/experimental/initializer_name_correction_test.rb
103
101
  - test/experimental/key_error_test.rb
104
102
  - test/experimental/method_name_checker_test.rb
105
- - test/fixtures/book.rb
106
103
  - test/spell_checker_test.rb
107
104
  - test/spell_checking/class_name_test.rb
108
105
  - test/spell_checking/method_name_test.rb
@@ -110,7 +107,6 @@ files:
110
107
  - test/spell_checking/variable_name_test.rb
111
108
  - test/test_helper.rb
112
109
  - test/verbose_formatter_test.rb
113
- - tmp/.keep
114
110
  homepage: https://github.com/yuki24/did_you_mean
115
111
  licenses:
116
112
  - MIT
@@ -123,7 +119,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
123
119
  requirements:
124
120
  - - ">="
125
121
  - !ruby/object:Gem::Version
126
- version: 2.3.0
122
+ version: 2.4.0dev
127
123
  required_rubygems_version: !ruby/object:Gem::Requirement
128
124
  requirements:
129
125
  - - ">="
@@ -131,18 +127,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
127
  version: '0'
132
128
  requirements: []
133
129
  rubyforge_project:
134
- rubygems_version: 2.5.2.3
130
+ rubygems_version: 2.6.8
135
131
  signing_key:
136
132
  specification_version: 4
137
133
  summary: '"Did you mean?" experience in Ruby'
138
134
  test_files:
139
135
  - test/core_ext/name_error_extension_test.rb
140
136
  - test/edit_distance/jaro_winkler_test.rb
141
- - test/experimental/deprecated_features_test.rb
142
137
  - test/experimental/initializer_name_correction_test.rb
143
138
  - test/experimental/key_error_test.rb
144
139
  - test/experimental/method_name_checker_test.rb
145
- - test/fixtures/book.rb
146
140
  - test/spell_checker_test.rb
147
141
  - test/spell_checking/class_name_test.rb
148
142
  - test/spell_checking/method_name_test.rb
@@ -1,3 +0,0 @@
1
- warn "The file 'did_you_mean/extra_features.rb' has been moved to 'did_you_mean/experimental.rb'. Please `require 'did_you_mean/experimental'` instead."
2
-
3
- require 'did_you_mean/experimental'
@@ -1,13 +0,0 @@
1
- require 'test_helper'
2
-
3
- class DeprecatedExtraFeaturesTest < Minitest::Test
4
- def test_message
5
- message = "The file 'did_you_mean/extra_features.rb' has been moved to " \
6
- "'did_you_mean/experimental.rb'. Please `require 'did_you_mean/experimental'` " \
7
- "instead.\n"
8
-
9
- assert_output nil, message do
10
- require 'did_you_mean/extra_features'
11
- end
12
- end
13
- end
@@ -1,4 +0,0 @@
1
- class Book
2
- class Cover
3
- end
4
- end