did_you_mean 1.5.0 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3befc8f677ec57e2975d04b2095fcecf7314ff207150aa994b197894dba883af
4
- data.tar.gz: dc5a44ad2f6058ef68913f4080a23141f39b23f3b30129fe753d5d88cca85cc0
3
+ metadata.gz: 5179422bf1ff107c7189cb5e75e44f1cd8d44c2e305cbd46f1c262011fe46add
4
+ data.tar.gz: ea8103ee404f2bed7e002efb615b9a1c26b8080284fac57929276b72fa5cb0c5
5
5
  SHA512:
6
- metadata.gz: 4d60d78614d4a6650b2be87599d3c3d867ab74f4cdf7f6083594229e3c51588af57a5c9574ca35ced229558f4280cd3677cbd7944cc5cef55e34a4f7ff7addf3
7
- data.tar.gz: df5f07a5893afee4e03af416230ee828c7c2c2dfb8e5e35b5c525bebdff03710645b4af192563dc546abd4c210f8f2e8ce15e90124503488b74db19bd700f71c
6
+ metadata.gz: 45ee6a7e79a463743a5529f38b503c78266458b07fe2e8a85d8f4e0ece2c65dbc40baf0aaa96c4c6592bca868c4a99f9d6001f4b5b9c033bf504aedb34ba5340
7
+ data.tar.gz: f259d9fef544f4071733007277c672c16f95bbe0e7d303bc6bf52fa0d7fa7108dcf615d6502e7950d2b48e4ce720034cc2d23096d52bee6f03e7206eab02569b
@@ -13,7 +13,7 @@ jobs:
13
13
  runs-on: ubuntu-latest
14
14
  strategy:
15
15
  matrix:
16
- ruby: [ '2.5.8', '2.6.6', '2.7.1', 'ruby-head', 'jruby-9.2.11.1', 'jruby-head' ]
16
+ ruby: [ '2.5', '2.6', '2.7', '3.0', 'ruby-head', 'jruby-9.2', 'jruby-head' ]
17
17
  steps:
18
18
  - uses: actions/checkout@v1
19
19
  - uses: ruby/setup-ruby@v1
data/CHANGELOG.md CHANGED
@@ -1,6 +1,41 @@
1
- ## v1.5.0
1
+ ## v1.6.1
2
2
 
