2 // monop -- a semi-clone of javap
5 // Ben Maurer (bmaurer@users.sourceforge.net)
6 // John Luke (john.luke@gmail.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System
.CodeDom
.Compiler
;
36 using System
.Collections
;
37 using System
.Diagnostics
;
39 using System
.Reflection
;
44 static string assembly
;
46 // very common namespaces, all in corlib
47 static readonly string [] v_common_ns
= {
55 static readonly string [] common_assemblies
= {
62 static readonly string [] common_ns
= {
69 static Type
GetType (string tname
, bool ignoreCase
)
72 if (assembly
!= null) {
73 Assembly a
= GetAssembly (assembly
, true);
74 t
= a
.GetType (tname
, false, ignoreCase
);
76 t
= Type
.GetType (tname
, false, ignoreCase
);
81 static string SearchTypes (string name
, ref Type retval
, out int count
)
83 StringBuilder sb
= new StringBuilder ();
87 string [] assemblies
= GetKnownAssemblyNames ();
88 for (int i
= 0; i
< assemblies
.Length
; i
++) {
89 Assembly a
= GetAssembly (assemblies
[i
], false);
93 Type
[] types
= a
.GetTypes ();
94 for (int j
= 0; j
< types
.Length
; j
++) {
96 if (t
.IsPublic
== false)
99 if (t
.Name
== name
|| t
.Name
.ToLower ().IndexOf (name
.ToLower ()) > 0) {
102 sb
.Append (t
.FullName
+ " from " + a
.Location
+ "\n");
115 return sb
.ToString ();
118 static string [] GetKnownAssemblyNames ()
120 Process p
= new Process ();
121 p
.StartInfo
.UseShellExecute
= false;
122 p
.StartInfo
.RedirectStandardOutput
= true;
123 p
.StartInfo
.FileName
= "gacutil";
124 p
.StartInfo
.Arguments
= "-l";
129 Console
.WriteLine ("WARNING: gacutil could not be found.");
130 return new string[0];
134 ArrayList names
= new ArrayList ();
135 StreamReader output
= p
.StandardOutput
;
137 while ((s
= output
.ReadLine ()) != null)
142 int length
= names
.Count
- 1;
143 string [] retval
= new string [length
];
144 retval
[0] = typeof (Object
).Assembly
.FullName
;
145 names
.CopyTo (1, retval
, 1, length
- 1); // skip the first and last line
149 static Assembly
GetAssembly (string assembly
, bool exit
)
153 // if -r:~/foo.dll syntax is used the shell misses it
154 if (assembly
.StartsWith ("~/"))
155 assembly
= Path
.Combine (Environment
.GetFolderPath (Environment
.SpecialFolder
.Personal
), assembly
.Substring (2));
158 // if it exists try to use LoadFrom
159 if (File
.Exists (assembly
))
160 a
= Assembly
.LoadFrom (assembly
);
161 // if it looks like a fullname try that
162 else if (assembly
.Split (',').Length
== 4)
163 a
= Assembly
.Load (assembly
);
164 // see if MONO_PATH has it
166 a
= LoadFromMonoPath (assembly
);
168 // ignore exception it gets handled below
171 // last try partial name
172 // this (apparently) is exception safe
174 a
= Assembly
.LoadWithPartialName (assembly
);
176 if (a
== null && exit
) {
177 Console
.WriteLine ("Could not load {0}", MonoP
.assembly
);
178 Environment
.Exit (1);
184 static Assembly
LoadFromMonoPath (string assembly
)
186 // ; on win32, : everywhere else
187 char sep
= (Path
.DirectorySeparatorChar
== '/' ? ':' : ';');
188 string[] paths
= Environment
.GetEnvironmentVariable ("MONO_PATH").Split (sep
);
189 foreach (string path
in paths
) {
190 string apath
= Path
.Combine (path
, assembly
);
191 if (File
.Exists (apath
))
192 return Assembly
.LoadFrom (apath
);
197 static Type
GetType (string tname
)
199 return GetType (tname
, false);
202 static void PrintRefs (string assembly
)
204 Assembly a
= GetAssembly (assembly
, true);
205 foreach (AssemblyName an
in a
.GetReferencedAssemblies ())
206 Console
.WriteLine (an
);
209 static void PrintTypes (string assembly
, bool show_private
, bool filter_obsolete
)
211 Assembly a
= GetAssembly (assembly
, true);
213 Console
.WriteLine ();
214 Console
.WriteLine ("Assembly Information:");
216 object[] cls
= a
.GetCustomAttributes (typeof (CLSCompliantAttribute
), false);
217 if (cls
.Length
> 0) {
218 CLSCompliantAttribute cca
= cls
[0] as CLSCompliantAttribute
;
220 Console
.WriteLine ("[CLSCompliant]");
223 foreach (string ai
in a
.ToString ().Split (','))
224 Console
.WriteLine (ai
.Trim ());
226 Console
.WriteLine ();
227 Type
[] types
= show_private
? a
.GetTypes () : a
.GetExportedTypes ();
228 Array
.Sort (types
, new TypeSorter ());
230 int obsolete_count
= 0;
231 foreach (Type t
in types
) {
232 if (filter_obsolete
&& t
.IsDefined (typeof (ObsoleteAttribute
), false))
235 Console
.WriteLine (t
.FullName
);
238 Console
.WriteLine ("\nTotal: {0} types.", types
.Length
- obsolete_count
);
241 internal static void Completion (string prefix
)
243 foreach (Type t
in typeof (object).Assembly
.GetExportedTypes ()) {
244 if (t
.Name
.StartsWith (prefix
)) {
245 if (Array
.IndexOf (v_common_ns
, t
.Namespace
) != -1) {
246 Console
.WriteLine (t
.Name
);
251 if (t
.FullName
.StartsWith (prefix
)) {
252 Console
.WriteLine (t
.FullName
);
256 foreach (string assm
in common_assemblies
) {
259 Assembly a
= GetAssembly (assm
, true);
260 foreach (Type t
in a
.GetExportedTypes ()) {
262 if (t
.Name
.StartsWith (prefix
)) {
263 if (Array
.IndexOf (common_ns
, t
.Namespace
) != -1) {
264 Console
.WriteLine (t
.Name
);
269 if (t
.FullName
.StartsWith (prefix
)) {
270 Console
.WriteLine (t
.FullName
);
280 static void ShowAll (string assembly
, bool show_private
, bool filter_obsolete
)
282 Assembly a
= GetAssembly (assembly
, true);
284 object[] cls
= a
.GetCustomAttributes (typeof (CLSCompliantAttribute
), false);
285 if (cls
.Length
> 0) {
286 CLSCompliantAttribute cca
= cls
[0] as CLSCompliantAttribute
;
288 Console
.WriteLine ("[CLSCompliant]");
291 foreach (string ai
in a
.ToString ().Split (','))
292 Console
.WriteLine (ai
.Trim ());
294 Console
.WriteLine ();
295 Type
[] types
= show_private
? a
.GetTypes () : a
.GetExportedTypes ();
296 Array
.Sort (types
, new TypeSorter ());
298 var sw
= new StreamWriter (Console
.OpenStandardOutput (), Console
.Out
.Encoding
);
299 foreach (Type t
in types
) {
300 if (filter_obsolete
&& t
.IsDefined (typeof (ObsoleteAttribute
), false))
303 new Outline (t
, sw
, true, show_private
, filter_obsolete
).OutlineType ();
308 static void Main (string [] args
)
310 Options options
= new Options ();
311 if (!options
.ProcessArgs (args
))
314 if (options
.AssemblyReference
!= null) {
315 assembly
= options
.AssemblyReference
;
317 if (options
.ShowAll
){
318 ShowAll (assembly
, options
.FilterObsolete
, options
.ShowPrivate
);
321 if (options
.Type
== null) {
322 if (options
.PrintRefs
)
323 PrintRefs (assembly
);
325 PrintTypes (assembly
, options
.ShowPrivate
, options
.FilterObsolete
);
331 string message
= null;
332 string tname
= options
.Type
;
336 if (options
.Search
) {
337 string matches
= SearchTypes (tname
, ref t
, out count
);
346 Console
.WriteLine ("Found " + count
+ " types that match:");
347 Console
.WriteLine (matches
);
355 // Try some very common ones, dont load anything
356 foreach (string ns
in v_common_ns
) {
357 t
= GetType (ns
+ "." + tname
, true);
364 foreach (string assm
in GetKnownAssemblyNames ()) {
366 Assembly a
= GetAssembly (assm
, false);
367 t
= a
.GetType (tname
, false, true);
369 message
= String
.Format ("{0} is included in the {1} assembly.",
371 t
.Assembly
.GetName ().Name
);
374 foreach (string ns
in common_ns
) {
375 t
= a
.GetType (ns
+ "." + tname
, false, true);
377 message
= String
.Format ("{0} is included in the {1} assembly.",
379 t
.Assembly
.GetName ().Name
);
390 Console
.WriteLine ("Could not find {0}", tname
);
395 // This gets us nice buffering
397 StreamWriter sw
= new StreamWriter (Console
.OpenStandardOutput (), Console
.Out
.Encoding
);
398 new Outline (t
, sw
, options
.DeclaredOnly
, options
.ShowPrivate
, options
.FilterObsolete
).OutlineType ();
402 Console
.WriteLine (message
);