1
0
Fork 0
mirror of https://github.com/pry/pry.git synced 2022-11-09 12:35:05 -05:00

Initial implementation of fast show-source command.

This requires an updated method_source gem. This approach works by reading all code between the start of the class definition
and the method with the highest line number in one go. Since we know this chunk of code is valid we can avoid the expensive eval-based validity checks.
Once we have primed the expression buffer with this chunk of code we then start the expensive checks looking for a complete expression, but there shouldn't be
many lines of code left since we've already processed the last method in the class definition. Using this technique i was able to show-source the 2000 line definition of
ActiveRecord::Base in under a second.
This commit is contained in:
John Mair 2012-06-29 05:24:18 +12:00
parent 4714d1835c
commit 2ad9d0befc
3 changed files with 18 additions and 9 deletions

View file

@ -352,8 +352,8 @@ class Pry
# #
# @param [Fixnum] line_number (1-based) # @param [Fixnum] line_number (1-based)
# @return [String] the code. # @return [String] the code.
def expression_at(line_number) def expression_at(line_number, consume=0)
self.class.expression_at(raw, line_number) self.class.expression_at(raw, line_number, :consume => consume)
end end
# Return an unformatted String of the code. # Return an unformatted String of the code.

View file

@ -52,8 +52,10 @@ class Pry
return @source if @source return @source if @source
raise CommandError, "Could not locate source for #{wrapped}!" if file.nil? raise CommandError, "Could not locate source for #{wrapped}!" if file.nil?
end_line = end_method_source_location.last
@source = strip_leading_whitespace(Pry::Code.from_file(file).expression_at(line)) num_lines = end_line - line
@source = strip_leading_whitespace(Pry::Code.from_file(file).expression_at(line, num_lines))
end end
# @raise [Pry::CommandError] If documentation cannot be found. # @raise [Pry::CommandError] If documentation cannot be found.
@ -86,7 +88,7 @@ class Pry
return @source_location if @source_location return @source_location if @source_location
mod_type_string = wrapped.class.to_s.downcase mod_type_string = wrapped.class.to_s.downcase
file, line = method_source_location file, line = start_method_source_location
return nil if !file.is_a?(String) return nil if !file.is_a?(String)
@ -110,16 +112,22 @@ class Pry
# starting point for the search for the candidate's definition. # starting point for the search for the candidate's definition.
# @return [Array] The source location of the base method used to # @return [Array] The source location of the base method used to
# calculate the source location of the candidate. # calculate the source location of the candidate.
def method_source_location def start_method_source_location
return @method_source_location if @method_source_location adjusted_source_location(method_candidates[@rank].first.source_location)
end
file, line = method_candidates[@rank].source_location def end_method_source_location
adjusted_source_location(method_candidates[@rank].last.source_location)
end
def adjusted_source_location(sl)
file, line = sl
if file && RbxPath.is_core_path?(file) if file && RbxPath.is_core_path?(file)
file = RbxPath.convert_path_to_full(file) file = RbxPath.convert_path_to_full(file)
end end
@method_source_location = [file, line] [file, line]
end end
# @param [String] doc The raw docstring to process. # @param [String] doc The raw docstring to process.

View file

@ -213,7 +213,8 @@ class Pry
# the search in uncovering the module definition. # the search in uncovering the module definition.
def method_candidates def method_candidates
@method_candidates ||= all_source_locations_by_popularity.map do |group| @method_candidates ||= all_source_locations_by_popularity.map do |group|
group.last.sort_by(&:source_line).first # best candidate for group methods_sorted_by_source_line = group.last.sort_by(&:source_line)
[methods_sorted_by_source_line.first, methods_sorted_by_source_line.last]
end end
end end