mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	Sync did_you_mean
This commit is contained in:
		
							parent
							
								
									8d940e3032
								
							
						
					
					
						commit
						f9712b029b
					
				
					 9 changed files with 78 additions and 14 deletions
				
			
		| 
						 | 
				
			
			@ -86,12 +86,25 @@ require_relative 'did_you_mean/tree_spell_checker'
 | 
			
		|||
#
 | 
			
		||||
module DidYouMean
 | 
			
		||||
  # Map of error types and spell checker objects.
 | 
			
		||||
  SPELL_CHECKERS = Hash.new(NullChecker)
 | 
			
		||||
  @spell_checkers = Hash.new(NullChecker)
 | 
			
		||||
 | 
			
		||||
  # Returns a sharable hash map of error types and spell checker objects.
 | 
			
		||||
  def self.spell_checkers
 | 
			
		||||
    @spell_checkers
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Adds +DidYouMean+ functionality to an error using a given spell checker
 | 
			
		||||
  def self.correct_error(error_class, spell_checker)
 | 
			
		||||
    SPELL_CHECKERS[error_class.name] = spell_checker
 | 
			
		||||
    error_class.prepend(Correctable) unless error_class < Correctable
 | 
			
		||||
    if defined?(Ractor)
 | 
			
		||||
      new_mapping = { **@spell_checkers, error_class.to_s => spell_checker }
 | 
			
		||||
      new_mapping.default = NullChecker
 | 
			
		||||
 | 
			
		||||
      @spell_checkers = Ractor.make_shareable(new_mapping)
 | 
			
		||||
    else
 | 
			
		||||
      spell_checkers[error_class.to_s] = spell_checker
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    error_class.prepend(Correctable) if error_class.is_a?(Class) && !(error_class < Correctable)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  correct_error NameError, NameErrorCheckers
 | 
			
		||||
| 
						 | 
				
			
			@ -100,15 +113,43 @@ module DidYouMean
 | 
			
		|||
  correct_error LoadError, RequirePathChecker if RUBY_VERSION >= '2.8.0'
 | 
			
		||||
  correct_error NoMatchingPatternKeyError, PatternKeyNameChecker if defined?(::NoMatchingPatternKeyError)
 | 
			
		||||
 | 
			
		||||
  # TODO: Remove on 3.3:
 | 
			
		||||
  class DeprecatedMapping # :nodoc:
 | 
			
		||||
    def []=(key, value)
 | 
			
		||||
      warn "Calling `DidYouMean::SPELL_CHECKERS[#{key.to_s}] = #{value.to_s}' has been deprecated. " \
 | 
			
		||||
           "Please call `DidYouMean.correct_error(#{key.to_s}, #{value.to_s})' instead."
 | 
			
		||||
 | 
			
		||||
      DidYouMean.correct_error(key, value)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def merge!(hash)
 | 
			
		||||
      warn "Calling `DidYouMean::SPELL_CHECKERS.merge!(error_name => spell_checker)' has been deprecated. " \
 | 
			
		||||
           "Please call `DidYouMean.correct_error(error_name, spell_checker)' instead."
 | 
			
		||||
 | 
			
		||||
      hash.each do |error_class, spell_checker|
 | 
			
		||||
        DidYouMean.correct_error(error_class, spell_checker)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # TODO: Remove on 3.3:
 | 
			
		||||
  SPELL_CHECKERS = DeprecatedMapping.new
 | 
			
		||||
  deprecate_constant :SPELL_CHECKERS
 | 
			
		||||
  private_constant :DeprecatedMapping
 | 
			
		||||
 | 
			
		||||
  # Returns the currently set formatter. By default, it is set to +DidYouMean::Formatter+.
 | 
			
		||||
  def self.formatter
 | 
			
		||||
    @formatter
 | 
			
		||||
    if defined?(Ractor)
 | 
			
		||||
      Ractor.current[:__did_you_mean_formatter__] || Formatter
 | 
			
		||||
    else
 | 
			
		||||
      Formatter
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Updates the primary formatter used to format the suggestions.
 | 
			
		||||
  def self.formatter=(formatter)
 | 
			
		||||
    @formatter = formatter
 | 
			
		||||
    if defined?(Ractor)
 | 
			
		||||
      Ractor.current[:__did_you_mean_formatter__] = formatter
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @formatter = Formatter.new
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ module DidYouMean
 | 
			
		|||
    end
 | 
			
		||||
 | 
			
		||||
    def spell_checker
 | 
			
		||||
      SPELL_CHECKERS[self.class.to_s].new(self)
 | 
			
		||||
      DidYouMean.spell_checkers[self.class.to_s].new(self)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,10 +26,19 @@ module DidYouMean
 | 
			
		|||
    #
 | 
			
		||||
    #   # => nil
 | 
			
		||||
    #
 | 
			
		||||
    def message_for(corrections)
 | 
			
		||||
    def self.message_for(corrections)
 | 
			
		||||
      corrections.empty? ? "" : "\nDid you mean?  #{corrections.join("\n               ")}"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def message_for(corrections)
 | 
			
		||||
      warn "The instance method #message_for has been deprecated. Please use the class method " \
 | 
			
		||||
           "DidYouMean::Formatter.message_for(...) instead."
 | 
			
		||||
 | 
			
		||||
      self.class.message_for(corrections)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  PlainFormatter = Formatter
 | 
			
		||||
 | 
			
		||||
  deprecate_constant :PlainFormatter
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ module DidYouMean
 | 
			
		|||
 | 
			
		||||
    NAMES_TO_EXCLUDE = { NilClass => nil.methods }
 | 
			
		||||
    NAMES_TO_EXCLUDE.default = []
 | 
			
		||||
    Ractor.make_shareable(NAMES_TO_EXCLUDE) if defined?(Ractor)
 | 
			
		||||
 | 
			
		||||
    # +MethodNameChecker::RB_RESERVED_WORDS+ is the list of reserved words in
 | 
			
		||||
    # Ruby that take an argument. Unlike
 | 
			
		||||
