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;
43 static string assembly;
45 // very common namespaces, all in corlib
46 static readonly string [] v_common_ns = {
54 static readonly string [] common_assemblies = {
61 static readonly string [] common_ns = {
68 static Type GetType (string tname, bool ignoreCase)
71 if (assembly != null) {
72 Assembly a = GetAssembly (assembly, true);
73 t = a.GetType (tname, false, ignoreCase);
75 t = Type.GetType (tname, false, ignoreCase);
80 static string SearchTypes (string name, ref Type retval, out int count)
82 StringBuilder sb = new StringBuilder ();
86 string [] assemblies = GetKnownAssemblyNames ();
87 for (int i = 0; i < assemblies.Length; i++) {
88 Assembly a = GetAssembly (assemblies [i], false);
92 Type [] types = a.GetTypes ();
93 for (int j = 0; j < types.Length; j++) {
95 if (t.IsPublic == false)
98 if (t.Name == name || t.Name.ToLower ().IndexOf (name.ToLower ()) > 0) {
101 sb.Append (t.FullName + " from " + a.Location + "\n");
114 return sb.ToString ();
117 static string [] GetKnownAssemblyNames ()
119 Process p = new Process ();
120 p.StartInfo.UseShellExecute = false;
121 p.StartInfo.RedirectStandardOutput = true;
122 p.StartInfo.FileName = "gacutil";
123 p.StartInfo.Arguments = "-l";
128 Console.WriteLine ("WARNING: gacutil could not be found.");
129 return new string[0];
133 ArrayList names = new ArrayList ();
134 StreamReader output = p.StandardOutput;
136 while ((s = output.ReadLine ()) != null)
141 int length = names.Count - 1;
142 string [] retval = new string [length];
143 retval [0] = typeof (Object).Assembly.FullName;
144 names.CopyTo (1, retval, 1, length - 1); // skip the first and last line
148 static Assembly GetAssembly (string assembly, bool exit)
152 // if -r:~/foo.dll syntax is used the shell misses it
153 if (assembly.StartsWith ("~/"))
154 assembly = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), assembly.Substring (2));
157 // if it exists try to use LoadFrom
158 if (File.Exists (assembly))
159 a = Assembly.LoadFrom (assembly);
160 // if it looks like a fullname try that
161 else if (assembly.Split (',').Length == 4)
162 a = Assembly.Load (assembly);
163 // see if MONO_PATH has it
165 a = LoadFromMonoPath (assembly);
167 // ignore exception it gets handled below
170 // last try partial name
171 // this (apparently) is exception safe
173 a = Assembly.LoadWithPartialName (assembly);
175 if (a == null && exit) {
176 Console.WriteLine ("Could not load {0}", MonoP.assembly);
177 Environment.Exit (1);
183 static Assembly LoadFromMonoPath (string assembly)
185 // ; on win32, : everywhere else
186 char sep = (Path.DirectorySeparatorChar == '/' ? ':' : ';');
187 string[] paths = Environment.GetEnvironmentVariable ("MONO_PATH").Split (sep);
188 foreach (string path in paths) {
189 string apath = Path.Combine (path, assembly);
190 if (File.Exists (apath))
191 return Assembly.LoadFrom (apath);
196 static Type GetType (string tname)
198 return GetType (tname, false);
201 static void PrintRefs (string assembly)
203 Assembly a = GetAssembly (assembly, true);
204 foreach (AssemblyName an in a.GetReferencedAssemblies ())
205 Console.WriteLine (an);
208 static void PrintTypes (string assembly, bool show_private, bool filter_obsolete)
210 Assembly a = GetAssembly (assembly, true);
212 Console.WriteLine ();
213 Console.WriteLine ("Assembly Information:");
215 object[] cls = a.GetCustomAttributes (typeof (CLSCompliantAttribute), false);
216 if (cls.Length > 0) {
217 CLSCompliantAttribute cca = cls[0] as CLSCompliantAttribute;
219 Console.WriteLine ("[CLSCompliant]");
222 foreach (string ai in a.ToString ().Split (','))
223 Console.WriteLine (ai.Trim ());
225 Console.WriteLine ();
226 Type [] types = show_private ? a.GetTypes () : a.GetExportedTypes ();
227 Array.Sort (types, new TypeSorter ());
229 int obsolete_count = 0;
230 foreach (Type t in types) {
231 if (filter_obsolete && t.IsDefined (typeof (ObsoleteAttribute), false))
234 Console.WriteLine (t.FullName);
237 Console.WriteLine ("\nTotal: {0} types.", types.Length - obsolete_count);
240 internal static void Completion (string prefix)
242 foreach (Type t in typeof (object).Assembly.GetExportedTypes ()) {
243 if (t.Name.StartsWith (prefix)) {
244 if (Array.IndexOf (v_common_ns, t.Namespace) != -1) {
245 Console.WriteLine (t.Name);
250 if (t.FullName.StartsWith (prefix)) {
251 Console.WriteLine (t.FullName);
255 foreach (string assm in common_assemblies) {
258 Assembly a = GetAssembly (assm, true);
259 foreach (Type t in a.GetExportedTypes ()) {
261 if (t.Name.StartsWith (prefix)) {
262 if (Array.IndexOf (common_ns, t.Namespace) != -1) {
263 Console.WriteLine (t.Name);
268 if (t.FullName.StartsWith (prefix)) {
269 Console.WriteLine (t.FullName);
279 static void Main (string [] args)
281 Options options = new Options ();
282 if (!options.ProcessArgs (args))
285 if (options.AssemblyReference != null) {
286 assembly = options.AssemblyReference;
288 if (options.Type == null) {
289 if (options.PrintRefs)
290 PrintRefs (assembly);
292 PrintTypes (assembly, options.ShowPrivate, options.FilterObsolete);
297 string message = null;
298 string tname = options.Type;
302 if (options.Search) {
303 string matches = SearchTypes (tname, ref t, out count);
312 Console.WriteLine ("Found " + count + " types that match:");
313 Console.WriteLine (matches);
321 // Try some very common ones, dont load anything
322 foreach (string ns in v_common_ns) {
323 t = GetType (ns + "." + tname, true);
330 foreach (string assm in GetKnownAssemblyNames ()) {
332 Assembly a = GetAssembly (assm, false);
333 t = a.GetType (tname, false, true);
335 message = String.Format ("{0} is included in the {1} assembly.",
337 t.Assembly.GetName ().Name);
340 foreach (string ns in common_ns) {
341 t = a.GetType (ns + "." + tname, false, true);
343 message = String.Format ("{0} is included in the {1} assembly.",
345 t.Assembly.GetName ().Name);
356 Console.WriteLine ("Could not find {0}", tname);
361 // This gets us nice buffering
363 StreamWriter sw = new StreamWriter (Console.OpenStandardOutput (), Console.Out.Encoding);
364 new Outline (t, sw, options).OutlineType ();
368 Console.WriteLine (message);