@@ -104,41 +104,27 @@ defmodule IEx.Introspection do
104104 Opens the given module, mfa, file/line, binary.
105105 """
106106 def open ( module ) when is_atom ( module ) do
107- case open_mfa ( module , :__info__ , 1 ) do
108- { source , nil , _ } -> open ( source )
109- { _ , tuple , _ } -> open ( tuple )
107+ case source_location ( module ) do
108+ { :ok , tuple } -> open ( tuple )
110109 { :error , reason } -> puts_error ( "Could not open #{ inspect ( module ) } , #{ reason } " )
111110 end
112111
113112 dont_display_result ( )
114113 end
115114
116115 def open ( { module , function } ) when is_atom ( module ) and is_atom ( function ) do
117- case open_mfa ( module , function , :* ) do
118- { _ , _ , nil } ->
119- puts_error (
120- "Could not open #{ inspect ( module ) } .#{ function } , function/macro is not available"
121- )
122-
123- { _ , _ , tuple } ->
124- open ( tuple )
125-
126- { :error , reason } ->
127- puts_error ( "Could not open #{ inspect ( module ) } .#{ function } , #{ reason } " )
116+ case source_location ( { module , function } ) do
117+ { :ok , tuple } -> open ( tuple )
118+ { :error , reason } -> puts_error ( "Could not open #{ inspect ( module ) } .#{ function } , #{ reason } " )
128119 end
129120
130121 dont_display_result ( )
131122 end
132123
133124 def open ( { module , function , arity } )
134125 when is_atom ( module ) and is_atom ( function ) and is_integer ( arity ) do
135- case open_mfa ( module , function , arity ) do
136- { _ , _ , nil } ->
137- puts_error (
138- "Could not open #{ inspect ( module ) } .#{ function } /#{ arity } , function/macro is not available"
139- )
140-
141- { _ , _ , tuple } ->
126+ case source_location ( { module , function , arity } ) do
127+ { :ok , tuple } ->
142128 open ( tuple )
143129
144130 { :error , reason } ->
@@ -181,13 +167,83 @@ defmodule IEx.Introspection do
181167 dont_display_result ( )
182168 end
183169
184- defp open_mfa ( module , fun , arity ) do
170+ @ doc """
171+ Prints source code.
172+ """
173+ def source ( module ) when is_atom ( module ) do
174+ case source_location ( module ) do
175+ { :ok , { file , _line } } ->
176+ IO . puts ( File . read! ( file ) )
177+
178+ { :error , reason } ->
179+ puts_error ( "Could not show source for #{ inspect ( module ) } , #{ reason } " )
180+ end
181+
182+ dont_display_result ( )
183+ end
184+
185+ def source ( { module , function } ) when is_atom ( module ) and is_atom ( function ) do
186+ case source_location ( { module , function } ) do
187+ { :ok , { file , _line } } ->
188+ IO . puts ( File . read! ( file ) )
189+
190+ { :error , reason } ->
191+ puts_error ( "Could not show source for #{ inspect ( module ) } .#{ function } , #{ reason } " )
192+ end
193+
194+ dont_display_result ( )
195+ end
196+
197+ def source ( { module , function , arity } )
198+ when is_atom ( module ) and is_atom ( function ) and is_integer ( arity ) do
199+ case source_location ( { module , function , arity } ) do
200+ { :ok , { file , _line } } ->
201+ IO . puts ( File . read! ( file ) )
202+
203+ { :error , reason } ->
204+ puts_error ( "Could not show source for #{ inspect ( module ) } .#{ function } /#{ arity } , #{ reason } " )
205+ end
206+
207+ dont_display_result ( )
208+ end
209+
210+ def source ( invalid ) do
211+ puts_error ( "Invalid arguments for source helper: #{ inspect ( invalid ) } " )
212+ dont_display_result ( )
213+ end
214+
215+ defp source_location ( module ) when is_atom ( module ) do
216+ case source_mfa ( module , :__info__ , 1 ) do
217+ { source , nil , _ } -> { :ok , { source , 1 } }
218+ { _ , tuple , _ } -> { :ok , tuple }
219+ { :error , reason } -> { :error , reason }
220+ end
221+ end
222+
223+ defp source_location ( { module , function } ) when is_atom ( module ) and is_atom ( function ) do
224+ case source_mfa ( module , function , :* ) do
225+ { _ , _ , nil } -> { :error , "function/macro is not available" }
226+ { _ , _ , tuple } -> { :ok , tuple }
227+ { :error , reason } -> { :error , reason }
228+ end
229+ end
230+
231+ defp source_location ( { module , function , arity } )
232+ when is_atom ( module ) and is_atom ( function ) and is_integer ( arity ) do
233+ case source_mfa ( module , function , arity ) do
234+ { _ , _ , nil } -> { :error , "function/macro is not available" }
235+ { _ , _ , tuple } -> { :ok , tuple }
236+ { :error , reason } -> { :error , reason }
237+ end
238+ end
239+
240+ defp source_mfa ( module , fun , arity ) do
185241 case Code . ensure_loaded ( module ) do
186242 { :module , _ } ->
187243 case module . module_info ( :compile ) [ :source ] do
188244 [ _ | _ ] = source ->
189245 source = rewrite_source ( module , source )
190- open_abstract_code ( module , fun , arity , source )
246+ source_abstract_code ( module , fun , arity , source )
191247
192248 _ ->
193249 { :error , "source code is not available" }
@@ -198,14 +254,14 @@ defmodule IEx.Introspection do
198254 end
199255 end
200256
201- defp open_abstract_code ( module , fun , arity , source ) do
257+ defp source_abstract_code ( module , fun , arity , source ) do
202258 fun = Atom . to_string ( fun )
203259
204260 with [ _ | _ ] = beam <- :code . which ( module ) ,
205261 { :ok , { _ , [ abstract_code: abstract_code ] } } <- :beam_lib . chunks ( beam , [ :abstract_code ] ) ,
206262 { :raw_abstract_v1 , code } <- abstract_code do
207263 { _ , module_pair , fa_pair } =
208- Enum . reduce ( code , { source , nil , nil } , & open_abstract_code_reduce ( & 1 , & 2 , fun , arity ) )
264+ Enum . reduce ( code , { source , nil , nil } , & source_abstract_code_reduce ( & 1 , & 2 , fun , arity ) )
209265
210266 { source , module_pair , fa_pair }
211267 else
@@ -214,7 +270,7 @@ defmodule IEx.Introspection do
214270 end
215271 end
216272
217- defp open_abstract_code_reduce ( entry , { file , module_pair , fa_pair } , fun , arity ) do
273+ defp source_abstract_code_reduce ( entry , { file , module_pair , fa_pair } , fun , arity ) do
218274 case entry do
219275 { :attribute , ann , :module , _ } ->
220276 { file , { file , :erl_anno . line ( ann ) } , fa_pair }
0 commit comments