From 22249bbb371d794c0330c1a4512f2581c1040297 Mon Sep 17 00:00:00 2001 From: Yuki Nishijima Date: Fri, 22 Oct 2021 20:56:26 -0400 Subject: [PATCH] Revert "Sync did_you_mean" This reverts commit e22d293e06966733e71a7fd9725eee06c03d0177. --- lib/did_you_mean.rb | 13 ++--- lib/did_you_mean/formatter.rb | 35 ------------- .../formatters/plain_formatter.rb | 35 +++++++++++-- .../formatters/verbose_formatter.rb | 52 ++++++++++++++++--- lib/did_you_mean/spell_checker.rb | 18 +++---- .../pattern_key_name_checker.rb | 20 ------- lib/did_you_mean/verbose.rb | 6 ++- .../test_pattern_key_name_check.rb | 20 ------- test/did_you_mean/test_spell_checker.rb | 1 - test/did_you_mean/test_verbose_formatter.rb | 38 ++++++++++++++ 10 files changed, 134 insertions(+), 104 deletions(-) delete mode 100644 lib/did_you_mean/formatter.rb delete mode 100644 lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb delete mode 100644 test/did_you_mean/spell_checking/test_pattern_key_name_check.rb create mode 100644 test/did_you_mean/test_verbose_formatter.rb diff --git a/lib/did_you_mean.rb b/lib/did_you_mean.rb index b317bf5ab596f7..ab7e6b01a8e1dc 100644 --- a/lib/did_you_mean.rb +++ b/lib/did_you_mean.rb @@ -7,8 +7,7 @@ require_relative 'did_you_mean/spell_checkers/key_error_checker' require_relative 'did_you_mean/spell_checkers/null_checker' require_relative 'did_you_mean/spell_checkers/require_path_checker' -require_relative 'did_you_mean/spell_checkers/pattern_key_name_checker' -require_relative 'did_you_mean/formatter' +require_relative 'did_you_mean/formatters/plain_formatter' require_relative 'did_you_mean/tree_spell_checker' # The +DidYouMean+ gem adds functionality to suggest possible method/class @@ -98,18 +97,16 @@ def self.correct_error(error_class, spell_checker) correct_error KeyError, KeyErrorChecker correct_error NoMethodError, MethodNameChecker correct_error LoadError, RequirePathChecker if RUBY_VERSION >= '2.8.0' - correct_error NoMatchingPatternKeyError, PatternKeyNameChecker if defined?(::NoMatchingPatternKeyError) # Returns the currently set formatter. By default, it is set to +DidYouMean::Formatter+. def self.formatter - @formatter + @@formatter end # Updates the primary formatter used to format the suggestions. - def self.formatter=(*) - warn "The custom formatter feature has been deprecated and has no effect. Please remove the usages of the " \ - "`#formatter=` method." + def self.formatter=(formatter) + @@formatter = formatter end - @formatter = Formatter.new + self.formatter = PlainFormatter.new end diff --git a/lib/did_you_mean/formatter.rb b/lib/did_you_mean/formatter.rb deleted file mode 100644 index 01eb59100ace0b..00000000000000 --- a/lib/did_you_mean/formatter.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen-string-literal: true - -module DidYouMean - # The +DidYouMean::Formatter+ is the basic, default formatter for the - # gem. The formatter responds to the +message_for+ method and it returns a - # human readable string. - class Formatter - - # Returns a human readable string that contains +corrections+. This - # formatter is designed to be less verbose to not take too much screen - # space while being helpful enough to the user. - # - # @example - # - # formatter = DidYouMean::Formatter.new - # - # # displays suggestions in two lines with the leading empty line - # puts formatter.message_for(["methods", "method"]) - # - # Did you mean? methods - # method - # # => nil - # - # # displays an empty line - # puts formatter.message_for([]) - # - # # => nil - # - def message_for(corrections) - corrections.empty? ? "" : "\nDid you mean? #{corrections.join("\n ")}" - end - end - - PlainFormatter = Formatter -end diff --git a/lib/did_you_mean/formatters/plain_formatter.rb b/lib/did_you_mean/formatters/plain_formatter.rb index d669588e0f3d41..e2d995f5871383 100644 --- a/lib/did_you_mean/formatters/plain_formatter.rb +++ b/lib/did_you_mean/formatters/plain_formatter.rb @@ -1,4 +1,33 @@ -require_relative '../formatter' +# frozen-string-literal: true -warn "`require 'did_you_mean/formatters/plain_formatter'` is deprecated. Please `require 'did_you_mean/formatter'` " \ - "instead." +module DidYouMean + # The +DidYouMean::PlainFormatter+ is the basic, default formatter for the + # gem. The formatter responds to the +message_for+ method and it returns a + # human readable string. + class PlainFormatter + + # Returns a human readable string that contains +corrections+. This + # formatter is designed to be less verbose to not take too much screen + # space while being helpful enough to the user. + # + # @example + # + # formatter = DidYouMean::PlainFormatter.new + # + # # displays suggestions in two lines with the leading empty line + # puts formatter.message_for(["methods", "method"]) + # + # Did you mean? methods + # method + # # => nil + # + # # displays an empty line + # puts formatter.message_for([]) + # + # # => nil + # + def message_for(corrections) + corrections.empty? ? "" : "\nDid you mean? #{corrections.join("\n ")}" + end + end +end diff --git a/lib/did_you_mean/formatters/verbose_formatter.rb b/lib/did_you_mean/formatters/verbose_formatter.rb index 8ee98fa070efb5..b8fe214d57825c 100644 --- a/lib/did_you_mean/formatters/verbose_formatter.rb +++ b/lib/did_you_mean/formatters/verbose_formatter.rb @@ -1,9 +1,49 @@ -warn "`require 'did_you_mean/formatters/verbose_formatter'` is deprecated and falls back to the default formatter. " - -require_relative '../formatter' - # frozen-string-literal: true + module DidYouMean - # For compatibility: - VerboseFormatter = Formatter + # The +DidYouMean::VerboseFormatter+ uses extra empty lines to make the + # suggestion stand out more in the error message. + # + # In order to activate the verbose formatter, + # + # @example + # + # OBject + # # => NameError: uninitialized constant OBject + # # Did you mean? Object + # + # require 'did_you_mean/verbose' + # + # OBject + # # => NameError: uninitialized constant OBject + # # + # # Did you mean? Object + # # + # + class VerboseFormatter + + # Returns a human readable string that contains +corrections+. This + # formatter is designed to be less verbose to not take too much screen + # space while being helpful enough to the user. + # + # @example + # + # formatter = DidYouMean::PlainFormatter.new + # + # puts formatter.message_for(["methods", "method"]) + # + # + # Did you mean? methods + # method + # + # # => nil + # + def message_for(corrections) + return "" if corrections.empty? + + output = "\n\n Did you mean? ".dup + output << corrections.join("\n ") + output << "\n " + end + end end diff --git a/lib/did_you_mean/spell_checker.rb b/lib/did_you_mean/spell_checker.rb index 37da2fc7a6ec26..e5106abba2c178 100644 --- a/lib/did_you_mean/spell_checker.rb +++ b/lib/did_you_mean/spell_checker.rb @@ -10,25 +10,25 @@ def initialize(dictionary:) end def correct(input) - normalized_input = normalize(input) - threshold = normalized_input.length > 3 ? 0.834 : 0.77 + input = normalize(input) + threshold = input.length > 3 ? 0.834 : 0.77 - words = @dictionary.select { |word| JaroWinkler.distance(normalize(word), normalized_input) >= threshold } - words.reject! { |word| input.to_s == word.to_s } - words.sort_by! { |word| JaroWinkler.distance(word.to_s, normalized_input) } + words = @dictionary.select { |word| JaroWinkler.distance(normalize(word), input) >= threshold } + words.reject! { |word| input == word.to_s } + words.sort_by! { |word| JaroWinkler.distance(word.to_s, input) } words.reverse! # Correct mistypes - threshold = (normalized_input.length * 0.25).ceil - corrections = words.select { |c| Levenshtein.distance(normalize(c), normalized_input) <= threshold } + threshold = (input.length * 0.25).ceil + corrections = words.select { |c| Levenshtein.distance(normalize(c), input) <= threshold } # Correct misspells if corrections.empty? corrections = words.select do |word| word = normalize(word) - length = normalized_input.length < word.length ? normalized_input.length : word.length + length = input.length < word.length ? input.length : word.length - Levenshtein.distance(word, normalized_input) < length + Levenshtein.distance(word, input) < length end.first(1) end diff --git a/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb b/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb deleted file mode 100644 index ed263c8f937320..00000000000000 --- a/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb +++ /dev/null @@ -1,20 +0,0 @@ -require_relative "../spell_checker" - -module DidYouMean - class PatternKeyNameChecker - def initialize(no_matching_pattern_key_error) - @key = no_matching_pattern_key_error.key - @keys = no_matching_pattern_key_error.matchee.keys - end - - def corrections - @corrections ||= exact_matches.empty? ? SpellChecker.new(dictionary: @keys).correct(@key).map(&:inspect) : exact_matches - end - - private - - def exact_matches - @exact_matches ||= @keys.select { |word| @key == word.to_s }.map(&:inspect) - end - end -end diff --git a/lib/did_you_mean/verbose.rb b/lib/did_you_mean/verbose.rb index 1ff19aef809dd1..4e86f167ea7618 100644 --- a/lib/did_you_mean/verbose.rb +++ b/lib/did_you_mean/verbose.rb @@ -1,2 +1,4 @@ -warn "The verbose formatter has been removed and now `require 'did_you_mean/verbose'` has no effect. Please " \ - "remove this call." +require_relative '../did_you_mean' +require_relative 'formatters/verbose_formatter' + +DidYouMean.formatter = DidYouMean::VerboseFormatter.new diff --git a/test/did_you_mean/spell_checking/test_pattern_key_name_check.rb b/test/did_you_mean/spell_checking/test_pattern_key_name_check.rb deleted file mode 100644 index 2b0752a56a9d48..00000000000000 --- a/test/did_you_mean/spell_checking/test_pattern_key_name_check.rb +++ /dev/null @@ -1,20 +0,0 @@ -require_relative '../helper' - -return if !defined?(::NoMatchingPatternKeyError) - -class PatternKeyNameCheckTest < Test::Unit::TestCase - include DidYouMean::TestHelper - - def test_corrects_hash_key_name_with_single_pattern_match - error = assert_raise(NoMatchingPatternKeyError) do - eval(<<~RUBY, binding, __FILE__, __LINE__) - hash = {foo: 1, bar: 2, baz: 3} - hash => {fooo:} - fooo = 1 # suppress "unused variable: fooo" warning - RUBY - end - - assert_correction ":foo", error.corrections - assert_match "Did you mean? :foo", error.to_s - end -end diff --git a/test/did_you_mean/test_spell_checker.rb b/test/did_you_mean/test_spell_checker.rb index 8445380de3381a..98460b4d94f047 100644 --- a/test/did_you_mean/test_spell_checker.rb +++ b/test/did_you_mean/test_spell_checker.rb @@ -10,7 +10,6 @@ def test_spell_checker_corrects_mistypes assert_spell 'eval', input: 'veal', dictionary: ['email', 'fail', 'eval'] assert_spell 'sub!', input: 'suv!', dictionary: ['sub', 'gsub', 'sub!'] assert_spell 'sub', input: 'suv', dictionary: ['sub', 'gsub', 'sub!'] - assert_spell 'Foo', input: 'FOo', dictionary: ['Foo', 'FOo'] assert_spell %w(gsub! gsub), input: 'gsuv!', dictionary: %w(sub gsub gsub!) assert_spell %w(sub! sub gsub!), input: 'ssub!', dictionary: %w(sub sub! gsub gsub!) diff --git a/test/did_you_mean/test_verbose_formatter.rb b/test/did_you_mean/test_verbose_formatter.rb new file mode 100644 index 00000000000000..411f175180ff5a --- /dev/null +++ b/test/did_you_mean/test_verbose_formatter.rb @@ -0,0 +1,38 @@ +require_relative './helper' + +class VerboseFormatterTest < Test::Unit::TestCase + class ErrorHighlightDummyFormatter + def message_for(spot) + "" + end + end + + def setup + require_relative File.join(DidYouMean::TestHelper.root, 'verbose') + + DidYouMean.formatter = DidYouMean::VerboseFormatter.new + + if defined?(ErrorHighlight) + @error_highlight_old_formatter = ErrorHighlight.formatter + ErrorHighlight.formatter = ErrorHighlightDummyFormatter.new + end + end + + def teardown + DidYouMean.formatter = DidYouMean::PlainFormatter.new + + if defined?(ErrorHighlight) + ErrorHighlight.formatter = @error_highlight_old_formatter + end + end + + def test_message + @error = assert_raise(NoMethodError){ 1.zeor? } + + assert_match <<~MESSAGE.strip, @error.message + undefined method `zeor?' for 1:Integer + + Did you mean? zero? + MESSAGE + end +end