예제 #1
0
        internal CodegenUnit(AssemblyName asmName)
        {
            var fileName = asmName.Name + ".dll";
            var pdbName  = asmName + ".pdb";

            // so that we can run multiple tests at once and not lose the info
            if (UnitTest.CurrentTest != null)
            {
                fileName = asmName + ", " + UnitTest.PersistentId + ".dll";
                pdbName  = asmName + ".pdb";
            }

#if TRACE
            try
            {
                _asm = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
                _mod = _asm.DefineDynamicModule(fileName, true);

                // Mark generated code as debuggable.
                // See http://blogs.msdn.com/jmstall/archive/2005/02/03/366429.aspx for explanation.
                var daCtor    = typeof(DebuggableAttribute).GetConstructor(new [] { typeof(DebuggableAttribute.DebuggingModes) });
                var daBuilder = new CustomAttributeBuilder(daCtor, new object[] {
                    DebuggableAttribute.DebuggingModes.DisableOptimizations |
                    DebuggableAttribute.DebuggingModes.Default
                });
                _asm.SetCustomAttribute(daBuilder);

                // Mark generated code as non-user code.
                // See http://stackoverflow.com/questions/1423733/how-to-tell-if-a-net-assembly-is-dynamic for explanation.
                var cgCtor    = typeof(CompilerGeneratedAttribute).GetConstructor(Type.EmptyTypes);
                var cgBuilder = new CustomAttributeBuilder(cgCtor, new object [] {});
                _asm.SetCustomAttribute(cgBuilder);

                var    hasAlreadyBeenDumped = false;
                Action dumpAssembly         = () =>
                {
                    if (!hasAlreadyBeenDumped && _asm != null)
                    {
                        try
                        {
                            // todo. before dumping make sure that all types are completed or else the dump will simply crash
                            // this is a complex task, but it needs to be resolved for generic case

                            _asm.Save(fileName);
                        }
                        catch (Exception ex)
                        {
                            var trace = String.Format("Codegen unit '{0}' has failed to dump the asm:{1}{2}",
                                                      asmName.FullName, Environment.NewLine, ex);
                            Log.WriteLine(trace);

                            SafetyTools.SafeDo(() =>
                            {
                                File.WriteAllText(fileName, trace);
                                File.Delete(pdbName);
                            });
                        }
                        finally
                        {
                            hasAlreadyBeenDumped = true;
                        }
                    }
                };
                _dumpAssembly = dumpAssembly;

                // do not use DomainUnload here because it never gets fired for default domain
                // however, we need not to neglect because R#'s unit-test runner never exits process
                AppDomain.CurrentDomain.DomainUnload       += (o, e) => dumpAssembly();
                AppDomain.CurrentDomain.ProcessExit        += (o, e) => dumpAssembly();
                AppDomain.CurrentDomain.UnhandledException += (o, e) => dumpAssembly();
            }
            catch (Exception ex)
            {
                var trace = String.Format("Codegen unit '{0}' has failed to initialize:{1}{2}",
                                          asmName.FullName, Environment.NewLine, ex);
                Log.WriteLine(trace);

                SafetyTools.SafeDo(() =>
                {
                    File.WriteAllText(fileName, trace);
                    File.Delete(pdbName);
                });

                throw;
            }
#else
            _asm = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run);
            _asm.SetCustomAttribute(new CustomAttributeBuilder(typeof(CompilerGeneratedAttribute).GetConstructor(Type.EmptyTypes), new object[] { }));
            _mod = _asm.DefineDynamicModule(fileName, false);
#endif
        }
예제 #2
0
        public static void Help(Type t_cfg)
        {
            var asm = t_cfg == null ? null : t_cfg.Assembly;

            if (t_cfg != null)
            {
                var @params = t_cfg.GetProperties(BF.AllInstance)
                              .Where(p => p.HasAttr <ParamAttribute>()).OrderBy(p => p.Attr <ParamAttribute>().Priority).ToReadOnly();

                var cfg_name = t_cfg.Attr <ConfigAttribute>().Name ?? asm.GetName().Name;
                var s_syntax = String.Format("Syntax: {0}", cfg_name);
                foreach (var p in @params)
                {
                    var is_optional = t_cfg.GetProperty("Default" + p.Name, BF.AllStatic) != null;
                    var alias       = p.Attr <ParamAttribute>().Aliases.First();
                    s_syntax += String.Format(" {0}-{1}:{2}{3}", is_optional ? "[" : "", alias, p.Name, is_optional ? "]" : "");
                }
                s_syntax += " [/verbose]";
                Console.WriteLine(s_syntax);

                var shortcuts = t_cfg.Attrs <ShortcutAttribute>().OrderBy(shortcut => shortcut.Priority);
                if (shortcuts.IsNotEmpty())
                {
                    Console.EnsureBlankLine();
                    if (shortcuts.Count() == 1)
                    {
                        Console.WriteLine("Shortcut: ");
                    }
                    else
                    {
                        Console.WriteLine("Shortcuts:"); Console.Write("    ");
                    }

                    shortcuts.ForEach((shortcut, i) =>
                    {
                        shortcut.Description.AssertNull();
                        Console.WriteLine(cfg_name + (shortcut.Schema.IsNullOrEmpty() ? "" : (" " + shortcut.Schema)));
                        if (i != shortcuts.Count() - 1)
                        {
                            Console.Write("    ");
                        }
                    });
                }

                Console.EnsureBlankLine();
                Console.WriteLine("Parameters:");
                var max_name = @params.MaxOrDefault(p => p.Name.Length);
                max_name = Math.Max("/verbose".Length, max_name);
                var feed     = new String(' ', 4 + 1 + max_name + 2);
                var max_desc = 80 - feed.Length;
                (max_desc > 0).AssertTrue();
                Action <String, String> write_name_desc = (name, desc) =>
                {
                    Console.Write(String.Format("    {0}{1}{2}  ",
                                                name.StartsWith("/") ? "" : "%",
                                                name.PadRight(max_name),
                                                name.StartsWith("/") ? " " : ""));

                    var num_lines = (int)Math.Ceiling(1.0 * desc.Length / max_desc);
                    for (var i = 0; i < num_lines; ++i)
                    {
                        if (i != 0)
                        {
                            Console.Write(feed);
                        }
                        var line = desc.Substring(i * max_desc, Math.Min(max_desc, desc.Length - i * max_desc));
                        Console.WriteLine(line);
                    }
                };
                foreach (var p in @params)
                {
                    var desc = p.Attr <ParamAttribute>().Description ?? String.Empty;

                    var p_default = t_cfg.GetProperty("Default" + p.Name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                    if (p_default != null)
                    {
                        var default_value = p_default.GetValue(null, null);
                        if (default_value != null)
                        {
                            var s_default_value = default_value == null ? "null" : default_value.ToString();
                            if (default_value is DirectoryInfo)
                            {
                                var dir = default_value as DirectoryInfo;
                                if (dir.FullName == Environment.CurrentDirectory)
                                {
                                    s_default_value = "current dir";
                                }
                            }

                            var s_default = String.Format("Defaults to {0}.", s_default_value);
                            if (!String.IsNullOrEmpty(desc))
                            {
                                if (!desc.EndsWith("."))
                                {
                                    desc += ".";
                                }
                                desc += " ";
                            }
                            desc += s_default;
                        }
                    }

                    if (!String.IsNullOrEmpty(desc))
                    {
                        write_name_desc(p.Name, desc);
                    }
                }
                write_name_desc("/verbose", "Turns verbose tracing on, useful for debugging.");
            }
        }