did_you_mean 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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