1
1
# frozen_string_literal: true
2
2
3
3
require_relative "nop"
4
+ require_relative "../source_finder"
4
5
require_relative "../color"
5
- require_relative "../ruby-lex"
6
6
7
7
module IRB
8
- # :stopdoc:
9
-
10
8
module ExtendCommand
11
9
class ShowSource < Nop
12
10
category "Context"
@@ -21,51 +19,6 @@ def transform_args(args)
21
19
args . strip . dump
22
20
end
23
21
end
24
-
25
- def find_source ( str , irb_context )
26
- case str
27
- when /\A [A-Z]\w *(::[A-Z]\w *)*\z / # Const::Name
28
- eval ( str , irb_context . workspace . binding ) # trigger autoload
29
- base = irb_context . workspace . binding . receiver . yield_self { |r | r . is_a? ( Module ) ? r : Object }
30
- file , line = base . const_source_location ( str )
31
- when /\A (?<owner>[A-Z]\w *(::[A-Z]\w *)*)#(?<method>[^ :.]+)\z / # Class#method
32
- owner = eval ( Regexp . last_match [ :owner ] , irb_context . workspace . binding )
33
- method = Regexp . last_match [ :method ]
34
- if owner . respond_to? ( :instance_method )
35
- methods = owner . instance_methods + owner . private_instance_methods
36
- file , line = owner . instance_method ( method ) . source_location if methods . include? ( method . to_sym )
37
- end
38
- when /\A ((?<receiver>.+)(\. |::))?(?<method>[^ :.]+)\z / # method, receiver.method, receiver::method
39
- receiver = eval ( Regexp . last_match [ :receiver ] || 'self' , irb_context . workspace . binding )
40
- method = Regexp . last_match [ :method ]
41
- file , line = receiver . method ( method ) . source_location if receiver . respond_to? ( method , true )
42
- end
43
- if file && line
44
- Source . new ( file : file , first_line : line , last_line : find_end ( file , line , irb_context ) )
45
- end
46
- end
47
-
48
- private
49
-
50
- def find_end ( file , first_line , irb_context )
51
- return first_line unless File . exist? ( file )
52
- lex = RubyLex . new ( irb_context )
53
- lines = File . read ( file ) . lines [ ( first_line - 1 ) ..-1 ]
54
- tokens = RubyLex . ripper_lex_without_warning ( lines . join )
55
- prev_tokens = [ ]
56
-
57
- # chunk with line number
58
- tokens . chunk { |tok | tok . pos [ 0 ] } . each do |lnum , chunk |
59
- code = lines [ 0 ..lnum ] . join
60
- prev_tokens . concat chunk
61
- continue = lex . should_continue? ( prev_tokens )
62
- syntax = lex . check_code_syntax ( code )
63
- if !continue && syntax == :valid
64
- return first_line + lnum
65
- end
66
- end
67
- first_line
68
- end
69
22
end
70
23
71
24
def execute ( str = nil )
@@ -74,8 +27,9 @@ def execute(str = nil)
74
27
return
75
28
end
76
29
77
- source = self . class . find_source ( str , @irb_context )
78
- if source && File . exist? ( source . file )
30
+ source = SourceFinder . new ( @irb_context ) . find_source ( str )
31
+
32
+ if source
79
33
show_source ( source )
80
34
else
81
35
puts "Error: Couldn't locate a definition for #{ str } "
@@ -85,7 +39,6 @@ def execute(str = nil)
85
39
86
40
private
87
41
88
- # @param [IRB::ExtendCommand::ShowSource::Source] source
89
42
def show_source ( source )
90
43
puts
91
44
puts "#{ bold ( "From" ) } : #{ source . file } :#{ source . first_line } "
@@ -98,16 +51,6 @@ def show_source(source)
98
51
def bold ( str )
99
52
Color . colorize ( str , [ :BOLD ] )
100
53
end
101
-
102
- Source = Struct . new (
103
- :file , # @param [String] - file name
104
- :first_line , # @param [String] - first line
105
- :last_line , # @param [String] - last line
106
- keyword_init : true ,
107
- )
108
- private_constant :Source
109
54
end
110
55
end
111
-
112
- # :startdoc:
113
56
end
0 commit comments