[前][次][番号順一覧][スレッド一覧]

ruby-changes:61588

From: Yuki <ko1@a...>
Date: Sun, 7 Jun 2020 02:02:28 +0900 (JST)
Subject: [ruby-changes:61588] e5f5446528 (master): Sync did_you_mean

https://git.ruby-lang.org/ruby.git/commit/?id=e5f5446528

From e5f54465284b4505042fca10ace998e1d29c2313 Mon Sep 17 00:00:00 2001
From: Yuki Nishijima <yk.nishijima@g...>
Date: Fri, 22 May 2020 17:17:10 -0400
Subject: Sync did_you_mean


diff --git a/lib/did_you_mean.rb b/lib/did_you_mean.rb
index b8f9257..ab7e6b0 100644
--- a/lib/did_you_mean.rb
+++ b/lib/did_you_mean.rb
@@ -6,6 +6,7 @@ require_relative 'did_you_mean/spell_checkers/name_error_checkers' https://github.com/ruby/ruby/blob/trunk/lib/did_you_mean.rb#L6
 require_relative 'did_you_mean/spell_checkers/method_name_checker'
 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/formatters/plain_formatter'
 require_relative 'did_you_mean/tree_spell_checker'
 
@@ -95,8 +96,9 @@ module DidYouMean https://github.com/ruby/ruby/blob/trunk/lib/did_you_mean.rb#L96
   correct_error NameError, NameErrorCheckers
   correct_error KeyError, KeyErrorChecker
   correct_error NoMethodError, MethodNameChecker
+  correct_error LoadError, RequirePathChecker if RUBY_VERSION >= '2.8.0'
 
-  # Returns the currenctly set formatter. By default, it is set to +DidYouMean::Formatter+.
+  # Returns the currently set formatter. By default, it is set to +DidYouMean::Formatter+.
   def self.formatter
     @@formatter
   end
diff --git a/lib/did_you_mean/experimental/ivar_name_correction.rb b/lib/did_you_mean/experimental/ivar_name_correction.rb
index 322e422..7b97ff4 100644
--- a/lib/did_you_mean/experimental/ivar_name_correction.rb
+++ b/lib/did_you_mean/experimental/ivar_name_correction.rb
@@ -1,22 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/lib/did_you_mean/experimental/ivar_name_correction.rb#L1
 # frozen-string-literal: true
 
-require_relative '../../did_you_mean'
+require_relative '../../did_you_mean/spell_checker'
+require_relative '../../did_you_mean/spell_checkers/method_name_checker'
 
 module DidYouMean
   module Experimental #:nodoc:
-    class IvarNameCheckerBuilder #:nodoc:
-      attr_reader :original_checker
-
-      def initialize(original_checker) #:nodoc:
-        @original_checker = original_checker
-      end
-
-      def new(no_method_error) #:nodoc:
-        IvarNameChecker.new(no_method_error, original_checker: @original_checker)
-      end
-    end
-
-    class IvarNameChecker #:nodoc:
+    class IvarNameChecker < ::DidYouMean::MethodNameChecker #:nodoc:
       REPLS = {
         "(irb)" => -> { Readline::HISTORY.to_a.last }
       }
@@ -29,10 +18,10 @@ module DidYouMean https://github.com/ruby/ruby/blob/trunk/lib/did_you_mean/experimental/ivar_name_correction.rb#L18
         end
       end
 
-      attr_reader :original_checker
+      attr_reader :location, :ivar_names
 
-      def initialize(no_method_error, original_checker: )
-        @original_checker = original_checker.new(no_method_error)
+      def initialize(no_method_error)
+        super(no_method_error)
 
         @location   = no_method_error.backtrace_locations.first
         @ivar_names = no_method_error.frame_binding.receiver.instance_variables
@@ -41,22 +30,22 @@ module DidYouMean https://github.com/ruby/ruby/blob/trunk/lib/did_you_mean/experimental/ivar_name_correction.rb#L30
       end
 
       def corrections
-        original_checker.corrections + ivar_name_corrections
+        super + ivar_name_corrections
       end
 
       def ivar_name_corrections
-        @ivar_name_corrections ||= SpellChecker.new(dictionary: @ivar_names).correct(receiver_name.to_s)
+        @ivar_name_corrections ||= SpellChecker.new(dictionary: ivar_names).correct(receiver_name.to_s)
       end
 
       private
 
       def receiver_name
-        return unless @original_checker.receiver.nil?
+        return unless receiver.nil?
 
-        abs_path = @location.absolute_path
-        lineno   = @location.lineno
+        abs_path = location.absolute_path
+        lineno   = location.lineno
 
-        /@(\w+)*\.#{@original_checker.method_name}/ =~ line(abs_path, lineno).to_s && $1
+        /@(\w+)*\.#{method_name}/ =~ line(abs_path, lineno).to_s && $1
       end
 
       def line(abs_path, lineno)
@@ -71,6 +60,6 @@ module DidYouMean https://github.com/ruby/ruby/blob/trunk/lib/did_you_mean/experimental/ivar_name_correction.rb#L60
     end
   end
 
-  NameError.send(:attr, :frame_binding)
-  SPELL_CHECKERS['NoMethodError'] = Experimental::IvarNameCheckerBuilder.new(SPELL_CHECKERS['NoMethodError'])
+  NoMethodError.send(:attr, :frame_binding)
+  SPELL_CHECKERS['NoMethodError'] = Experimental::IvarNameChecker
 end
