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;
44 static BindingFlags default_flags =
45 BindingFlags.Instance |
49 // very common namespaces, all in corlib
50 static readonly string [] v_common_ns = {
58 static readonly string [] common_assemblies = {
65 static readonly string [] common_ns = {
72 static Type GetType (string tname, bool ignoreCase)
75 if (assembly != null) {
76 Assembly a = GetAssembly (assembly, true);
77 t = a.GetType (tname, false, ignoreCase);
79 t = Type.GetType (tname, false, ignoreCase);
84 static string SearchTypes (string name)
86 StringBuilder sb = new StringBuilder ();
88 foreach (string asm in GetKnownAssemblyNames ()) {
89 Assembly a = GetAssembly (asm, false);
94 foreach (Type t in a.GetTypes ()) {
96 sb.Append (t.FullName + " from " + a.Location + "\n");
98 if (t.Name.ToLower ().IndexOf (name.ToLower ()) > 0)
99 sb.Append (t.FullName + " from " + a.Location + "\n");
106 return sb.ToString ();
109 static string [] GetKnownAssemblyNames ()
111 Process p = new Process ();
112 p.StartInfo.UseShellExecute = false;
113 p.StartInfo.RedirectStandardOutput = true;
114 p.StartInfo.FileName = "gacutil";
115 p.StartInfo.Arguments = "-l";
119 ArrayList names = new ArrayList ();
120 StreamReader output = p.StandardOutput;
122 while ((s = output.ReadLine ()) != null)
127 int length = names.Count - 1;
128 string [] retval = new string [length];
129 retval [0] = typeof (Object).Assembly.FullName;
130 names.CopyTo (1, retval, 1, length - 1); // skip the first and last line
134 static Assembly GetAssembly (string assembly, bool exit)
138 // if -r:~/foo.dll syntax is used the shell misses it
139 if (assembly.StartsWith ("~/"))
140 assembly = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), assembly.Substring (2));
143 // if it exists try to use LoadFrom
144 if (File.Exists (assembly))
145 a = Assembly.LoadFrom (assembly);
146 // if it looks like a fullname try that
147 else if (assembly.Split (',').Length == 4)
148 a = Assembly.Load (assembly);
149 // see if MONO_PATH has it
151 a = LoadFromMonoPath (assembly);
153 // ignore exception it gets handled below
156 // last try partial name
157 // this (apparently) is exception safe
159 a = Assembly.LoadWithPartialName (assembly);
161 if (a == null && exit) {
162 Console.WriteLine ("Could not load {0}", MonoP.assembly);
163 Environment.Exit (1);
169 static Assembly LoadFromMonoPath (string assembly)
171 // ; on win32, : everywhere else
172 char sep = (Path.DirectorySeparatorChar == '/' ? ':' : ';');
173 string[] paths = Environment.GetEnvironmentVariable ("MONO_PATH").Split (sep);
174 foreach (string path in paths) {
175 string apath = Path.Combine (path, assembly);
176 if (File.Exists (apath))
177 return Assembly.LoadFrom (apath);
182 static Type GetType (string tname)
184 return GetType (tname, false);
187 static void PrintTypes (string assembly)
189 Assembly a = GetAssembly (assembly, true);
191 Console.WriteLine ();
192 Console.WriteLine ("Assembly Information:");
194 object[] cls = a.GetCustomAttributes (typeof (CLSCompliantAttribute), false);
195 if (cls.Length > 0) {
196 CLSCompliantAttribute cca = cls[0] as CLSCompliantAttribute;
198 Console.WriteLine ("[CLSCompliant]");
201 foreach (string ai in a.ToString ().Split (','))
202 Console.WriteLine (ai.Trim ());
204 Console.WriteLine ();
205 Type [] types = a.GetExportedTypes ();
206 Array.Sort (types, new TypeSorter ());
208 foreach (Type t in types)
209 Console.WriteLine (t.FullName);
211 Console.WriteLine ("\nTotal: {0} types.", types.Length);
214 static void Completion (string prefix)
216 foreach (Type t in typeof (object).Assembly.GetExportedTypes ()) {
217 if (t.Name.StartsWith (prefix)) {
218 if (Array.IndexOf (v_common_ns, t.Namespace) != -1) {
219 Console.WriteLine (t.Name);
224 if (t.FullName.StartsWith (prefix)) {
225 Console.WriteLine (t.FullName);
229 foreach (string assm in common_assemblies) {
232 Assembly a = GetAssembly (assm, true);
233 foreach (Type t in a.GetExportedTypes ()) {
235 if (t.Name.StartsWith (prefix)) {
236 if (Array.IndexOf (common_ns, t.Namespace) != -1) {
237 Console.WriteLine (t.Name);
242 if (t.FullName.StartsWith (prefix)) {
243 Console.WriteLine (t.FullName);
253 static void PrintUsage ()
255 Console.WriteLine ("Usage is: monop [option] [-c] [-r:Assembly] [class-name]");
258 static void PrintHelp ()
261 Console.WriteLine ("");
262 Console.WriteLine ("options:");
263 Console.WriteLine ("\t--declared-only,-d\tOnly show members declared in the Type");
264 Console.WriteLine ("\t--help,-h\t\tShow this information");
265 Console.WriteLine ("\t--private,-p\t\tShow private members");
266 Console.WriteLine ("\t--search,-s,-k\t\tSearch through all known namespaces");
269 static void Main (string [] args)
271 if (args.Length < 1) {
276 if (args.Length == 1 && (args[0] == "--help" || args[0] == "-h"))
284 if (args [0].StartsWith ("-r:") || args [0].StartsWith ("/r:")){
286 assembly = args [0].Substring (3);
288 if (args.Length == 1) {
289 PrintTypes (assembly);
294 if (args [0] == "-c") {
295 Completion (args [1]);
299 if (args [i] == "--private" || args [i] == "-p") {
300 default_flags |= BindingFlags.NonPublic;
304 if (args [i] == "--declared-only" || args [i] == "-d") {
305 default_flags |= BindingFlags.DeclaredOnly;
310 if (args [i] == "--search" || args [i] == "-s" || args [i] == "-k") {
315 if (args.Length < i + 1) {
320 string message = null;
321 string tname = args [i];
325 string matches = SearchTypes (tname);
327 if (matches != null) {
328 Console.WriteLine ("The follow types match:");
329 Console.WriteLine (matches);
338 // Try some very common ones, dont load anything
339 foreach (string ns in v_common_ns) {
340 t = GetType (ns + "." + tname, true);
347 foreach (string assm in GetKnownAssemblyNames ()) {
349 Assembly a = GetAssembly (assm, false);
350 t = a.GetType (tname, false, true);
352 message = String.Format ("{0} is included in the {1} assembly.",
354 t.Assembly.GetName ().Name);
357 foreach (string ns in common_ns) {
358 t = a.GetType (ns + "." + tname, false, true);
360 message = String.Format ("{0} is included in the {1} assembly.",
362 t.Assembly.GetName ().Name);
373 Console.WriteLine ("Could not find {0}", tname);
378 // This gets us nice buffering
380 StreamWriter sw = new StreamWriter (Console.OpenStandardOutput (), Console.Out.Encoding);
381 new Outline (t, sw).OutlineType (default_flags);
385 Console.WriteLine (message);