2007-02-23 Nagappan A <anagappan@novell.com>
[mono.git] / mcs / tools / monop / monop.cs
index f7e20996b97cffbf2ea7d1dba9a5eff9ea5ed4d9..df046cd903e714f42bdd7ddaa9c785433b9a8ae0 100644 (file)
@@ -9,19 +9,38 @@
 // (C) 2004 John Luke
 //
 
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 
 using System;
-using System.Reflection;
-using System.Collections;
 using System.CodeDom.Compiler;
+using System.Collections;
+using System.Diagnostics;
 using System.IO;
+using System.Reflection;
+using System.Text;
 
 class MonoP {
        static string assembly;
-       static BindingFlags default_flags = 
-               BindingFlags.Instance |
-               BindingFlags.Static |
-               BindingFlags.Public;
        
        // very common namespaces, all in corlib
        static readonly string [] v_common_ns = {
@@ -52,17 +71,88 @@ class MonoP {
                if (assembly != null) {
                        Assembly a = GetAssembly (assembly, true);
                        t = a.GetType (tname, false, ignoreCase);
-               } else {
+               } else 
                        t = Type.GetType (tname, false, ignoreCase);
-               }
 
                return t;
        }
+       
+       static string SearchTypes (string name, ref Type retval, out int count)
+       {
+               StringBuilder sb = new StringBuilder ();
+               Type current = null;
+               count = 0;
+
+               string [] assemblies = GetKnownAssemblyNames ();
+               for (int i = 0; i < assemblies.Length; i++) {
+                       Assembly a = GetAssembly (assemblies [i], false);
+                       if (a == null)
+                               continue;
+
+                       Type [] types = a.GetTypes ();
+                       for (int j = 0; j < types.Length; j++) {
+                               Type t = types [j];
+                               if (t.IsPublic == false)
+                                       continue;
+                               
+                               if (t.Name == name || t.Name.ToLower ().IndexOf (name.ToLower ()) > 0) {
+                                       current = t;
+                                       count ++;
+                                       sb.Append (t.FullName + " from " + a.Location + "\n");
+                               }
+                       }
+               }
+
+               if (count == 0) 
+                       return null;
+
+               if (count == 1) {
+                       retval = current;
+                       return String.Empty;
+               }
+               
+               return sb.ToString ();
+       }
+
+       static string [] GetKnownAssemblyNames ()
+       {
+               Process p = new Process ();
+               p.StartInfo.UseShellExecute = false;
+               p.StartInfo.RedirectStandardOutput = true;
+               p.StartInfo.FileName = "gacutil";
+               p.StartInfo.Arguments = "-l";
+               try {
+                       p.Start ();
+               }
+               catch {
+                       Console.WriteLine ("WARNING: gacutil could not be found.");
+                       return new string[0];
+               }
+
+               string s;
+               ArrayList names = new ArrayList ();
+               StreamReader output = p.StandardOutput;
+
+               while ((s = output.ReadLine ()) != null)
+                       names.Add (s);
+
+               p.WaitForExit ();
+               
+               int length = names.Count - 1;
+               string [] retval = new string [length];
+               retval [0] = typeof (Object).Assembly.FullName;         
+               names.CopyTo (1, retval, 1, length - 1); // skip the first and last line
+               return retval;
+       }
 
        static Assembly GetAssembly (string assembly, bool exit)
        {
                Assembly a = null;
 
+               // if -r:~/foo.dll syntax is used the shell misses it
+               if (assembly.StartsWith ("~/"))
+                       assembly = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), assembly.Substring (2));
+
                try {
                        // if it exists try to use LoadFrom
                        if (File.Exists (assembly))
@@ -95,8 +185,7 @@ class MonoP {
                // ; on win32, : everywhere else
                char sep = (Path.DirectorySeparatorChar == '/' ? ':' : ';');
                string[] paths = Environment.GetEnvironmentVariable ("MONO_PATH").Split (sep);
-               foreach (string path in paths)
-               {       
+               foreach (string path in paths) {        
                        string apath = Path.Combine (path, assembly);
                        if (File.Exists (apath))
                                return Assembly.LoadFrom (apath);       
@@ -108,27 +197,47 @@ class MonoP {
        {
                return GetType (tname, false);
        }
-       
-       static void PrintTypes (string assembly)
+
+       static void PrintRefs (string assembly)
+       {
+               Assembly a = GetAssembly (assembly, true);
+               foreach (AssemblyName an in a.GetReferencedAssemblies ())
+                       Console.WriteLine (an);
+       }
+
+       static void PrintTypes (string assembly, bool show_private, bool filter_obsolete)
        {
                Assembly a = GetAssembly (assembly, true);
 
                Console.WriteLine ();
                Console.WriteLine ("Assembly Information:");
 
+               object[] cls = a.GetCustomAttributes (typeof (CLSCompliantAttribute), false);
+               if (cls.Length > 0) {
+                       CLSCompliantAttribute cca = cls[0] as CLSCompliantAttribute;
+                       if (cca.IsCompliant)
+                               Console.WriteLine ("[CLSCompliant]");
+               }
+
                foreach (string ai in a.ToString ().Split (','))
                        Console.WriteLine (ai.Trim ());
-
+                       
                Console.WriteLine ();
-               Type [] types = a.GetExportedTypes ();
+               Type [] types = show_private ? a.GetTypes () : a.GetExportedTypes ();
+               Array.Sort (types, new TypeSorter ());
 
-               foreach (Type t in types)
-                       Console.WriteLine (t.FullName);
+               int obsolete_count = 0;
+               foreach (Type t in types) {
+                       if (filter_obsolete && t.IsDefined (typeof (ObsoleteAttribute), false))
+                               obsolete_count ++;
+                       else
+                               Console.WriteLine (t.FullName);
+               }
 
-               Console.WriteLine ("\nTotal: {0} types.", types.Length);
+               Console.WriteLine ("\nTotal: {0} types.", types.Length - obsolete_count);
        }
        
-       static void Completion (string prefix)
+       internal static void Completion (string prefix)
        {
                foreach (Type t in typeof (object).Assembly.GetExportedTypes ()) {
                        if (t.Name.StartsWith (prefix)) {
@@ -167,68 +276,46 @@ class MonoP {
                
        }
 
-       static void PrintUsage ()
-       {
-               Console.WriteLine ("Usage is: monop [option] [-c] [-r:Assembly] [class-name]");
-       }
-
-       static void PrintHelp ()
-       {
-               PrintUsage ();
-               Console.WriteLine ("");
-               Console.WriteLine ("options:");
-               Console.WriteLine ("\t--declared-only,-d\tOnly show members declared in the Type");
-               Console.WriteLine ("\t--help,-h\t\tShow this information");
-               Console.WriteLine ("\t--private,-p\t\tShow private members");
-       }
-       
        static void Main (string [] args)
        {
-               if (args.Length < 1) {
-                       PrintUsage ();
-                       return;
-               }
-
-               if (args.Length == 1 && (args[0] == "--help" || args[0] == "-h"))
-               {
-                       PrintHelp ();
+               Options options = new Options ();
+               if (!options.ProcessArgs (args))
                        return;
-
-               }
                
-               int i = 0;
-               if (args [0].StartsWith ("-r:") || args [0].StartsWith ("/r:")){
-                       i++;
-                       assembly = args [0].Substring (3);
+               if (options.AssemblyReference != null) {
+                       assembly = options.AssemblyReference;
                        
-                       if (args.Length == 1) {
-                               PrintTypes (assembly);
+                       if (options.Type == null) {
+                               if (options.PrintRefs)
+                                       PrintRefs (assembly);
+                               else
+                                       PrintTypes (assembly, options.ShowPrivate, options.FilterObsolete);
                                return;
                        }
                }
-               
-               if (args [0] == "-c") {
-                       Completion (args [1]);
-                       return;
-               }
 
-               if (args [i] == "--private" || args [i] == "-p") {
-                               default_flags |= BindingFlags.NonPublic;
-                               i++;
-               }
+               string message = null;
+               string tname = options.Type;
+               Type t = null;
+               int count;
 
-               if (args [i] == "--declared-only" || args [i] == "-d") {
-                               default_flags |= BindingFlags.DeclaredOnly;
-                               i++;
-               }
+               if (options.Search) {
+                       string matches = SearchTypes (tname, ref t, out count);
 
-               if (args.Length < i + 1) {
-                       PrintUsage ();
-                       return;
-               }
+                       if (count == 0)
+                               goto notfound;
 
-               string tname = args [i];
-               Type t = GetType (tname);
+                       if (count == 1)
+                               goto found;
+                       
+                       if (count > 1){
+                               Console.WriteLine ("Found " + count + " types that match:");
+                               Console.WriteLine (matches);
+                               return;
+                       }
+               }
+                       
+               t = GetType (tname);
 
                if (t == null) {
                        // Try some very common ones, dont load anything
@@ -240,16 +327,22 @@ class MonoP {
                }
 
                if (t == null) {
-                       foreach (string assm in common_assemblies) {
+                       foreach (string assm in GetKnownAssemblyNames ()) {
                                try {
                                        Assembly a = GetAssembly (assm, false);
                                        t = a.GetType (tname, false, true);
-                                       if (t != null)
+                                       if (t != null) {
+                                               message = String.Format ("{0} is included in the {1} assembly.",
+                                                               t.FullName, 
+                                                               t.Assembly.GetName ().Name);
                                                goto found;
+                                       }
                                        foreach (string ns in common_ns) {
                                                t = a.GetType (ns + "." + tname, false, true);
                                                if (t != null) {
-                                                       Console.WriteLine ("(using class from {0})", ns);
+                                                       message = String.Format ("{0} is included in the {1} assembly.",
+                                                                       t.FullName, 
+                                                                       t.Assembly.GetName ().Name);
                                                        goto found;
                                                }
                                        }
@@ -257,7 +350,8 @@ class MonoP {
                                }
                        }
                }
-               
+
+       notfound:
                if (t == null) {
                        Console.WriteLine ("Could not find {0}", tname);
                        return;
@@ -266,9 +360,12 @@ class MonoP {
                //
                // This gets us nice buffering
                //
-               StreamWriter sw = new StreamWriter (Console.OpenStandardOutput (), Console.Out.Encoding);
-               new Outline (t, sw).OutlineType (default_flags);
+               StreamWriter sw = new StreamWriter (Console.OpenStandardOutput (), Console.Out.Encoding);                               
+               new Outline (t, sw, options).OutlineType ();
                sw.Flush ();
+
+               if (message != null)
+                       Console.WriteLine (message);
        }
 }