diff --git a/lib/did_you_mean/spell_checkers/method_name_checker.rb b/lib/did_you_mean/spell_checkers/method_name_checker.rb
index 3a38245..0483127 100644
--- a/lib/did_you_mean/spell_checkers/method_name_checker.rb
+++ b/lib/did_you_mean/spell_checkers/method_name_checker.rb
@@ -43,7 +43,12 @@ module DidYouMean https://github.com/ruby/ruby/blob/trunk/lib/did_you_mean/spell_checkers/method_name_checker.rb#L43
     end
 
     def corrections
-      @corrections ||= SpellChecker.new(dictionary: RB_RESERVED_WORDS + method_names).correct(method_name) - names_to_exclude
+      @corrections ||= begin
+                         dictionary = method_names
+                         dictionary = RB_RESERVED_WORDS + dictionary if @private_call
+
+                         SpellChecker.new(dictionary: dictionary).correct(method_name) - names_to_exclude
+                       end
     end
 
     def method_names
diff --git a/lib/did_you_mean/spell_checkers/require_path_checker.rb b/lib/did_you_mean/spell_checkers/require_path_checker.rb
new file mode 100644
index 0000000..aaf877b
--- /dev/null
+++ b/lib/did_you_mean/spell_checkers/require_path_checker.rb
@@ -0,0 +1,35 @@ https://github.com/ruby/ruby/blob/trunk/lib/did_you_mean/spell_checkers/require_path_checker.rb#L1
+# frozen-string-literal: true
+
+require_relative "../spell_checker"
+require_relative "../tree_spell_checker"
+
+module DidYouMean
+  class RequirePathChecker
+    attr_reader :path
+
+    INITIAL_LOAD_PATH = $LOAD_PATH.dup.freeze
+    ENV_SPECIFIC_EXT  = ".#{RbConfig::CONFIG["DLEXT"]}"
+
+    private_constant :INITIAL_LOAD_PATH, :ENV_SPECIFIC_EXT
+
+    def self.requireables
+      @requireables ||= INITIAL_LOAD_PATH
+                          .flat_map {|path| Dir.glob("**/???*{.rb,#{ENV_SPECIFIC_EXT}}", base: path) }
+                          .map {|path| path.chomp!(".rb") || path.chomp!(ENV_SPECIFIC_EXT) }
+    end
+
+    def initialize(exception)
+      @path = exception.path
+    end
+
+    def corrections
+      @corrections ||= begin
+                         threshold     = path.size * 2
+                         dictionary    = self.class.requireables.reject {|str| str.size >= threshold }
+                         spell_checker = path.include?("/") ? TreeSpellChecker : SpellChecker
+
+                         spell_checker.new(dictionary: dictionary).correct(path).uniq
+                       end
+    end
+  end
+end
diff --git a/lib/did_you_mean/tree_spell_checker.rb b/lib/did_you_mean/tree_spell_checker.rb
index 6a5b485..799f07f 100644
--- a/lib/did_you_mean/tree_spell_checker.rb
+++ b/lib/did_you_mean/tree_spell_checker.rb
@@ -1,137 +1,109 @@ https://github.com/ruby/ruby/blob/trunk/lib/did_you_mean/tree_spell_checker.rb#L1
+# frozen_string_literal: true
+
 module DidYouMean
   # spell checker for a dictionary that has a tree
   # structure, see doc/tree_spell_checker_api.md
   class TreeSpellChecker
-    attr_reader :dictionary, :dimensions, :separator, :augment
+    attr_reader :dictionary, :separator, :augment
 
     def initialize(dictionary:, separator: '/', augment: nil)
       @dictionary = dictionary
       @separator = separator
       @augment = augment
-      @dimensions = parse_dimensions
     end
 
     def correct(input)
-      plausibles = plausible_dimensions input
-      return no_idea(input) if plausibles.empty?
-      suggestions = find_suggestions input, plausibles
-      return no_idea(input) if suggestions.empty?
-      suggestions
-    end
+      plausibles = plausible_dimensions(input)
+      return fall_back_to_normal_spell_check(input) if plausibles.empty?
 
-    private
+      suggestions = find_suggestions(input, plausibles)
+      return fall_back_to_normal_spell_check(input) if suggestions.empty?
 
-    def parse_dimensions
-      ParseDimensions.new(dictionary, separator).call
+      suggestions
     end
 
-    def find_suggestions(input, plausibles)
-      states = plausibles[0].product(*plausibles[1..-1])
-      paths = possible_paths states
-      leaf = input.split(separator).last
-      ideas = find_ideas(paths, leaf)
-      ideas.compact.flatten
+    def dictionary_without_leaves
+      @dictionary_without_leaves ||= dictionary.map { |word| word.split(separator)[0..-2] }.uniq
     end
 
-    def no_idea(input)
-      return [] unless augment
-      ::DidYouMean::SpellChecker.new(dictionary: dictionary).correct(input)
+    def tree_depth
+      @tree_depth ||= dictionary_without_leaves.max { |a, b| a.size <=> b.size }.size
     end
 
-    def find_ideas(paths, leaf)
-      paths.map do |path|
-        names = find_leaves(path)
-        ideas = CorrectElement.new.call names, leaf
-        ideas_to_paths ideas, leaf, names, path
-      end
+    def dimensions
+      @dimensions ||= tree_depth.times.map do |index|
+                        dictionary_without_leaves.map { |element| element[index] }.compact.uniq
+                      end
     end
 
-    def ideas_to_paths(ideas, leaf, names, path)
-      return nil if ideas.empty?
-      return [path + separator + leaf] if names.include? leaf
-      ideas.map { |str| path + separator + str }
+    def find_leaves(path)
+      path_with_separator = "#{path}#{separator}"
+
+      dictionary
+        .select {|str| str.include?(path_with_separator) }
+        .map {|str| str.gsub(path_with_separator, '') }
     end
 
-    def find_leaves(path)
- (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]