3
- - Suggest require paths on LoadError ([#143](https://github.com/ruby/did_you_mean/pull/143))
3
+ _<sup>released at 2020-12-22 13:22:35 UTC</sup>_
4
+
5
+ #### Deprecations
6
+
7
+ - Deprecate custom formatters to reduce complexity for Ractor support.
8
+ - Deprecate access to the `DidYouMean::SPELL_CHECEKRS` constant for Ractor support.
9
+
10
+ #### Features
11
+
12
+ - The `did_you_mean` gem is now Ractor-compatible (`8faba54b`)
13
+ - Suggest keys on NoMatchingPatternKeyError (#159, @k-tsj)
14
+ - Make the same name check case-sensitive (#164, @pocke)
15
+
16
+ Before:
17
+ ```ruby
18
+ DidYouMean::SpellChecker.new(dictionary: ['Method', 'MEthod']).correct("MEthod")
19
+ # => ['Method', 'method']
20
+ ```
21
+
22
+ After:
23
+ ```ruby
24
+ DidYouMean::SpellChecker.new(dictionary: ['Method', 'MEthod']).correct("MEthod")
25
+ # => ['Method']
26
+ ```
27
+
28
+ ## v1.6.0 (yanked)
29
+
30
+ _This version has been yanked due to significant and unexpected breaking changes._
31
+
32
+ ## [v1.5.0](https://github.com/ruby/did_you_mean/tree/v1.5.0)
33
+
34
+ _<sup>released at 2020-12-22 05:47:21 UTC</sup>_
35
+
36
+ #### Features
37
+
38
+ - Suggest require paths on LoadError ([#143](https://github.com/ruby/did_you_mean/pull/143))
4
39
 
5
40
  ## [v1.4.0](https://github.com/ruby/did_you_mean/tree/v1.4.0)
6
41
 
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # did_you_mean [![Gem Version](https://badge.fury.io/rb/did_you_mean.svg)](https://rubygems.org/gems/did_you_mean) [![Build Status](https://travis-ci.org/ruby/did_you_mean.svg?branch=master)](https://travis-ci.org/ruby/did_you_mean)
1
+ # did_you_mean [![Gem Version](https://badge.fury.io/rb/did_you_mean.svg)](https://rubygems.org/gems/did_you_mean) [![Build status](https://github.com/ruby/did_you_mean/actions/workflows/ruby.yml/badge.svg)](https://github.com/ruby/did_you_mean/actions/workflows/ruby.yml)
2
2
 
3
3
  ## Installation
4
4
 
@@ -69,21 +69,13 @@ require 'net-http'
69
69
  # Did you mean? net/http
70
70
  ```
71
71
 
72
- ## Verbose Formatter
73
-
74
- This verbose formatter changes the error message format to take more lines/spaces so it'll be slightly easier to read the suggestions. This formatter can totally be used in any environment including production.
72
+ ### NoMatchingPatternKeyError
75
73
 
76
74
  ```ruby
77
- OBject
78
- # => NameError: uninitialized constant OBject
79
- # Did you mean? Object
80
-
81
- require 'did_you_mean/verbose'
82
- OBject
83
- # => NameError: uninitialized constant OBject
84
- #
85
- # Did you mean? Object
86
- #
75
+ hash = {foo: 1, bar: 2, baz: 3}
76
+ hash => {fooo:}
77
+ # => NoMatchingPatternKeyError: key not found: :fooo
78
+ # Did you mean? :foo
87
79
  ```
88
80
 
89
81
  ## Using the `DidYouMean::SpellChecker`
@@ -107,7 +99,7 @@ $ ruby --disable-did_you_mean -e "1.zeor?"
107
99
  -e:1:in `<main>': undefined method `zeor?' for 1:Integer (NameError)
108
100
  ```
109
101
 
110
- When you do not have direct access to the `ruby` command (e.g. `rails console`, `irb`), you could applyoptions using the
102
+ When you do not have direct access to the `ruby` command (e.g. `rails console`, `irb`), you could apply options using the
111
103
  `RUBYOPT` environment variable:
112
104
 
113
105
  ```bash
@@ -11,7 +11,7 @@ where
11
11
  * that are used to correct a misspelling
12
12
  * The dictionary must be tree structured with a single character separator
13
13
  * e.g 'spec/models/goals_spec_rb'.
14
- ####separator: A single charactor. Cannot be cannot be alphabetical, '@' or '.'.
14
+ ####separator: A single character. Cannot be cannot be alphabetical, '@' or '.'.
15
15
  ####augment: When set to true, the checker will used the standard ```SpellChecker``` to find possible suggestions.
16
16
  ## Methods
17
17
  ```
@@ -1,14 +1,21 @@
1
1
  module DidYouMean
2
2
  module Correctable
3
+ SKIP_TO_S_FOR_SUPER_LOOKUP = true
4
+ private_constant :SKIP_TO_S_FOR_SUPER_LOOKUP
5
+
3
6
  def original_message
4
- method(:to_s).super_method.call
7
+ meth = method(:to_s)
8
+ while meth.owner.const_defined?(:SKIP_TO_S_FOR_SUPER_LOOKUP)
9
+ meth = meth.super_method
10
+ end
11
+ meth.call
5
12
  end
6
13
 
7
14
  def to_s
8
15
  msg = super.dup
9
16
  suggestion = DidYouMean.formatter.message_for(corrections)
10
17
 
11
- msg << suggestion if !msg.end_with?(suggestion)
18
+ msg << suggestion if !msg.include?(suggestion)
12
19
  msg
13
20
  rescue
14
21
  super
@@ -19,7 +26,7 @@ module DidYouMean
19
26
  end
20
27
 
21
28
  def spell_checker
22
- SPELL_CHECKERS[self.class.to_s].new(self)
29
+ DidYouMean.spell_checkers[self.class.to_s].new(self)
23
30
  end
24
31
  end
25
32
  end
@@ -0,0 +1,44 @@
1
+ # frozen-string-literal: true
2
+
3
+ module DidYouMean
4
+ # The +DidYouMean::Formatter+ is the basic, default formatter for the
5
+ # gem. The formatter responds to the +message_for+ method and it returns a
6
+ # human readable string.
7
+ class Formatter
8
+
9
+ # Returns a human readable string that contains +corrections+. This
10
+ # formatter is designed to be less verbose to not take too much screen
11
+ # space while being helpful enough to the user.
12
+ #
13
+ # @example
14
+ #
15
+ # formatter = DidYouMean::Formatter.new
16
+ #
17
+ # # displays suggestions in two lines with the leading empty line
18
+ # puts formatter.message_for(["methods", "method"])
19
+ #
20
+ # Did you mean? methods
21
+ # method
22
+ # # => nil
23
+ #
24
+ # # displays an empty line
25
+ # puts formatter.message_for([])
26
+ #
27
+ # # => nil
28
+ #
29
+ def self.message_for(corrections)
30
+ corrections.empty? ? "" : "\nDid you mean? #{corrections.join("\n ")}"
31
+ end
32
+
33
+ def message_for(corrections)
34
+ warn "The instance method #message_for has been deprecated. Please use the class method " \
35
+ "DidYouMean::Formatter.message_for(...) instead."
36
+
37
+ self.class.message_for(corrections)
38
+ end
39
+ end
40
+
41
+ PlainFormatter = Formatter
42
+
43
+ deprecate_constant :PlainFormatter
44
+ end
@@ -1,33 +1,4 @@
1
- # frozen-string-literal: true
1
+ require_relative '../formatter'
2
2
 
3
- module DidYouMean
4
- # The +DidYouMean::PlainFormatter+ is the basic, default formatter for the
5
- # gem. The formatter responds to the +message_for+ method and it returns a
6
- # human readable string.
7
- class PlainFormatter
8
-
9
- # Returns a human readable string that contains +corrections+. This
10
- # formatter is designed to be less verbose to not take too much screen
11
- # space while being helpful enough to the user.
12
- #
13
- # @example
14
- #
15
- # formatter = DidYouMean::PlainFormatter.new
16
- #
17
- # # displays suggestions in two lines with the leading empty line
18
- # puts formatter.message_for(["methods", "method"])
19
- #
20
- # Did you mean? methods
21
- # method
22
- # # => nil
23
- #
24
- # # displays an empty line
25
- # puts formatter.message_for([])
26
- #
27
- # # => nil
28
- #
29
- def message_for(corrections)
30
- corrections.empty? ? "" : "\nDid you mean? #{corrections.join("\n ")}"
31
- end
32
- end
33
- end
3
+ warn "`require 'did_you_mean/formatters/plain_formatter'` is deprecated. Please `require 'did_you_mean/formatter'` " \
4
+ "instead."
@@ -1,49 +1,9 @@
1
- # frozen-string-literal: true
2
-
3
- module DidYouMean
4
- # The +DidYouMean::VerboseFormatter+ uses extra empty lines to make the
5
- # suggestion stand out more in the error message.
6
- #
7
- # In order to activate the verbose formatter,
8
- #
9
- # @example
10
- #
11
- # OBject
12
- # # => NameError: uninitialized constant OBject
13
- # # Did you mean? Object
14
- #
15
- # require 'did_you_mean/verbose'
16
- #
17
- # OBject
18
- # # => NameError: uninitialized constant OBject
19
- # #
20
- # # Did you mean? Object
21
- # #
22
- #
23
- class VerboseFormatter
1
+ warn "`require 'did_you_mean/formatters/verbose_formatter'` is deprecated and falls back to the default formatter. "
24
2
 
25
- # Returns a human readable string that contains +corrections+. This
26
- # formatter is designed to be less verbose to not take too much screen
27
- # space while being helpful enough to the user.
28
- #
29
- # @example
30
- #
31
- # formatter = DidYouMean::PlainFormatter.new
32
- #
33
- # puts formatter.message_for(["methods", "method"])
34
- #
35
- #
36
- # Did you mean? methods
37
- # method
38
- #
39
- # # => nil
40
- #
41
- def message_for(corrections)
42
- return "" if corrections.empty?
3
+ require_relative '../formatter'
43
4
 
44
- output = "\n\n Did you mean? ".dup
45
- output << corrections.join("\n ")
46
- output << "\n "
47
- end
48
- end
5
+ # frozen-string-literal: true
6
+ module DidYouMean
7
+ # For compatibility:
8
+ VerboseFormatter = Formatter
49
9
  end
@@ -10,25 +10,25 @@ module DidYouMean
10
10
  end
11
11
 
12
12
  def correct(input)
13
- input = normalize(input)
14
- threshold = input.length > 3 ? 0.834 : 0.77
13
+ normalized_input = normalize(input)
14
+ threshold = normalized_input.length > 3 ? 0.834 : 0.77
15
15
 
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) }
16
+ words = @dictionary.select { |word| JaroWinkler.distance(normalize(word), normalized_input) >= threshold }
17
+ words.reject! { |word| input.to_s == word.to_s }
18
+ words.sort_by! { |word| JaroWinkler.distance(word.to_s, normalized_input) }
19
19
  words.reverse!
20
20
 
21
21
  # Correct mistypes
22
- threshold = (input.length * 0.25).ceil
23
- corrections = words.select { |c| Levenshtein.distance(normalize(c), input) <= threshold }
22
+ threshold = (normalized_input.length * 0.25).ceil
23
+ corrections = words.select { |c| Levenshtein.distance(normalize(c), normalized_input) <= threshold }
24
24
 
25
25
  # Correct misspells
26
26
  if corrections.empty?
27
27
  corrections = words.select do |word|
28
28
  word = normalize(word)
29
- length = input.length < word.length ? input.length : word.length
29
+ length = normalized_input.length < word.length ? normalized_input.length : word.length
30
30
 
31
- Levenshtein.distance(word, input) < length
31
+ Levenshtein.distance(word, normalized_input) < length
32
32
  end.first(1)
33
33
  end
34
34
 
@@ -6,6 +6,7 @@ module DidYouMean
6
6
 
7
7
  NAMES_TO_EXCLUDE = { NilClass => nil.methods }
8
8
  NAMES_TO_EXCLUDE.default = []
9
+ Ractor.make_shareable(NAMES_TO_EXCLUDE) if defined?(Ractor)
9
10
 
10
11
  # +MethodNameChecker::RB_RESERVED_WORDS+ is the list of reserved words in
11
12
  # Ruby that take an argument. Unlike
@@ -36,6 +37,8 @@ module DidYouMean
36
37
  yield
37
38
  )
38
39
 
40
+ Ractor.make_shareable(RB_RESERVED_WORDS) if defined?(Ractor)
41
+
39
42
  def initialize(exception)
40
43
  @method_name = exception.name
41
44
  @receiver = exception.receiver
@@ -8,6 +8,7 @@ module DidYouMean
8
8
 
9
9
  NAMES_TO_EXCLUDE = { 'foo' => [:fork, :for] }
10
10
  NAMES_TO_EXCLUDE.default = []
11
+ Ractor.make_shareable(NAMES_TO_EXCLUDE) if defined?(Ractor)
11
12
 
12
13
  # +VariableNameChecker::RB_RESERVED_WORDS+ is the list of all reserved
13
14
  # words in Ruby. They could be declared like methods are, and a typo would
@@ -62,6 +63,8 @@ module DidYouMean
62
63
  __ENCODING__
63
64
  )
64
65
 
66
+ Ractor.make_shareable(RB_RESERVED_WORDS) if defined?(Ractor)
67
+
65
68
  def initialize(exception)
66
69
  @name = exception.name.to_s.tr("@", "")
67
70
  @lvar_names = exception.respond_to?(:local_variables) ? exception.local_variables : []
@@ -0,0 +1,20 @@
1
+ require_relative "../spell_checker"
2
+
3
+ module DidYouMean
4
+ class PatternKeyNameChecker
5
+ def initialize(no_matching_pattern_key_error)
6
+ @key = no_matching_pattern_key_error.key
7
+ @keys = no_matching_pattern_key_error.matchee.keys
8
+ end
9
+
10
+ def corrections
11
+ @corrections ||= exact_matches.empty? ? SpellChecker.new(dictionary: @keys).correct(@key).map(&:inspect) : exact_matches
12
+ end
13
+
14
+ private
15
+
16
+ def exact_matches
17
+ @exact_matches ||= @keys.select { |word| @key == word.to_s }.map(&:inspect)
18
+ end
19
+ end
20
+ end
@@ -2,13 +2,17 @@
2
2
 
3
3
  require_relative "../spell_checker"
4
4
  require_relative "../tree_spell_checker"
5
+ require "rbconfig"
5
6
 
6
7
  module DidYouMean
7
8
  class RequirePathChecker
8
9
  attr_reader :path
9
10
 
10
11
  INITIAL_LOAD_PATH = $LOAD_PATH.dup.freeze
11
- ENV_SPECIFIC_EXT = ".#{RbConfig::CONFIG["DLEXT"]}"
12
+ Ractor.make_shareable(INITIAL_LOAD_PATH) if defined?(Ractor)
13
+
14
+ ENV_SPECIFIC_EXT = ".#{RbConfig::CONFIG["DLEXT"]}"
15
+ Ractor.make_shareable(ENV_SPECIFIC_EXT) if defined?(Ractor)
12
16
 
13
17
  private_constant :INITIAL_LOAD_PATH, :ENV_SPECIFIC_EXT
14
18
 
@@ -1,4 +1,2 @@
1
- require_relative '../did_you_mean'
2
- require_relative 'formatters/verbose_formatter'
3
-
4
- DidYouMean.formatter = DidYouMean::VerboseFormatter.new
1
+ warn "The verbose formatter has been removed and now `require 'did_you_mean/verbose'` has no effect. Please " \
2
+ "remove this call."
@@ -1,3 +1,3 @@
1
1
  module DidYouMean
2
- VERSION = "1.5.0"
2
+ VERSION = "1.6.1".freeze
3
3
  end
data/lib/did_you_mean.rb CHANGED
@@ -7,7 +7,8 @@ require_relative 'did_you_mean/spell_checkers/method_name_checker'
7
7
  require_relative 'did_you_mean/spell_checkers/key_error_checker'
8
8
  require_relative 'did_you_mean/spell_checkers/null_checker'
9
9
  require_relative 'did_you_mean/spell_checkers/require_path_checker'
10
- require_relative 'did_you_mean/formatters/plain_formatter'
10
+ require_relative 'did_you_mean/spell_checkers/pattern_key_name_checker'
11
+ require_relative 'did_you_mean/formatter'
11
12
  require_relative 'did_you_mean/tree_spell_checker'
12
13
 
13
14
  # The +DidYouMean+ gem adds functionality to suggest possible method/class
@@ -85,28 +86,70 @@ require_relative 'did_you_mean/tree_spell_checker'
85
86
  #
86
87
  module DidYouMean
87
88
  # Map of error types and spell checker objects.
88
- SPELL_CHECKERS = Hash.new(NullChecker)
89
+ @spell_checkers = Hash.new(NullChecker)
90
+
91
+ # Returns a sharable hash map of error types and spell checker objects.
92
+ def self.spell_checkers
93
+ @spell_checkers
94
+ end
89
95
 
90
96
  # Adds +DidYouMean+ functionality to an error using a given spell checker
91
97
  def self.correct_error(error_class, spell_checker)
92
- SPELL_CHECKERS[error_class.name] = spell_checker
93
- error_class.prepend(Correctable) unless error_class < Correctable
98
+ if defined?(Ractor)
99
+ new_mapping = { **@spell_checkers, error_class.to_s => spell_checker }
100
+ new_mapping.default = NullChecker
101
+
102
+ @spell_checkers = Ractor.make_shareable(new_mapping)
103
+ else
104
+ spell_checkers[error_class.to_s] = spell_checker
105
+ end
106
+
107
+ error_class.prepend(Correctable) if error_class.is_a?(Class) && !(error_class < Correctable)
94
108
  end
95
109
 
96
110
  correct_error NameError, NameErrorCheckers
97
111
  correct_error KeyError, KeyErrorChecker
98
112
  correct_error NoMethodError, MethodNameChecker
99
113
  correct_error LoadError, RequirePathChecker if RUBY_VERSION >= '2.8.0'
114
+ correct_error NoMatchingPatternKeyError, PatternKeyNameChecker if defined?(::NoMatchingPatternKeyError)
115
+
116
+ # TODO: Remove on 3.3:
117
+ class DeprecatedMapping # :nodoc:
118
+ def []=(key, value)
119
+ warn "Calling `DidYouMean::SPELL_CHECKERS[#{key.to_s}] = #{value.to_s}' has been deprecated. " \
120
+ "Please call `DidYouMean.correct_error(#{key.to_s}, #{value.to_s})' instead."
121
+
122
+ DidYouMean.correct_error(key, value)
123
+ end
124
+
125
+ def merge!(hash)
126
+ warn "Calling `DidYouMean::SPELL_CHECKERS.merge!(error_name => spell_checker)' has been deprecated. " \
127
+ "Please call `DidYouMean.correct_error(error_name, spell_checker)' instead."
128
+
129
+ hash.each do |error_class, spell_checker|
130
+ DidYouMean.correct_error(error_class, spell_checker)
131
+ end
132
+ end
133
+ end
134
+
135
+ # TODO: Remove on 3.3:
136
+ SPELL_CHECKERS = DeprecatedMapping.new
137
+ deprecate_constant :SPELL_CHECKERS
138
+ private_constant :DeprecatedMapping
100
139
 
101
140
  # Returns the currently set formatter. By default, it is set to +DidYouMean::Formatter+.
102
141
  def self.formatter
103
- @@formatter
142
+ if defined?(Ractor)
143
+ Ractor.current[:__did_you_mean_formatter__] || Formatter
144
+ else
145
+ Formatter
146
+ end
104
147
  end
105
148
 
106
149
  # Updates the primary formatter used to format the suggestions.
107
150
  def self.formatter=(formatter)
108
- @@formatter = formatter
151
+ if defined?(Ractor)
152
+ Ractor.current[:__did_you_mean_formatter__] = formatter
153
+ end
109
154
  end
110
-
111
- self.formatter = PlainFormatter.new
112
155
  end
@@ -1,7 +1,7 @@
1
1
  require_relative '../helper'
2
2
 
3
3
  class NameErrorExtensionTest < Test::Unit::TestCase
4
- SPELL_CHECKERS = DidYouMean::SPELL_CHECKERS
4
+ SPELL_CHECKERS = DidYouMean.spell_checkers
5
5
 
6
6
  class TestSpellChecker
7
7
  def initialize(*); end
@@ -9,13 +9,14 @@ class NameErrorExtensionTest < Test::Unit::TestCase
9
9
  end
10
10
 
11
11
  def setup
12
- @org, SPELL_CHECKERS['NameError'] = SPELL_CHECKERS['NameError'], TestSpellChecker
12
+ @original_spell_checker = DidYouMean.spell_checkers['NameError']
13
+ DidYouMean.correct_error(NameError, TestSpellChecker)
13
14
 
14
15
  @error = assert_raise(NameError){ doesnt_exist }
15
16
  end
16
17
 
17
18
  def teardown
18
- SPELL_CHECKERS['NameError'] = @org
19
+ DidYouMean.correct_error(NameError, @original_spell_checker)
19
20
  end
20
21
 
21
22
  def test_message
data/test/helper.rb CHANGED
@@ -4,6 +4,10 @@ module DidYouMean
4
4
  module TestHelper
5
5
  class << self
6
6
  attr_reader :root
7
+
8
+ def ractor_compatible?
9
+ defined?(Ractor) && RUBY_VERSION >= "3.1.0"
10
+ end
7
11
  end
8
12
 
9
13
  if File.file?(File.expand_path('../lib/did_you_mean.rb', __dir__))
@@ -0,0 +1,20 @@
1
+ require_relative '../helper'
2
+
3
+ return if !defined?(::NoMatchingPatternKeyError)
4
+
5
+ class PatternKeyNameCheckTest < Test::Unit::TestCase
6
+ include DidYouMean::TestHelper
7
+
8
+ def test_corrects_hash_key_name_with_single_pattern_match
9
+ error = assert_raise(NoMatchingPatternKeyError) do
10
+ eval(<<~RUBY, binding, __FILE__, __LINE__)
11
+ hash = {foo: 1, bar: 2, baz: 3}
12
+ hash => {fooo:}
13
+ fooo = 1 # suppress "unused variable: fooo" warning
14
+ RUBY
15
+ end
16
+
17
+ assert_correction ":foo", error.corrections
18
+ assert_match "Did you mean? :foo", error.to_s
19
+ end
20
+ end
@@ -10,6 +10,6 @@ class UncorrectableNameCheckTest < Test::Unit::TestCase
10
10
  end
11
11
 
12
12
  def test_message
13
- assert_equal "Other name error", @error.message
13
+ assert_not_match(/Did you mean\?/, @error.message)
14
14
  end
15
15
  end
@@ -0,0 +1,102 @@
1
+ require_relative './helper'
2
+
3
+ return if not DidYouMean::TestHelper.ractor_compatible?
4
+
5
+ class RactorCompatibilityTest < Test::Unit::TestCase
6
+ include DidYouMean::TestHelper
7
+
8
+ class ::Book; end
9
+ class FirstNameError < NameError; end
10
+
11
+ def test_class_name_suggestion_works_in_ractor
12
+ error = Ractor.new {
13
+ begin
14
+ Boook
15
+ rescue NameError => e
16
+ e.corrections # It is important to call the #corrections method within Ractor.
17
+ e
18
+ end
19
+ }.take
20
+
21
+ assert_correction "Book", error.corrections
22
+ end
23
+
24
+ def test_key_name_suggestion_works_in_ractor
25
+ error = Ractor.new {
26
+ begin
27
+ hash = { "foo" => 1, bar: 2 }
28
+
29
+ hash.fetch(:bax)
30
+ rescue KeyError => e
31
+ e.corrections # It is important to call the #corrections method within Ractor.
32
+ e
33
+ end
34
+ }.take
35
+
36
+ assert_correction ":bar", error.corrections
37
+ assert_match "Did you mean? :bar", error.to_s
38
+ end
39
+
40
+ def test_method_name_suggestion_works_in_ractor
41
+ error = Ractor.new {
42
+ begin
43
+ self.to__s
44
+ rescue NoMethodError => e
45
+ e.corrections # It is important to call the #corrections method within Ractor.
46
+ e
47
+ end
48
+ }.take
49
+
50
+ assert_correction :to_s, error.corrections
51
+ assert_match "Did you mean? to_s", error.to_s
52
+ end
53
+
54
+ if defined?(::NoMatchingPatternKeyError)
55
+ def test_pattern_key_name_suggestion_works_in_ractor
56
+ error = Ractor.new {
57
+ begin
58
+ eval(<<~RUBY, binding, __FILE__, __LINE__)
59
+ hash = {foo: 1, bar: 2, baz: 3}
60
+ hash => {fooo:}
61
+ fooo = 1 # suppress "unused variable: fooo" warning
62
+ RUBY
63
+ rescue NoMatchingPatternKeyError => e
64
+ e.corrections # It is important to call the #corrections method within Ractor.
65
+ e
66
+ end
67
+ }.take
68
+
69
+ assert_correction ":foo", error.corrections
70
+ assert_match "Did you mean? :foo", error.to_s
71
+ end
72
+ end
73
+
74
+ def test_can_raise_other_name_error_in_ractor
75
+ error = Ractor.new {
76
+ begin
77
+ raise FirstNameError, "Other name error"
78
+ rescue FirstNameError => e
79
+ e.corrections # It is important to call the #corrections method within Ractor.
80
+ e
81
+ end
82
+ }.take
83
+
84
+ assert_not_match(/Did you mean\?/, error.message)
85
+ end
86
+
87
+ def test_variable_name_suggestion_works_in_ractor
88
+ error = Ractor.new {
89
+ in_ractor = in_ractor = 1
90
+
91
+ begin
92
+ in_reactor
93
+ rescue NameError => e
94
+ e.corrections # It is important to call the #corrections method within Ractor.
95
+ e
96
+ end
97
+ }.take
98
+
99
+ assert_correction :in_ractor, error.corrections
100
+ assert_match "Did you mean? in_ractor", error.to_s
101
+ end
102
+ end
@@ -10,6 +10,7 @@ class SpellCheckerTest < Test::Unit::TestCase
10
10
  assert_spell 'eval', input: 'veal', dictionary: ['email', 'fail', 'eval']
11
11
  assert_spell 'sub!', input: 'suv!', dictionary: ['sub', 'gsub', 'sub!']
12
12
  assert_spell 'sub', input: 'suv', dictionary: ['sub', 'gsub', 'sub!']
13
+ assert_spell 'Foo', input: 'FOo', dictionary: ['Foo', 'FOo']
13
14
 
14
15
  assert_spell %w(gsub! gsub), input: 'gsuv!', dictionary: %w(sub gsub gsub!)
15
16
  assert_spell %w(sub! sub gsub!), input: 'ssub!', dictionary: %w(sub sub! gsub gsub!)
@@ -8,7 +8,7 @@ class ChangeWordTest < Test::Unit::TestCase
8
8
  @len = @input.length
9
9
  end
10
10
 
11
- def test_deleletion
11
+ def test_deletion
12
12
  assert_match @cw.deletion(5), 'spec/ervices/anything_spec'
13
13
  assert_match @cw.deletion(@len - 1), 'spec/services/anything_spe'
14
14
  assert_match @cw.deletion(0), 'pec/services/anything_spec'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: did_you_mean
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuki Nishijima
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-22 00:00:00.000000000 Z
11
+ date: 2021-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -55,6 +55,7 @@ files:
55
55
  - lib/did_you_mean.rb
56
56
  - lib/did_you_mean/core_ext/name_error.rb
57
57
  - lib/did_you_mean/experimental.rb
58
+ - lib/did_you_mean/formatter.rb
58
59
  - lib/did_you_mean/formatters/plain_formatter.rb
59
60
  - lib/did_you_mean/formatters/verbose_formatter.rb
60
61
  - lib/did_you_mean/jaro_winkler.rb
@@ -66,6 +67,7 @@ files:
66
67
  - lib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb
67
68
  - lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb
68
69
  - lib/did_you_mean/spell_checkers/null_checker.rb
70
+ - lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb
69
71
  - lib/did_you_mean/spell_checkers/require_path_checker.rb
70
72
  - lib/did_you_mean/tree_spell_checker.rb
71
73
  - lib/did_you_mean/verbose.rb
@@ -79,12 +81,13 @@ files:
79
81
  - test/spell_checking/test_class_name_check.rb
80
82
  - test/spell_checking/test_key_name_check.rb
81
83
  - test/spell_checking/test_method_name_check.rb
84
+ - test/spell_checking/test_pattern_key_name_check.rb
82
85
  - test/spell_checking/test_require_path_check.rb
83
86
  - test/spell_checking/test_uncorrectable_name_check.rb
84
87
  - test/spell_checking/test_variable_name_check.rb
88
+ - test/test_ractor_compatibility.rb
85
89
  - test/test_spell_checker.rb
86
90
  - test/test_tree_spell_checker.rb
87
- - test/test_verbose_formatter.rb
88
91
  - test/tree_spell/change_word.rb
89
92
  - test/tree_spell/human_typo.rb
90
93
  - test/tree_spell/test_change_word.rb
@@ -94,7 +97,7 @@ homepage: https://github.com/ruby/did_you_mean
94
97
  licenses:
95
98
  - MIT
96
99
  metadata: {}
97
- post_install_message:
100
+ post_install_message:
98
101
  rdoc_options: []
99
102
  require_paths:
100
103
  - lib
@@ -109,8 +112,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
112
  - !ruby/object:Gem::Version
110
113
  version: '0'
111
114
  requirements: []
112
- rubygems_version: 3.1.3
113
- signing_key:
115
+ rubygems_version: 3.3.0.dev
116
+ signing_key:
114
117
  specification_version: 4
115
118
  summary: '"Did you mean?" experience in Ruby'
116
119
  test_files:
@@ -123,12 +126,13 @@ test_files:
123
126
  - test/spell_checking/test_class_name_check.rb
124
127
  - test/spell_checking/test_key_name_check.rb
125
128
  - test/spell_checking/test_method_name_check.rb
129
+ - test/spell_checking/test_pattern_key_name_check.rb
126
130
  - test/spell_checking/test_require_path_check.rb
127
131
  - test/spell_checking/test_uncorrectable_name_check.rb
128
132
  - test/spell_checking/test_variable_name_check.rb
133
+ - test/test_ractor_compatibility.rb
129
134
  - test/test_spell_checker.rb
130
135
  - test/test_tree_spell_checker.rb
131
- - test/test_verbose_formatter.rb
132
136
  - test/tree_spell/change_word.rb
133
137
  - test/tree_spell/human_typo.rb
134
138
  - test/tree_spell/test_change_word.rb
@@ -1,23 +0,0 @@
1
- require_relative './helper'
2
-
3
- class VerboseFormatterTest < Test::Unit::TestCase
4
- def setup
5
- require_relative File.join(DidYouMean::TestHelper.root, 'verbose')
6
-
7
- DidYouMean.formatter = DidYouMean::VerboseFormatter.new
8
- end
9
-
10
- def teardown
11
- DidYouMean.formatter = DidYouMean::PlainFormatter.new
12
- end
13
-
14
- def test_message
15
- @error = assert_raise(NoMethodError){ 1.zeor? }
16
-
17
- assert_match <<~MESSAGE.strip, @error.message
18
- undefined method `zeor?' for 1:Integer
19
-
20
- Did you mean? zero?
21
- MESSAGE
22
- end
23
- end