add ISafeSerializationData
[mcs.git] / tools / monop / monop.cs
blob504d899f831e6a22c2b059c6a02317ed1f6a5db9
1 //
2 // monop -- a semi-clone of javap
3 //
4 // Authors:
5 // Ben Maurer (bmaurer@users.sourceforge.net)
6 // John Luke (john.luke@gmail.com)
7 //
8 // (C) 2004 Ben Maurer
9 // (C) 2004 John Luke
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:
20 //
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 //
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.
34 using System;
35 using System.CodeDom.Compiler;
36 using System.Collections;
37 using System.Diagnostics;
38 using System.IO;
39 using System.Reflection;
40 using System.Text;
41 using Mono.CSharp;
43 class MonoP {
44 static string assembly;
46 // very common namespaces, all in corlib
47 static readonly string [] v_common_ns = {
48 "System",
49 "System.Collections",
50 "System.Reflection",
51 "System.Text",
52 "System.IO"
55 static readonly string [] common_assemblies = {
56 "System.Xml.dll",
57 "System.Web.dll",
58 "gtk-sharp.dll",
59 "glib-sharp.dll"
62 static readonly string [] common_ns = {
63 "System.Xml",
64 "System.Web",
65 "Gtk",
66 "GLib"
69 static Type GetType (string tname, bool ignoreCase)
71 Type t;
72 if (assembly != null) {
73 Assembly a = GetAssembly (assembly, true);
74 t = a.GetType (tname, false, ignoreCase);
75 } else
76 t = Type.GetType (tname, false, ignoreCase);
78 return t;
81 static string SearchTypes (string name, ref Type retval, out int count)
83 StringBuilder sb = new StringBuilder ();
84 Type current = null;
85 count = 0;
87 string [] assemblies = GetKnownAssemblyNames ();
88 for (int i = 0; i < assemblies.Length; i++) {
89 Assembly a = GetAssembly (assemblies [i], false);
90 if (a == null)
91 continue;
93 Type [] types = a.GetTypes ();
94 for (int j = 0; j < types.Length; j++) {
95 Type t = types [j];
96 if (t.IsPublic == false)
97 continue;
99 if (t.Name == name || t.Name.ToLower ().IndexOf (name.ToLower ()) > 0) {
100 current = t;
101 count ++;
102 sb.Append (t.FullName + " from " + a.Location + "\n");
107 if (count == 0)
108 return null;
110 if (count == 1) {
111 retval = current;
112 return String.Empty;
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";
125 try {
126 p.Start ();
128 catch {
129 Console.WriteLine ("WARNING: gacutil could not be found.");
130 return new string[0];
133 string s;
134 ArrayList names = new ArrayList ();
135 StreamReader output = p.StandardOutput;
137 while ((s = output.ReadLine ()) != null)
138 names.Add (s);
140 p.WaitForExit ();
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
146 return retval;
149 static Assembly GetAssembly (string assembly, bool exit)
151 Assembly a = null;
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));
157 try {
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
165 else
166 a = LoadFromMonoPath (assembly);
167 } catch {
168 // ignore exception it gets handled below
171 // last try partial name
172 // this (apparently) is exception safe
173 if (a == null)
174 a = Assembly.LoadWithPartialName (assembly);
176 if (a == null && exit) {
177 Console.WriteLine ("Could not load {0}", MonoP.assembly);
178 Environment.Exit (1);
181 return a;
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);
194 return null;
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;
219 if (cca.IsCompliant)
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))
233 obsolete_count ++;
234 else
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);
247 return;
251 if (t.FullName.StartsWith (prefix)) {
252 Console.WriteLine (t.FullName);
256 foreach (string assm in common_assemblies) {
257 try {
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);
265 return;
269 if (t.FullName.StartsWith (prefix)) {
270 Console.WriteLine (t.FullName);
274 } catch {
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;
287 if (cca.IsCompliant)
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))
301 continue;
303 new Outline (t, sw, true, show_private, filter_obsolete).OutlineType ();
305 sw.Flush ();
308 static void Main (string [] args)
310 Options options = new Options ();
311 if (!options.ProcessArgs (args))
312 return;
314 if (options.AssemblyReference != null) {
315 assembly = options.AssemblyReference;
317 if (options.ShowAll){
318 ShowAll (assembly, options.FilterObsolete, options.ShowPrivate);
319 return;
320 } else {
321 if (options.Type == null) {
322 if (options.PrintRefs)
323 PrintRefs (assembly);
324 else
325 PrintTypes (assembly, options.ShowPrivate, options.FilterObsolete);
326 return;
331 string message = null;
332 string tname = options.Type;
333 Type t = null;
334 int count;
336 if (options.Search) {
337 string matches = SearchTypes (tname, ref t, out count);
339 if (count == 0)
340 goto notfound;
342 if (count == 1)
343 goto found;
345 if (count > 1){
346 Console.WriteLine ("Found " + count + " types that match:");
347 Console.WriteLine (matches);
348 return;
352 t = GetType (tname);
354 if (t == null) {
355 // Try some very common ones, dont load anything
356 foreach (string ns in v_common_ns) {
357 t = GetType (ns + "." + tname, true);
358 if (t != null)
359 goto found;
363 if (t == null) {
364 foreach (string assm in GetKnownAssemblyNames ()) {
365 try {
366 Assembly a = GetAssembly (assm, false);
367 t = a.GetType (tname, false, true);
368 if (t != null) {
369 message = String.Format ("{0} is included in the {1} assembly.",
370 t.FullName,
371 t.Assembly.GetName ().Name);
372 goto found;
374 foreach (string ns in common_ns) {
375 t = a.GetType (ns + "." + tname, false, true);
376 if (t != null) {
377 message = String.Format ("{0} is included in the {1} assembly.",
378 t.FullName,
379 t.Assembly.GetName ().Name);
380 goto found;
383 } catch {
388 notfound:
389 if (t == null) {
390 Console.WriteLine ("Could not find {0}", tname);
391 return;
393 found:
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 ();
399 sw.Flush ();
401 if (message != null)
402 Console.WriteLine (message);