| 
						 | 
				
			
			@ -36,6 +37,8 @@ module DidYouMean
 | 
			
		|||
      yield
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    Ractor.make_shareable(RB_RESERVED_WORDS) if defined?(Ractor)
 | 
			
		||||
 | 
			
		||||
    def initialize(exception)
 | 
			
		||||
      @method_name  = exception.name
 | 
			
		||||
      @receiver     = exception.receiver
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ module DidYouMean
 | 
			
		|||
 | 
			
		||||
    NAMES_TO_EXCLUDE = { 'foo' => [:fork, :for] }
 | 
			
		||||
    NAMES_TO_EXCLUDE.default = []
 | 
			
		||||
    Ractor.make_shareable(NAMES_TO_EXCLUDE) if defined?(Ractor)
 | 
			
		||||
 | 
			
		||||
    # +VariableNameChecker::RB_RESERVED_WORDS+ is the list of all reserved
 | 
			
		||||
    # words in Ruby. They could be declared like methods are, and a typo would
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +63,8 @@ module DidYouMean
 | 
			
		|||
      __ENCODING__
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    Ractor.make_shareable(RB_RESERVED_WORDS) if defined?(Ractor)
 | 
			
		||||
 | 
			
		||||
    def initialize(exception)
 | 
			
		||||
      @name       = exception.name.to_s.tr("@", "")
 | 
			
		||||
      @lvar_names = exception.respond_to?(:local_variables) ? exception.local_variables : []
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,10 @@ module DidYouMean
 | 
			
		|||
    attr_reader :path
 | 
			
		||||
 | 
			
		||||
    INITIAL_LOAD_PATH = $LOAD_PATH.dup.freeze
 | 
			
		||||
    ENV_SPECIFIC_EXT  = ".#{RbConfig::CONFIG["DLEXT"]}"
 | 
			
		||||
    Ractor.make_shareable(INITIAL_LOAD_PATH) if defined?(Ractor)
 | 
			
		||||
 | 
			
		||||
    ENV_SPECIFIC_EXT = ".#{RbConfig::CONFIG["DLEXT"]}"
 | 
			
		||||
    Ractor.make_shareable(ENV_SPECIFIC_EXT) if defined?(Ractor)
 | 
			
		||||
 | 
			
		||||
    private_constant :INITIAL_LOAD_PATH, :ENV_SPECIFIC_EXT
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,3 @@
 | 
			
		|||
module DidYouMean
 | 
			
		||||
  VERSION = "1.6.0-alpha"
 | 
			
		||||
  VERSION = "1.6.1".freeze
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
require_relative '../helper'
 | 
			
		||||
 | 
			
		||||
class NameErrorExtensionTest < Test::Unit::TestCase
 | 
			
		||||
  SPELL_CHECKERS = DidYouMean::SPELL_CHECKERS
 | 
			
		||||
  SPELL_CHECKERS = DidYouMean.spell_checkers
 | 
			
		||||
 | 
			
		||||
  class TestSpellChecker
 | 
			
		||||
    def initialize(*); end
 | 
			
		||||
| 
						 | 
				
			
			@ -9,13 +9,14 @@ class NameErrorExtensionTest < Test::Unit::TestCase
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def setup
 | 
			
		||||
    @org, SPELL_CHECKERS['NameError'] = SPELL_CHECKERS['NameError'], TestSpellChecker
 | 
			
		||||
    @original_spell_checker = DidYouMean.spell_checkers['NameError']
 | 
			
		||||
    DidYouMean.correct_error(NameError, TestSpellChecker)
 | 
			
		||||
 | 
			
		||||
    @error = assert_raise(NameError){ doesnt_exist }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def teardown
 | 
			
		||||
    SPELL_CHECKERS['NameError'] = @org
 | 
			
		||||
    DidYouMean.correct_error(NameError, @original_spell_checker)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_message
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,10 @@ module DidYouMean
 | 
			
		|||
  module TestHelper
 | 
			
		||||
    class << self
 | 
			
		||||
      attr_reader :root
 | 
			
		||||
 | 
			
		||||
      def ractor_compatible?
 | 
			
		||||
        defined?(Ractor) && RUBY_VERSION >= "3.1.0"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if File.file?(File.expand_path('../lib/did_you_mean.rb', __dir__))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue