Exemplo n.º 1
0
        /// <summary>
        /// Main program entry point (MSBuild task)
        /// </summary>
        /// <param name="args">Command line arguments</param>
        /// <returns>Zero on success or non-zero on failure</returns>
        public static int MainEntryPoint(string[] args)
        {
            string path, version, framework = null, assemblyPath, typeName;

            // Write banner
            ConsoleApplication.WriteBanner();

            // Specify options
            OptionCollection options = new OptionCollection
            {
                new SwitchOption("?", "Show this help page."),
                new StringOption("out", "Specify an output file. If unspecified, output goes to the console.", "outputFilePath"),
                new StringOption("config", "Specify a configuration file. If unspecified, MRefBuilder.config is used", "configFilePath"),
                new ListOption("dep", "Specify assemblies to load for dependencies.", "dependencyAssembly")
            };

            // Process options
            ParseArgumentsResult results = options.ParseArguments(args);

            if (results.Options["?"].IsPresent)
            {
                Console.WriteLine("MRefBuilder [options] assemblies");
                options.WriteOptionSummary(Console.Out);
                return(1);
            }

            // Check for invalid options
            if (!results.Success)
            {
                results.WriteParseErrors(Console.Out);
                return(1);
            }

            // Check for missing or extra assembly directories
            if (results.UnusedArguments.Count < 1)
            {
                Console.WriteLine("Specify at least one assembly to reflect.");
                return(1);
            }

            // Load the configuration file
            XPathDocument  config;
            XPathNavigator configNav;
            string         configDirectory = ComponentUtilities.ToolsFolder,
                           configFile = Path.Combine(ComponentUtilities.ToolsFolder, "MRefBuilder.config");

            if (results.Options["config"].IsPresent)
            {
                configFile      = (string)results.Options["config"].Value;
                configDirectory = Path.GetDirectoryName(configFile);
            }

            try
            {
                config    = new XPathDocument(configFile);
                configNav = config.CreateNavigator();
            }
            catch (IOException e)
            {
                ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while attempting to read " +
                                                "the configuration file '{0}'. The error message is: {1}", configFile, e.Message);
                return(1);
            }
            catch (UnauthorizedAccessException e)
            {
                ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while attempting to read " +
                                                "the configuration file '{0}'. The error message is: {1}", configFile, e.Message);
                return(1);
            }
            catch (XmlException e)
            {
                ConsoleApplication.WriteMessage(LogLevel.Error, "The configuration file '{0}' is not " +
                                                "well-formed. The error message is: {1}", configFile, e.Message);
                return(1);
            }

            // Adjust the target platform
            var platformNode = configNav.SelectSingleNode("/configuration/dduetools/platform");

            if (platformNode == null)
            {
                ConsoleApplication.WriteMessage(LogLevel.Error, "A platform element is required to define the " +
                                                "framework type and version to use.");
                return(1);
            }

            // !EFW - Use the framework definition file to load core framework assembly reference information
            version   = platformNode.GetAttribute("version", String.Empty);
            framework = platformNode.GetAttribute("framework", String.Empty);

            // Get component locations used to find additional reflection data definition files
            List <string> componentFolders = new List <string>();
            var           locations        = configNav.SelectSingleNode("/configuration/dduetools/componentLocations");

            if (locations != null)
            {
                foreach (XPathNavigator folder in locations.Select("location/@folder"))
                {
                    if (!String.IsNullOrWhiteSpace(folder.Value) && Directory.Exists(folder.Value))
                    {
                        componentFolders.Add(folder.Value);
                    }
                }
            }

            // Get the dependencies
            string[] dependencies = Array.Empty <string>();

            if (results.Options["dep"].IsPresent)
            {
                dependencies = (string[])results.Options["dep"].Value;
            }

            if (!String.IsNullOrEmpty(framework) && !String.IsNullOrEmpty(version))
            {
                var coreNames = new HashSet <string>(new[] { "netstandard", "mscorlib", "System.Runtime" },
                                                     StringComparer.OrdinalIgnoreCase);

                var coreFrameworkAssemblies = results.UnusedArguments.Concat(dependencies).Where(d =>
                                                                                                 coreNames.Contains(Path.GetFileNameWithoutExtension(d)));

                TargetPlatform.SetFrameworkInformation(framework, version, componentFolders,
                                                       coreFrameworkAssemblies);
            }
            else
            {
                ConsoleApplication.WriteMessage(LogLevel.Error, "Unknown target framework version '{0} {1}'.",
                                                framework, version);
                return(1);
            }

            // Create an API member namer
            ApiNamer namer;

            // Apply a different naming method to assemblies using these frameworks
            if (framework == PlatformType.DotNetCore || framework == PlatformType.DotNetPortable ||
                framework == PlatformType.WindowsPhone || framework == PlatformType.WindowsPhoneApp)
            {
                namer = new WindowsStoreAndPhoneNamer();
            }
            else
            {
                namer = new OrcasNamer();
            }

            XPathNavigator namerNode = configNav.SelectSingleNode("/configuration/dduetools/namer");

            if (namerNode != null)
            {
                assemblyPath = namerNode.GetAttribute("assembly", String.Empty);
                typeName     = namerNode.GetAttribute("type", String.Empty);

                assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);

                if (!Path.IsPathRooted(assemblyPath))
                {
                    assemblyPath = Path.Combine(configDirectory, assemblyPath);
                }

                try
                {
                    Assembly assembly = Assembly.LoadFrom(assemblyPath);
                    namer = (ApiNamer)assembly.CreateInstance(typeName);

                    if (namer == null)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                                        "component assembly '{1}'.", typeName, assemblyPath);
                        return(1);
                    }
                }
                catch (IOException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                                    "attempting to load the component assembly '{0}'. The error message is: {1}",
                                                    assemblyPath, e.Message);
                    return(1);
                }
                catch (UnauthorizedAccessException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                                    "attempting to load the component assembly '{0}'. The error message is: {1}",
                                                    assemblyPath, e.Message);
                    return(1);
                }
                catch (BadImageFormatException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "The component assembly '{0}' is not a " +
                                                    "valid managed assembly.", assemblyPath);
                    return(1);
                }
                catch (TypeLoadException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                                    "component assembly '{1}'.", typeName, assemblyPath);
                    return(1);
                }
                catch (MissingMethodException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "No appropriate constructor exists for " +
                                                    "the type'{0}' in the component assembly '{1}'.", typeName, assemblyPath);
                    return(1);
                }
                catch (TargetInvocationException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while initializing the " +
                                                    "type '{0}' in the component assembly '{1}'. The error message and stack trace " +
                                                    "follows: {2}", typeName, assemblyPath, e.InnerException);
                    return(1);
                }
                catch (InvalidCastException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' in the component assembly " +
                                                    "'{1}' is not a component type.", typeName, assemblyPath);
                    return(1);
                }
            }

            // Create a resolver
            AssemblyResolver resolver     = new AssemblyResolver();
            XPathNavigator   resolverNode = configNav.SelectSingleNode("/configuration/dduetools/resolver");

            if (resolverNode != null)
            {
                assemblyPath = resolverNode.GetAttribute("assembly", String.Empty);
                typeName     = resolverNode.GetAttribute("type", String.Empty);

                assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);
                if (!Path.IsPathRooted(assemblyPath))
                {
                    assemblyPath = Path.Combine(configDirectory, assemblyPath);
                }

                try
                {
                    Assembly assembly = Assembly.LoadFrom(assemblyPath);
                    resolver = (AssemblyResolver)assembly.CreateInstance(typeName, false, BindingFlags.Public |
                                                                         BindingFlags.Instance, null, new object[1] {
                        resolverNode
                    }, null, null);

                    if (resolver == null)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                                        "component assembly '{1}'.", typeName, assemblyPath);
                        return(1);
                    }
                }
                catch (IOException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                                    "attempting to load the component assembly '{0}'. The error message is: {1}",
                                                    assemblyPath, e.Message);
                    return(1);
                }
                catch (UnauthorizedAccessException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                                    "attempting to load the component assembly '{0}'. The error message is: {1}",
                                                    assemblyPath, e.Message);
                    return(1);
                }
                catch (BadImageFormatException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "The component assembly '{0}' is not a " +
                                                    "valid managed assembly.", assemblyPath);
                    return(1);
                }
                catch (TypeLoadException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                                    "component assembly '{1}'.", typeName, assemblyPath);
                    return(1);
                }
                catch (MissingMethodException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "No appropriate constructor exists for " +
                                                    "the type'{0}' in the component assembly '{1}'.", typeName, assemblyPath);
                    return(1);
                }
                catch (TargetInvocationException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while initializing the " +
                                                    "type '{0}' in the component assembly '{1}'. The error message and stack trace " +
                                                    "follows: {2}", typeName, assemblyPath, e.InnerException);
                    return(1);
                }
                catch (InvalidCastException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' in the component assembly " +
                                                    "'{1}' is not a component type.", typeName, assemblyPath);
                    return(1);
                }
            }

            resolver.UnresolvedAssemblyReference += UnresolvedAssemblyReferenceHandler;

            // Get a text writer for output
            TextWriter output = Console.Out;

            if (results.Options["out"].IsPresent)
            {
                string file = (string)results.Options["out"].Value;

                try
                {
                    output = new StreamWriter(file, false, Encoding.UTF8);
                }
                catch (IOException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while attempting to " +
                                                    "create an output file. The error message is: {0}", e.Message);
                    return(1);
                }
                catch (UnauthorizedAccessException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while attempting to " +
                                                    "create an output file. The error message is: {0}", e.Message);
                    return(1);
                }
            }

            try
            {
                // Create a writer
                string sourceCodeBasePath = (string)configNav.Evaluate(
                    "string(/configuration/dduetools/sourceContext/@basePath)");
                bool warnOnMissingContext = false;

                if (!String.IsNullOrWhiteSpace(sourceCodeBasePath))
                {
                    warnOnMissingContext = (bool)configNav.Evaluate(
                        "boolean(/configuration/dduetools/sourceContext[@warnOnMissingSourceContext='true'])");
                }
                else
                {
                    ConsoleApplication.WriteMessage(LogLevel.Info, "No source code context base path " +
                                                    "specified.  Source context information is unavailable.");
                }

                ApiVisitor = new ManagedReflectionWriter(output, namer, resolver, sourceCodeBasePath,
                                                         warnOnMissingContext, new ApiFilter(configNav.SelectSingleNode("/configuration/dduetools")));

                // Register add-ins to the builder
                XPathNodeIterator addinNodes = configNav.Select("/configuration/dduetools/addins/addin");

                foreach (XPathNavigator addinNode in addinNodes)
                {
                    assemblyPath = addinNode.GetAttribute("assembly", String.Empty);
                    typeName     = addinNode.GetAttribute("type", String.Empty);

                    assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);

                    if (!Path.IsPathRooted(assemblyPath))
                    {
                        assemblyPath = Path.Combine(configDirectory, assemblyPath);
                    }

                    try
                    {
                        Assembly         assembly = Assembly.LoadFrom(assemblyPath);
                        MRefBuilderAddIn addin    = (MRefBuilderAddIn)assembly.CreateInstance(typeName, false,
                                                                                              BindingFlags.Public | BindingFlags.Instance, null,
                                                                                              new object[2] {
                            ApiVisitor, addinNode
                        }, null, null);

                        if (addin == null)
                        {
                            ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' was not found in " +
                                                            "the add-in assembly '{1}'.", typeName, assemblyPath);
                            return(1);
                        }
                    }
                    catch (IOException e)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                                        "attempting to load the add-in assembly '{0}'. The error message is: {1}",
                                                        assemblyPath, e.Message);
                        return(1);
                    }
                    catch (BadImageFormatException)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "The add-in assembly '{0}' is not a " +
                                                        "valid managed assembly.", assemblyPath);
                        return(1);
                    }
                    catch (TypeLoadException)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                                        "add-in assembly '{1}'.", typeName, assemblyPath);
                        return(1);
                    }
                    catch (MissingMethodException)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "No appropriate constructor exists " +
                                                        "for the type '{0}' in the add-in assembly '{1}'.", typeName, assemblyPath);
                        return(1);
                    }
                    catch (TargetInvocationException e)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while initializing " +
                                                        "the type '{0}' in the add-in assembly '{1}'. The error message and stack trace " +
                                                        "follows: {2}", typeName, assemblyPath, e.InnerException);
                        return(1);
                    }
                    catch (InvalidCastException)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' in the add-in " +
                                                        "assembly '{1}' is not an MRefBuilderAddIn type.", typeName, assemblyPath);
                        return(1);
                    }
                }

                // Load dependencies
                foreach (string dependency in dependencies)
                {
                    try
                    {
                        // Expand environment variables
                        path = Environment.ExpandEnvironmentVariables(dependency);

                        // If x86 but it didn't exist, assume it's a 32-bit system and change the name
                        if (path.IndexOf("%ProgramFiles(x86)%", StringComparison.Ordinal) != -1)
                        {
                            path = Environment.ExpandEnvironmentVariables(path.Replace("(x86)", String.Empty));
                        }

                        ApiVisitor.LoadAccessoryAssemblies(path);
                    }
                    catch (IOException e)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while loading " +
                                                        "dependency assemblies. The error message is: {0}", e.Message);
                        return(1);
                    }
                }

                // Parse the assemblies
                foreach (string dllPath in results.UnusedArguments.OrderBy(d =>
                                                                           d.IndexOf("System.Runtime.dll", StringComparison.OrdinalIgnoreCase) != -1 ? 0 :
                                                                           d.IndexOf("netstandard.dll", StringComparison.OrdinalIgnoreCase) != -1 ? 1 :
                                                                           d.IndexOf("mscorlib.dll", StringComparison.OrdinalIgnoreCase) != -1 ? 2 : 3))
                {
                    try
                    {
                        // Expand environment variables
                        path = Environment.ExpandEnvironmentVariables(dllPath);

                        // If x86 but it didn't exist, assume it's a 32-bit system and change the name
                        if (path.IndexOf("%ProgramFiles(x86)%", StringComparison.Ordinal) != -1)
                        {
                            path = Environment.ExpandEnvironmentVariables(path.Replace("(x86)", String.Empty));
                        }

                        ApiVisitor.LoadAssemblies(path);
                    }
                    catch (IOException e)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while loading " +
                                                        "assemblies for reflection. The error message is: {0}", e.Message);
                        return(1);
                    }
                }

                ConsoleApplication.WriteMessage(LogLevel.Info, "Loaded {0} assemblies for reflection and " +
                                                "{1} dependency assemblies.", ApiVisitor.Assemblies.Count(),
                                                ApiVisitor.AccessoryAssemblies.Count());

                ApiVisitor.VisitApis();

                if (ApiVisitor.Canceled)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "MRefBuilder task canceled");
                }
                else
                {
                    ConsoleApplication.WriteMessage(LogLevel.Info, "Wrote information on {0} namespaces, " +
                                                    "{1} types, and {2} members", ApiVisitor.NamespaceCount, ApiVisitor.TypeCount,
                                                    ApiVisitor.MemberCount);
                }
            }
            finally
            {
                if (ApiVisitor != null)
                {
                    ApiVisitor.Dispose();
                }

                if (results.Options["out"].IsPresent)
                {
                    output.Close();
                }
            }

            return((ApiVisitor != null && ApiVisitor.Canceled) ? 2 : 0);
        }
Exemplo n.º 2
0
        //=====================================================================

        /// <summary>
        /// Main program entry point
        /// </summary>
        /// <param name="args">Command line arguments</param>
        /// <returns>Zero on success or non-zero on failure</returns>
        public static int Main(string[] args)
        {
            string path, version, framework = null, assemblyPath, typeName;

            // Write banner
            ConsoleApplication.WriteBanner();

            // Specify options
            OptionCollection options = new OptionCollection();

            options.Add(new SwitchOption("?", "Show this help page."));
            options.Add(new StringOption("out", "Specify an output file. If unspecified, output goes to the " +
                                         "console.", "outputFilePath"));
            options.Add(new StringOption("config", "Specify a configuration file. If unspecified, " +
                                         "MRefBuilder.config is used", "configFilePath"));
            options.Add(new ListOption("dep", "Specify assemblies to load for dependencies.",
                                       "dependencyAssembly"));
            options.Add(new BooleanOption("internal", "Specify whether to document internal as well as " +
                                          "externally exposed APIs.  *** DEPRECATED:  Use the visibility settings in the MRefBuilder.config " +
                                          "file instead which provide finer grained control over the exposed API members."));

            // Process options
            ParseArgumentsResult results = options.ParseArguments(args);

            if (results.Options["?"].IsPresent)
            {
                Console.WriteLine("MRefBuilder [options] assemblies");
                options.WriteOptionSummary(Console.Out);
                return(1);
            }

            // Check for invalid options
            if (!results.Success)
            {
                results.WriteParseErrors(Console.Out);
                return(1);
            }

            // Check for missing or extra assembly directories
            if (results.UnusedArguments.Count < 1)
            {
                Console.WriteLine("Specify at least one assembly to reflect.");
                return(1);
            }

            // Load the configuration file
            XPathDocument config;
            string        configDirectory = ComponentUtilities.ToolsFolder,
                          configFile      = Path.Combine(ComponentUtilities.ToolsFolder, "MRefBuilder.config");

            if (results.Options["config"].IsPresent)
            {
                configFile      = (string)results.Options["config"].Value;
                configDirectory = Path.GetDirectoryName(configFile);
            }

            try
            {
                config = new XPathDocument(configFile);
            }
            catch (IOException e)
            {
                ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while attempting to read " +
                                                "the configuration file '{0}'. The error message is: {1}", configFile, e.Message);
                return(1);
            }
            catch (UnauthorizedAccessException e)
            {
                ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while attempting to read " +
                                                "the configuration file '{0}'. The error message is: {1}", configFile, e.Message);
                return(1);
            }
            catch (XmlException e)
            {
                ConsoleApplication.WriteMessage(LogLevel.Error, "The configuration file '{0}' is not " +
                                                "well-formed. The error message is: {1}", configFile, e.Message);
                return(1);
            }

            // Adjust the target platform
            XPathNodeIterator platformNodes = config.CreateNavigator().Select("/configuration/dduetools/platform");

            if (platformNodes.MoveNext())
            {
                XPathNavigator platformNode = platformNodes.Current;
                version = platformNode.GetAttribute("version", String.Empty);
                path    = platformNode.GetAttribute("path", String.Empty);

                // !EFW - Added support for the new platform attributes and the framework XML file
                if (!String.IsNullOrEmpty(version) && !String.IsNullOrEmpty(path))
                {
                    // Set the framework using the legacy attributes.  If set properly, they will document
                    // other framework types but it uses the standard .NET assemblies which contain more
                    // classes and methods that are not relevant to the other frameworks.
                    path = Environment.ExpandEnvironmentVariables(path);

                    if (!Directory.Exists(path))
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "The specified target platform " +
                                                        "directory '{0}' does not exist.", path);
                        return(1);
                    }

                    if (version == "2.0")
                    {
                        TargetPlatform.SetToV2(path);
                    }
                    else
                    if (version == "1.1")
                    {
                        TargetPlatform.SetToV1_1(path);
                    }
                    else
                    if (version == "1.0")
                    {
                        TargetPlatform.SetToV1(path);
                    }
                    else
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "Unknown target platform " +
                                                        "version '{0}'.", version);
                        return(1);
                    }
                }
                else
                {
                    // Use the new framework definition file
                    framework = platformNode.GetAttribute("framework", String.Empty);

                    if (!String.IsNullOrEmpty(framework) && !String.IsNullOrEmpty(version))
                    {
                        TargetPlatform.SetFrameworkInformation(framework, version);
                    }
                    else
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "Unknown target framework " +
                                                        "version '{0} {1}'.", framework, version);
                        return(1);
                    }
                }
            }

            // Create an API member namer
            ApiNamer namer;

            // Apply a different naming method to assemblies using the Windows Store or Windows Phone frameworks
            if (framework == ".NETCore" || framework == ".NETPortable" || framework == "WindowsPhone" ||
                framework == "WindowsPhoneApp")
            {
                namer = new WindowsStoreAndPhoneNamer();
            }
            else
            {
                namer = new OrcasNamer();
            }

            XPathNavigator namerNode = config.CreateNavigator().SelectSingleNode("/configuration/dduetools/namer");

            if (namerNode != null)
            {
                assemblyPath = namerNode.GetAttribute("assembly", String.Empty);
                typeName     = namerNode.GetAttribute("type", String.Empty);

                assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);

                if (!Path.IsPathRooted(assemblyPath))
                {
                    assemblyPath = Path.Combine(configDirectory, assemblyPath);
                }

                try
                {
                    Assembly assembly = Assembly.LoadFrom(assemblyPath);
                    namer = (ApiNamer)assembly.CreateInstance(typeName);

                    if (namer == null)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                                        "component assembly '{1}'.", typeName, assemblyPath);
                        return(1);
                    }
                }
                catch (IOException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                                    "attempting to load the component assembly '{0}'. The error message is: {1}",
                                                    assemblyPath, e.Message);
                    return(1);
                }
                catch (UnauthorizedAccessException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                                    "attempting to load the component assembly '{0}'. The error message is: {1}",
                                                    assemblyPath, e.Message);
                    return(1);
                }
                catch (BadImageFormatException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "The component assembly '{0}' is not a " +
                                                    "valid managed assembly.", assemblyPath);
                    return(1);
                }
                catch (TypeLoadException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                                    "component assembly '{1}'.", typeName, assemblyPath);
                    return(1);
                }
                catch (MissingMethodException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "No appropriate constructor exists for " +
                                                    "the type'{0}' in the component assembly '{1}'.", typeName, assemblyPath);
                    return(1);
                }
                catch (TargetInvocationException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while initializing the " +
                                                    "type '{0}' in the component assembly '{1}'. The error message and stack trace " +
                                                    "follows: {2}", typeName, assemblyPath, e.InnerException);
                    return(1);
                }
                catch (InvalidCastException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' in the component assembly " +
                                                    "'{1}' is not a component type.", typeName, assemblyPath);
                    return(1);
                }
            }

            // Create a resolver
            AssemblyResolver resolver     = new AssemblyResolver();
            XPathNavigator   resolverNode = config.CreateNavigator().SelectSingleNode("/configuration/dduetools/resolver");

            if (resolverNode != null)
            {
                assemblyPath = resolverNode.GetAttribute("assembly", String.Empty);
                typeName     = resolverNode.GetAttribute("type", String.Empty);

                assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);
                if (!Path.IsPathRooted(assemblyPath))
                {
                    assemblyPath = Path.Combine(configDirectory, assemblyPath);
                }

                try
                {
                    Assembly assembly = Assembly.LoadFrom(assemblyPath);
                    resolver = (AssemblyResolver)assembly.CreateInstance(typeName, false, BindingFlags.Public |
                                                                         BindingFlags.Instance, null, new object[1] {
                        resolverNode
                    }, null, null);

                    if (resolver == null)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                                        "component assembly '{1}'.", typeName, assemblyPath);
                        return(1);
                    }
                }
                catch (IOException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                                    "attempting to load the component assembly '{0}'. The error message is: {1}",
                                                    assemblyPath, e.Message);
                    return(1);
                }
                catch (UnauthorizedAccessException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                                    "attempting to load the component assembly '{0}'. The error message is: {1}",
                                                    assemblyPath, e.Message);
                    return(1);
                }
                catch (BadImageFormatException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "The component assembly '{0}' is not a " +
                                                    "valid managed assembly.", assemblyPath);
                    return(1);
                }
                catch (TypeLoadException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                                    "component assembly '{1}'.", typeName, assemblyPath);
                    return(1);
                }
                catch (MissingMethodException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "No appropriate constructor exists for " +
                                                    "the type'{0}' in the component assembly '{1}'.", typeName, assemblyPath);
                    return(1);
                }
                catch (TargetInvocationException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while initializing the " +
                                                    "type '{0}' in the component assembly '{1}'. The error message and stack trace " +
                                                    "follows: {2}", typeName, assemblyPath, e.InnerException);
                    return(1);
                }
                catch (InvalidCastException)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' in the component assembly " +
                                                    "'{1}' is not a component type.", typeName, assemblyPath);
                    return(1);
                }
            }

            resolver.UnresolvedAssemblyReference += UnresolvedAssemblyReferenceHandler;

            // Get a text writer for output
            TextWriter output = Console.Out;

            if (results.Options["out"].IsPresent)
            {
                string file = (string)results.Options["out"].Value;

                try
                {
                    output = new StreamWriter(file, false, Encoding.UTF8);
                }
                catch (IOException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while attempting to " +
                                                    "create an output file. The error message is: {0}", e.Message);
                    return(1);
                }
                catch (UnauthorizedAccessException e)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while attempting to " +
                                                    "create an output file. The error message is: {0}", e.Message);
                    return(1);
                }
            }

            // Dependency directory
            string[] dependencies = new string[0];

            if (results.Options["dep"].IsPresent)
            {
                dependencies = (string[])results.Options["dep"].Value;
            }

            try
            {
                // Create a builder
                ApiVisitor = new ManagedReflectionWriter(output, namer, resolver,
                                                         new ApiFilter(config.CreateNavigator().SelectSingleNode("/configuration/dduetools")));

                // If the deprecated /internal+ option is used, expose everything via the filter to mimic the
                // behavior of prior versions.
                if (results.Options["internal"].IsPresent && (bool)results.Options["internal"].Value)
                {
                    ApiVisitor.ApiFilter.IncludeAttributes =
                        ApiVisitor.ApiFilter.IncludeExplicitInterfaceImplementations =
                            ApiVisitor.ApiFilter.IncludePrivates                             =
                                ApiVisitor.ApiFilter.IncludePrivateFields                    =
                                    ApiVisitor.ApiFilter.IncludeInternals                    =
                                        ApiVisitor.ApiFilter.IncludeProtected                =
                                            ApiVisitor.ApiFilter.IncludeSealedProtected      =
                                                ApiVisitor.ApiFilter.IncludeInheritedMembers =
                                                    ApiVisitor.ApiFilter.IncludeInheritedFrameworkMembers                 =
                                                        ApiVisitor.ApiFilter.IncludeInheritedFrameworkPrivateMembers      =
                                                            ApiVisitor.ApiFilter.IncludeInheritedFrameworkInternalMembers =
                                                                ApiVisitor.ApiFilter.IncludeNoPIATypes = true;
                    ApiVisitor.ApiFilter.IncludeProtectedInternalAsProtected = false;
                }

                // Register add-ins to the builder
                XPathNodeIterator addinNodes = config.CreateNavigator().Select("/configuration/dduetools/addins/addin");

                foreach (XPathNavigator addinNode in addinNodes)
                {
                    assemblyPath = addinNode.GetAttribute("assembly", String.Empty);
                    typeName     = addinNode.GetAttribute("type", String.Empty);

                    assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);

                    if (!Path.IsPathRooted(assemblyPath))
                    {
                        assemblyPath = Path.Combine(configDirectory, assemblyPath);
                    }

                    try
                    {
                        Assembly         assembly = Assembly.LoadFrom(assemblyPath);
                        MRefBuilderAddIn addin    = (MRefBuilderAddIn)assembly.CreateInstance(typeName, false,
                                                                                              BindingFlags.Public | BindingFlags.Instance, null,
                                                                                              new object[2] {
                            ApiVisitor, addinNode
                        }, null, null);

                        if (addin == null)
                        {
                            ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' was not found in " +
                                                            "the add-in assembly '{1}'.", typeName, assemblyPath);
                            return(1);
                        }
                    }
                    catch (IOException e)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                                        "attempting to load the add-in assembly '{0}'. The error message is: {1}",
                                                        assemblyPath, e.Message);
                        return(1);
                    }
                    catch (BadImageFormatException)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "The add-in assembly '{0}' is not a " +
                                                        "valid managed assembly.", assemblyPath);
                        return(1);
                    }
                    catch (TypeLoadException)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                                        "add-in assembly '{1}'.", typeName, assemblyPath);
                        return(1);
                    }
                    catch (MissingMethodException)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "No appropriate constructor exists " +
                                                        "for the type '{0}' in the add-in assembly '{1}'.", typeName, assemblyPath);
                        return(1);
                    }
                    catch (TargetInvocationException e)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while initializing " +
                                                        "the type '{0}' in the add-in assembly '{1}'. The error message and stack trace " +
                                                        "follows: {2}", typeName, assemblyPath, e.InnerException);
                        return(1);
                    }
                    catch (InvalidCastException)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "The type '{0}' in the add-in " +
                                                        "assembly '{1}' is not an MRefBuilderAddIn type.", typeName, assemblyPath);
                        return(1);
                    }
                }

                // Load dependencies
                foreach (string dependency in dependencies)
                {
                    try
                    {
                        // Expand environment variables
                        path = Environment.ExpandEnvironmentVariables(dependency);

                        // If x86 but it didn't exist, assume it's a 32-bit system and change the name
                        if (path.IndexOf("%ProgramFiles(x86)%", StringComparison.Ordinal) != -1)
                        {
                            path = Environment.ExpandEnvironmentVariables(path.Replace("(x86)", String.Empty));
                        }

                        ApiVisitor.LoadAccessoryAssemblies(path);
                    }
                    catch (IOException e)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while loading " +
                                                        "dependency assemblies. The error message is: {0}", e.Message);
                        return(1);
                    }
                }

                // Parse the assemblies
                foreach (string dllPath in results.UnusedArguments)
                {
                    try
                    {
                        // Expand environment variables
                        path = Environment.ExpandEnvironmentVariables(dllPath);

                        // If x86 but it didn't exist, assume it's a 32-bit system and change the name
                        if (path.IndexOf("%ProgramFiles(x86)%", StringComparison.Ordinal) != -1)
                        {
                            path = Environment.ExpandEnvironmentVariables(path.Replace("(x86)", String.Empty));
                        }

                        ApiVisitor.LoadAssemblies(path);
                    }
                    catch (IOException e)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while loading " +
                                                        "assemblies for reflection. The error message is: {0}", e.Message);
                        return(1);
                    }
                }

                ConsoleApplication.WriteMessage(LogLevel.Info, "Loaded {0} assemblies for reflection and " +
                                                "{1} dependency assemblies.", ApiVisitor.Assemblies.Count(),
                                                ApiVisitor.AccessoryAssemblies.Count());

                ApiVisitor.VisitApis();

                if (ApiVisitor.Canceled)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, "MRefBuilder task canceled");
                }
                else
                {
                    ConsoleApplication.WriteMessage(LogLevel.Info, "Wrote information on {0} namespaces, " +
                                                    "{1} types, and {2} members", ApiVisitor.Namespaces.Count(), ApiVisitor.Types.Count(),
                                                    ApiVisitor.Members.Count());
                }
            }
            finally
            {
                if (ApiVisitor != null)
                {
                    ApiVisitor.Dispose();
                }

                if (results.Options["out"].IsPresent)
                {
                    output.Close();
                }
            }

            return((ApiVisitor != null && ApiVisitor.Canceled) ? 2 : 0);
        }
Exemplo n.º 3
0
        public static int Main(string[] args)
        {
            // write banner
            ConsoleApplication.WriteBanner();

            // specify options
            OptionCollection options = new OptionCollection();

            options.Add(new SwitchOption("?", "Show this help page."));
            options.Add(new StringOption("out", "Specify an output file. If unspecified, output goes to the console.", "outputFilePath"));
            options.Add(new StringOption("config", "Specify a configuration file. If unspecified, MRefBuilder.config is used", "configFilePath"));
            options.Add(new ListOption("dep", "Speficy assemblies to load for dependencies.", "dependencyAssembly"));
            // options.Add( new BooleanOption("namespaces", "Control whether information on namespaces in provided.") );
            options.Add(new BooleanOption("internal", "Specify whether to document internal as well as externally exposed APIs."));

            // process options
            ParseArgumentsResult results = options.ParseArguments(args);

            if (results.Options["?"].IsPresent)
            {
                Console.WriteLine("MRefBuilder [options] assemblies");
                options.WriteOptionSummary(Console.Out);
                return(0);
            }

            // check for invalid options
            if (!results.Success)
            {
                results.WriteParseErrors(Console.Out);
                return(1);
            }

            // check for missing or extra assembly directories
            if (results.UnusedArguments.Count < 1)
            {
                Console.WriteLine("Specify at least one assembly to reflect.");
                return(1);
            }

            // load the configuration file
            XPathDocument config;
            string        configDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string        configFile      = Path.Combine(configDirectory, "MRefBuilder.config");

            if (results.Options["config"].IsPresent)
            {
                configFile      = (string)results.Options["config"].Value;
                configDirectory = Path.GetDirectoryName(configFile);
            }
            try {
                config = new XPathDocument(configFile);
            } catch (IOException e) {
                ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while attempting to read the configuration file '{0}'. The error message is: {1}", configFile, e.Message));
                return(1);
            } catch (UnauthorizedAccessException e) {
                ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while attempting to read the configuration file '{0}'. The error message is: {1}", configFile, e.Message));
                return(1);
            } catch (XmlException e) {
                ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The configuration file '{0}' is not well-formed. The error message is: {1}", configFile, e.Message));
                return(1);
            }

            // adjust the target platform
            XPathNodeIterator platformNodes = config.CreateNavigator().Select("/configuration/dduetools/platform");

            if (platformNodes.MoveNext())
            {
                XPathNavigator platformNode = platformNodes.Current;
                string         version      = platformNode.GetAttribute("version", String.Empty);
                string         path         = platformNode.GetAttribute("path", String.Empty);
                path = Environment.ExpandEnvironmentVariables(path);
                if (!Directory.Exists(path))
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The specifed target platform directory '{0}' does not exist.", path));
                    return(1);
                }
                if (version == "2.0")
                {
                    TargetPlatform.SetToV2(path);
                }
                else if (version == "1.1")
                {
                    TargetPlatform.SetToV1_1(path);
                }
                else if (version == "1.0")
                {
                    TargetPlatform.SetToV1(path);
                }
                else
                {
                    Console.WriteLine("Unknown target platform version '{0}'.", version);
                    return(1);
                }
            }

            // create a namer
            ApiNamer       namer     = new OrcasNamer();
            XPathNavigator namerNode = config.CreateNavigator().SelectSingleNode("/configuration/dduetools/namer");

            if (namerNode != null)
            {
                string assemblyPath = namerNode.GetAttribute("assembly", String.Empty);
                string typeName     = namerNode.GetAttribute("type", String.Empty);

                assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);
                if (!Path.IsPathRooted(assemblyPath))
                {
                    assemblyPath = Path.Combine(configDirectory, assemblyPath);
                }

                try {
                    Assembly assembly = Assembly.LoadFrom(assemblyPath);
                    namer = (ApiNamer)assembly.CreateInstance(typeName);

                    if (namer == null)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' was not found in the component assembly '{1}'.", typeName, assemblyPath));
                        return(1);
                    }
                } catch (IOException e) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("A file access error occured while attempting to load the component assembly '{0}'. The error message is: {1}", assemblyPath, e.Message));
                    return(1);
                } catch (UnauthorizedAccessException e) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("A file access error occured while attempting to load the component assembly '{0}'. The error message is: {1}", assemblyPath, e.Message));
                    return(1);
                } catch (BadImageFormatException) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The component assembly '{0}' is not a valid managed assembly.", assemblyPath));
                    return(1);
                } catch (TypeLoadException) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' was not found in the component assembly '{1}'.", typeName, assemblyPath));
                    return(1);
                } catch (MissingMethodException) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("No appropriate constructor exists for the type'{0}' in the component assembly '{1}'.", typeName, assemblyPath));
                    return(1);
                } catch (TargetInvocationException e) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while initializing the type '{0}' in the component assembly '{1}'. The error message and stack trace follows: {2}", typeName, assemblyPath, e.InnerException.ToString()));
                    return(1);
                } catch (InvalidCastException) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' in the component assembly '{1}' is not a component type.", typeName, assemblyPath));
                    return(1);
                }
            }

            // create a resolver
            AssemblyResolver resolver     = new AssemblyResolver();
            XPathNavigator   resolverNode = config.CreateNavigator().SelectSingleNode("/configuration/dduetools/resolver");

            if (resolverNode != null)
            {
                string assemblyPath = resolverNode.GetAttribute("assembly", String.Empty);
                string typeName     = resolverNode.GetAttribute("type", String.Empty);

                assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);
                if (!Path.IsPathRooted(assemblyPath))
                {
                    assemblyPath = Path.Combine(configDirectory, assemblyPath);
                }

                try {
                    Assembly assembly = Assembly.LoadFrom(assemblyPath);
                    resolver = (AssemblyResolver)assembly.CreateInstance(typeName, false, BindingFlags.Public | BindingFlags.Instance, null, new Object[1] {
                        resolverNode
                    }, null, null);

                    if (resolver == null)
                    {
                        ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' was not found in the component assembly '{1}'.", typeName, assemblyPath));
                        return(1);
                    }
                } catch (IOException e) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("A file access error occured while attempting to load the component assembly '{0}'. The error message is: {1}", assemblyPath, e.Message));
                    return(1);
                } catch (UnauthorizedAccessException e) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("A file access error occured while attempting to load the component assembly '{0}'. The error message is: {1}", assemblyPath, e.Message));
                    return(1);
                } catch (BadImageFormatException) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The component assembly '{0}' is not a valid managed assembly.", assemblyPath));
                    return(1);
                } catch (TypeLoadException) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' was not found in the component assembly '{1}'.", typeName, assemblyPath));
                    return(1);
                } catch (MissingMethodException) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("No appropriate constructor exists for the type'{0}' in the component assembly '{1}'.", typeName, assemblyPath));
                    return(1);
                } catch (TargetInvocationException e) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while initializing the type '{0}' in the component assembly '{1}'. The error message and stack trace follows: {2}", typeName, assemblyPath, e.InnerException.ToString()));
                    return(1);
                } catch (InvalidCastException) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' in the component assembly '{1}' is not a component type.", typeName, assemblyPath));
                    return(1);
                }
            }
            resolver.UnresolvedAssemblyReference += new EventHandler <AssemblyReferenceEventArgs>(UnresolvedAssemblyReferenceHandler);

            // get a textwriter for output
            TextWriter output = Console.Out;

            if (results.Options["out"].IsPresent)
            {
                string file = (string)results.Options["out"].Value;
                try {
                    output = new StreamWriter(file, false, Encoding.UTF8);
                } catch (IOException e) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while attempting to create an output file. The error message is: {0}", e.Message));
                    return(1);
                } catch (UnauthorizedAccessException e) {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while attempting to create an output file. The error message is: {0}", e.Message));
                    return(1);
                }
            }


            // dependency directory
            string[] dependencies = new string[0];
            if (results.Options["dep"].IsPresent)
            {
                dependencies = (string[])results.Options["dep"].Value;
            }


            try {
                // create a builder
                ManagedReflectionWriter builder = new ManagedReflectionWriter(output, namer);

                // specify the resolver for the builder
                builder.Resolver = resolver;

                // builder.ApiFilter = new ExternalDocumentedFilter(config.CreateNavigator().SelectSingleNode("/configuration/dduetools"));

                // specify the filter for the builder

                if (results.Options["internal"].IsPresent && (bool)results.Options["internal"].Value)
                {
                    builder.ApiFilter = new AllDocumentedFilter(config.CreateNavigator().SelectSingleNode("/configuration/dduetools"));
                }
                else
                {
                    builder.ApiFilter = new ExternalDocumentedFilter(config.CreateNavigator().SelectSingleNode("/configuration/dduetools"));
                }

                // register add-ins to the builder

                XPathNodeIterator addinNodes = config.CreateNavigator().Select("/configuration/dduetools/addins/addin");
                foreach (XPathNavigator addinNode in addinNodes)
                {
                    string assemblyPath = addinNode.GetAttribute("assembly", String.Empty);
                    string typeName     = addinNode.GetAttribute("type", String.Empty);

                    assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);
                    if (!Path.IsPathRooted(assemblyPath))
                    {
                        assemblyPath = Path.Combine(configDirectory, assemblyPath);
                    }

                    try {
                        Assembly         assembly = Assembly.LoadFrom(assemblyPath);
                        MRefBuilderAddIn addin    = (MRefBuilderAddIn)assembly.CreateInstance(typeName, false, BindingFlags.Public | BindingFlags.Instance, null, new Object[2] {
                            builder, addinNode
                        }, null, null);

                        if (namer == null)
                        {
                            ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' was not found in the addin assembly '{1}'.", typeName, assemblyPath));
                            return(1);
                        }
                    } catch (IOException e) {
                        ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("A file access error occured while attempting to load the addin assembly '{0}'. The error message is: {1}", assemblyPath, e.Message));
                        return(1);
                    } catch (BadImageFormatException) {
                        ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The addin assembly '{0}' is not a valid managed assembly.", assemblyPath));
                        return(1);
                    } catch (TypeLoadException) {
                        ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' was not found in the addin assembly '{1}'.", typeName, assemblyPath));
                        return(1);
                    } catch (MissingMethodException) {
                        ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("No appropriate constructor exists for the type '{0}' in the addin assembly '{1}'.", typeName, assemblyPath));
                        return(1);
                    } catch (TargetInvocationException e) {
                        ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while initializing the type '{0}' in the addin assembly '{1}'. The error message and stack trace follows: {2}", typeName, assemblyPath, e.InnerException.ToString()));
                        return(1);
                    } catch (InvalidCastException) {
                        ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("The type '{0}' in the addin assembly '{1}' is not an MRefBuilderAddIn type.", typeName, assemblyPath));
                        return(1);
                    }
                }

                try {
                    // add a handler for unresolved assembly references
                    //builder.UnresolvedModuleHandler = new System.Compiler.Module.AssemblyReferenceResolver(AssemblyNotFound);

                    // load dependent bits
                    foreach (string dependency in dependencies)
                    {
                        try {
                            builder.LoadAccessoryAssemblies(dependency);
                        } catch (IOException e) {
                            ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while loading dependency assemblies. The error message is: {0}", e.Message));
                            return(1);
                        }
                    }

                    // parse the bits
                    foreach (string dllPath in results.UnusedArguments)
                    {
                        try {
                            builder.LoadAssemblies(dllPath);
                        } catch (IOException e) {
                            ConsoleApplication.WriteMessage(LogLevel.Error, String.Format("An error occured while loading assemblies for reflection. The error message is: {0}", e.Message));
                            return(1);
                        }
                    }

                    ConsoleApplication.WriteMessage(LogLevel.Info, String.Format("Loaded {0} assemblies for reflection and {1} dependency assemblies.", builder.Assemblies.Length, builder.AccessoryAssemblies.Length));

                    // register callbacks

                    //builder.RegisterStartTagCallback("apis", new MRefBuilderCallback(startTestCallback));

                    //MRefBuilderAddIn addin = new XamlAttachedMembersAddIn(builder, null);

                    builder.VisitApis();

                    ConsoleApplication.WriteMessage(LogLevel.Info, String.Format("Wrote information on {0} namespaces, {1} types, and {2} members", builder.Namespaces.Length, builder.Types.Length, builder.Members.Length));
                } finally {
                    builder.Dispose();
                }
            } finally {
                // output.Close();
            }

            return(0);
        }
Exemplo n.º 4
0
        //=====================================================================

        /// <summary>
        /// Main program entry point (MSBuild task)
        /// </summary>
        /// <returns>True on success or false failure</returns>
        public bool GenerateReflectionInformation()
        {
            string path, version, framework = null, assemblyPath, typeName;

            // Load the configuration file
            XPathDocument  config;
            XPathNavigator configNav;

            string configDirectory = Path.GetDirectoryName(this.ConfigurationFile);

            try
            {
                config    = new XPathDocument(this.ConfigurationFile);
                configNav = config.CreateNavigator();
            }
            catch (IOException e)
            {
                this.WriteMessage(LogLevel.Error, "An error occurred while attempting to read " +
                                  "the configuration file '{0}'. The error message is: {1}", this.ConfigurationFile, e.Message);
                return(false);
            }
            catch (UnauthorizedAccessException e)
            {
                this.WriteMessage(LogLevel.Error, "An error occurred while attempting to read " +
                                  "the configuration file '{0}'. The error message is: {1}", this.ConfigurationFile, e.Message);
                return(false);
            }
            catch (XmlException e)
            {
                this.WriteMessage(LogLevel.Error, "The configuration file '{0}' is not " +
                                  "well-formed. The error message is: {1}", this.ConfigurationFile, e.Message);
                return(false);
            }

            // Adjust the target platform
            var platformNode = configNav.SelectSingleNode("/configuration/dduetools/platform");

            if (platformNode == null)
            {
                this.WriteMessage(LogLevel.Error, "A platform element is required to define the " +
                                  "framework type and version to use.");
                return(false);
            }

            // !EFW - Use the framework definition file to load core framework assembly reference information
            version   = platformNode.GetAttribute("version", String.Empty);
            framework = platformNode.GetAttribute("framework", String.Empty);

            // Get component locations used to find additional reflection data definition files
            List <string> componentFolders = new List <string>();
            var           locations        = configNav.SelectSingleNode("/configuration/dduetools/componentLocations");

            if (locations != null)
            {
                foreach (XPathNavigator folder in locations.Select("location/@folder"))
                {
                    if (!String.IsNullOrWhiteSpace(folder.Value) && Directory.Exists(folder.Value))
                    {
                        componentFolders.Add(folder.Value);
                    }
                }
            }

            // Get the dependencies
            var dependencies = new List <string>();

            if (this.References != null)
            {
                dependencies.AddRange(this.References.Select(r => r.ItemSpec));
            }

            if (!String.IsNullOrEmpty(framework) && !String.IsNullOrEmpty(version))
            {
                var coreNames = new HashSet <string>(new[] { "netstandard", "mscorlib", "System.Runtime" },
                                                     StringComparer.OrdinalIgnoreCase);

                var coreFrameworkAssemblies = this.Assemblies.Select(a => a.ItemSpec).Concat(dependencies).Where(
                    d => coreNames.Contains(Path.GetFileNameWithoutExtension(d)));

                TargetPlatform.SetFrameworkInformation(framework, version, componentFolders,
                                                       coreFrameworkAssemblies);
            }
            else
            {
                this.WriteMessage(LogLevel.Error, "Unknown target framework version '{0} {1}'.",
                                  framework, version);
                return(false);
            }

            // Create an API member namer
            ApiNamer namer;

            // Apply a different naming method to assemblies using these frameworks
            if (framework == PlatformType.DotNetCore || framework == PlatformType.DotNetPortable ||
                framework == PlatformType.WindowsPhone || framework == PlatformType.WindowsPhoneApp)
            {
                namer = new WindowsStoreAndPhoneNamer();
            }
            else
            {
                namer = new OrcasNamer();
            }

            XPathNavigator namerNode = configNav.SelectSingleNode("/configuration/dduetools/namer");

            if (namerNode != null)
            {
                assemblyPath = namerNode.GetAttribute("assembly", String.Empty);
                typeName     = namerNode.GetAttribute("type", String.Empty);

                if (!String.IsNullOrWhiteSpace(assemblyPath))
                {
                    assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);

                    if (!Path.IsPathRooted(assemblyPath))
                    {
                        assemblyPath = Path.Combine(configDirectory, assemblyPath);
                    }
                }

                try
                {
                    Assembly assembly = !String.IsNullOrWhiteSpace(assemblyPath) ? Assembly.LoadFrom(assemblyPath) :
                                        Assembly.GetExecutingAssembly();
                    namer = (ApiNamer)assembly.CreateInstance(typeName);

                    if (namer == null)
                    {
                        this.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                          "component assembly '{1}'.", typeName, assembly.Location);
                        return(false);
                    }
                }
                catch (IOException e)
                {
                    this.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                      "attempting to load the component assembly '{0}'. The error message is: {1}",
                                      assemblyPath, e.Message);
                    return(false);
                }
                catch (UnauthorizedAccessException e)
                {
                    this.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                      "attempting to load the component assembly '{0}'. The error message is: {1}",
                                      assemblyPath, e.Message);
                    return(false);
                }
                catch (BadImageFormatException)
                {
                    this.WriteMessage(LogLevel.Error, "The component assembly '{0}' is not a " +
                                      "valid managed assembly.", assemblyPath);
                    return(false);
                }
                catch (TypeLoadException)
                {
                    this.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                      "component assembly '{1}'.", typeName, assemblyPath);
                    return(false);
                }
                catch (MissingMethodException)
                {
                    this.WriteMessage(LogLevel.Error, "No appropriate constructor exists for " +
                                      "the type'{0}' in the component assembly '{1}'.", typeName, assemblyPath);
                    return(false);
                }
                catch (TargetInvocationException e)
                {
                    this.WriteMessage(LogLevel.Error, "An error occurred while initializing the " +
                                      "type '{0}' in the component assembly '{1}'. The error message and stack trace " +
                                      "follows: {2}", typeName, assemblyPath, e.InnerException);
                    return(false);
                }
                catch (InvalidCastException)
                {
                    this.WriteMessage(LogLevel.Error, "The type '{0}' in the component assembly " +
                                      "'{1}' is not a component type.", typeName, assemblyPath);
                    return(false);
                }
            }

            // Create a resolver
            AssemblyResolver resolver     = new AssemblyResolver();
            XPathNavigator   resolverNode = configNav.SelectSingleNode("/configuration/dduetools/resolver");

            if (resolverNode != null)
            {
                assemblyPath = resolverNode.GetAttribute("assembly", String.Empty);
                typeName     = resolverNode.GetAttribute("type", String.Empty);

                if (!String.IsNullOrWhiteSpace(assemblyPath))
                {
                    assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);

                    if (!Path.IsPathRooted(assemblyPath))
                    {
                        assemblyPath = Path.Combine(configDirectory, assemblyPath);
                    }
                }

                try
                {
                    Assembly assembly = !String.IsNullOrWhiteSpace(assemblyPath) ? Assembly.LoadFrom(assemblyPath) :
                                        Assembly.GetExecutingAssembly();
                    resolver = (AssemblyResolver)assembly.CreateInstance(typeName, false, BindingFlags.Public |
                                                                         BindingFlags.Instance, null, new object[1] {
                        resolverNode
                    }, null, null);

                    if (resolver == null)
                    {
                        this.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                          "component assembly '{1}'.", typeName, assembly.Location);
                        return(false);
                    }
                }
                catch (IOException e)
                {
                    this.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                      "attempting to load the component assembly '{0}'. The error message is: {1}",
                                      assemblyPath, e.Message);
                    return(false);
                }
                catch (UnauthorizedAccessException e)
                {
                    this.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                      "attempting to load the component assembly '{0}'. The error message is: {1}",
                                      assemblyPath, e.Message);
                    return(false);
                }
                catch (BadImageFormatException)
                {
                    this.WriteMessage(LogLevel.Error, "The component assembly '{0}' is not a " +
                                      "valid managed assembly.", assemblyPath);
                    return(false);
                }
                catch (TypeLoadException)
                {
                    this.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                      "component assembly '{1}'.", typeName, assemblyPath);
                    return(false);
                }
                catch (MissingMethodException)
                {
                    this.WriteMessage(LogLevel.Error, "No appropriate constructor exists for " +
                                      "the type'{0}' in the component assembly '{1}'.", typeName, assemblyPath);
                    return(false);
                }
                catch (TargetInvocationException e)
                {
                    this.WriteMessage(LogLevel.Error, "An error occurred while initializing the " +
                                      "type '{0}' in the component assembly '{1}'. The error message and stack trace " +
                                      "follows: {2}", typeName, assemblyPath, e.InnerException);
                    return(false);
                }
                catch (InvalidCastException)
                {
                    this.WriteMessage(LogLevel.Error, "The type '{0}' in the component assembly " +
                                      "'{1}' is not a component type.", typeName, assemblyPath);
                    return(false);
                }
            }

            resolver.MessageLogger = (lvl, msg) => this.WriteMessage(lvl, msg);
            resolver.UnresolvedAssemblyReference += UnresolvedAssemblyReferenceHandler;

            // Get a text writer for output
            TextWriter output;

            try
            {
                output = new StreamWriter(this.ReflectionFilename, false, Encoding.UTF8);
            }
            catch (IOException e)
            {
                this.WriteMessage(LogLevel.Error, "An error occurred while attempting to " +
                                  "create an output file. The error message is: {0}", e.Message);
                return(false);
            }
            catch (UnauthorizedAccessException e)
            {
                this.WriteMessage(LogLevel.Error, "An error occurred while attempting to " +
                                  "create an output file. The error message is: {0}", e.Message);
                return(false);
            }

            try
            {
                // Create a writer
                string sourceCodeBasePath = (string)configNav.Evaluate(
                    "string(/configuration/dduetools/sourceContext/@basePath)");
                bool warnOnMissingContext = false;

                if (!String.IsNullOrWhiteSpace(sourceCodeBasePath))
                {
                    warnOnMissingContext = (bool)configNav.Evaluate(
                        "boolean(/configuration/dduetools/sourceContext[@warnOnMissingSourceContext='true'])");
                }
                else
                {
                    this.WriteMessage(LogLevel.Info, "No source code context base path " +
                                      "specified.  Source context information is unavailable.");
                }

                apiVisitor = new ManagedReflectionWriter(output, namer, resolver, sourceCodeBasePath,
                                                         warnOnMissingContext, new ApiFilter(configNav.SelectSingleNode("/configuration/dduetools")))
                {
                    MessageLogger = (lvl, msg) => this.WriteMessage(lvl, msg)
                };

                // Register add-ins to the builder
                XPathNodeIterator addinNodes = configNav.Select("/configuration/dduetools/addins/addin");

                foreach (XPathNavigator addinNode in addinNodes)
                {
                    assemblyPath = addinNode.GetAttribute("assembly", String.Empty);
                    typeName     = addinNode.GetAttribute("type", String.Empty);

                    if (!String.IsNullOrWhiteSpace(assemblyPath))
                    {
                        assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);

                        if (!Path.IsPathRooted(assemblyPath))
                        {
                            assemblyPath = Path.Combine(configDirectory, assemblyPath);
                        }
                    }

                    try
                    {
                        Assembly assembly = !String.IsNullOrWhiteSpace(assemblyPath) ? Assembly.LoadFrom(assemblyPath) :
                                            Assembly.GetExecutingAssembly();
                        MRefBuilderAddIn addin = (MRefBuilderAddIn)assembly.CreateInstance(typeName, false,
                                                                                           BindingFlags.Public | BindingFlags.Instance, null,
                                                                                           new object[2] {
                            apiVisitor, addinNode
                        }, null, null);

                        if (addin == null)
                        {
                            this.WriteMessage(LogLevel.Error, "The type '{0}' was not found in " +
                                              "the add-in assembly '{1}'.", typeName, assembly.Location);
                            return(false);
                        }
                    }
                    catch (IOException e)
                    {
                        this.WriteMessage(LogLevel.Error, "A file access error occurred while " +
                                          "attempting to load the add-in assembly '{0}'. The error message is: {1}",
                                          assemblyPath, e.Message);
                        return(false);
                    }
                    catch (BadImageFormatException)
                    {
                        this.WriteMessage(LogLevel.Error, "The add-in assembly '{0}' is not a " +
                                          "valid managed assembly.", assemblyPath);
                        return(false);
                    }
                    catch (TypeLoadException)
                    {
                        this.WriteMessage(LogLevel.Error, "The type '{0}' was not found in the " +
                                          "add-in assembly '{1}'.", typeName, assemblyPath);
                        return(false);
                    }
                    catch (MissingMethodException)
                    {
                        this.WriteMessage(LogLevel.Error, "No appropriate constructor exists " +
                                          "for the type '{0}' in the add-in assembly '{1}'.", typeName, assemblyPath);
                        return(false);
                    }
                    catch (TargetInvocationException e)
                    {
                        this.WriteMessage(LogLevel.Error, "An error occurred while initializing " +
                                          "the type '{0}' in the add-in assembly '{1}'. The error message and stack trace " +
                                          "follows: {2}", typeName, assemblyPath, e.InnerException);
                        return(false);
                    }
                    catch (InvalidCastException)
                    {
                        this.WriteMessage(LogLevel.Error, "The type '{0}' in the add-in " +
                                          "assembly '{1}' is not an MRefBuilderAddIn type.", typeName, assemblyPath);
                        return(false);
                    }
                }

                // Load dependencies
                foreach (string dependency in dependencies)
                {
                    try
                    {
                        // Expand environment variables
                        path = Environment.ExpandEnvironmentVariables(dependency);

                        // If x86 but it didn't exist, assume it's a 32-bit system and change the name
                        if (path.IndexOf("%ProgramFiles(x86)%", StringComparison.Ordinal) != -1)
                        {
                            path = Environment.ExpandEnvironmentVariables(path.Replace("(x86)", String.Empty));
                        }

                        apiVisitor.LoadAccessoryAssemblies(path);
                    }
                    catch (IOException e)
                    {
                        this.WriteMessage(LogLevel.Error, "An error occurred while loading " +
                                          "dependency assemblies. The error message is: {0}", e.Message);
                        return(false);
                    }
                }

                // Parse the assemblies
                foreach (string dllPath in this.Assemblies.Select(a => a.ItemSpec).OrderBy(d =>
                                                                                           d.IndexOf("System.Runtime.dll", StringComparison.OrdinalIgnoreCase) != -1 ? 0 :
                                                                                           d.IndexOf("netstandard.dll", StringComparison.OrdinalIgnoreCase) != -1 ? 1 :
                                                                                           d.IndexOf("mscorlib.dll", StringComparison.OrdinalIgnoreCase) != -1 ? 2 : 3))
                {
                    try
                    {
                        // Expand environment variables
                        path = Environment.ExpandEnvironmentVariables(dllPath);

                        // If x86 but it didn't exist, assume it's a 32-bit system and change the name
                        if (path.IndexOf("%ProgramFiles(x86)%", StringComparison.Ordinal) != -1)
                        {
                            path = Environment.ExpandEnvironmentVariables(path.Replace("(x86)", String.Empty));
                        }

                        apiVisitor.LoadAssemblies(path);
                    }
                    catch (IOException e)
                    {
                        this.WriteMessage(LogLevel.Error, "An error occurred while loading " +
                                          "assemblies for reflection. The error message is: {0}", e.Message);
                        return(false);
                    }
                }

                this.WriteMessage(LogLevel.Info, "Loaded {0} assemblies for reflection and " +
                                  "{1} dependency assemblies.", apiVisitor.Assemblies.Count(),
                                  apiVisitor.AccessoryAssemblies.Count());

                apiVisitor.VisitApis();

                if (apiVisitor.Canceled)
                {
                    this.WriteMessage(LogLevel.Error, "MRefBuilder task canceled");
                }
                else
                {
                    this.WriteMessage(LogLevel.Info, "Wrote information on {0} namespaces, " +
                                      "{1} types, and {2} members", apiVisitor.NamespaceCount, apiVisitor.TypeCount,
                                      apiVisitor.MemberCount);

                    this.WriteMessage(LogLevel.Info, "Merging duplicate type and member information");

                    var(mergedTypes, mergedMembers) = apiVisitor.MergeDuplicateReflectionData(this.ReflectionFilename);

                    this.WriteMessage(LogLevel.Info, "Merged {0} duplicate type(s) and {1} " +
                                      "duplicate member(s)", mergedTypes, mergedMembers);
                }
            }
            finally
            {
                if (apiVisitor != null)
                {
                    apiVisitor.Dispose();
                }

                if (output != null)
                {
                    output.Close();
                }
            }

            return(apiVisitor != null && !apiVisitor.Canceled);
        }
        protected override bool OnRun(BuildLogger logger)
        {
            bool isSuccessful = false;

            _logger = logger;

            if (_assemblyFiles == null || _assemblyFiles.Count == 0)
            {
                _logger.WriteLine(
                    "The assemblies files for reflections are required, but are not specified.",
                    BuildLoggerLevel.Error);
            }

            // load the configuration file
            XPathDocument  config;
            XPathNavigator documentNode;
            string         configDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string         configFile      = Path.Combine(configDirectory,
                                                          "Sandcastle.Reflection.config");

            if (!String.IsNullOrEmpty(_configurationFile) && File.Exists(_configurationFile))
            {
                configFile      = _configurationFile;
                configDirectory = Path.GetDirectoryName(configFile);
            }
            try
            {
                config       = new XPathDocument(configFile);
                documentNode = config.CreateNavigator();
            }
            catch (IOException e)
            {
                _logger.WriteLine(String.Format(
                                      "An error occurred while attempting to read the configuration file '{0}'. The error message is: {1}",
                                      configFile, e.Message), BuildLoggerLevel.Error);

                return(isSuccessful);
            }
            catch (UnauthorizedAccessException e)
            {
                _logger.WriteLine(String.Format(
                                      "An error occurred while attempting to read the configuration file '{0}'. The error message is: {1}",
                                      configFile, e.Message), BuildLoggerLevel.Error);

                return(isSuccessful);
            }
            catch (XmlException e)
            {
                _logger.WriteLine(String.Format(
                                      "The configuration file '{0}' is not well-formed. The error message is: {1}",
                                      configFile, e.Message), BuildLoggerLevel.Error);

                return(isSuccessful);
            }

            // adjust the target platform
            XPathNodeIterator platformNodes = documentNode.Select(
                "/configuration/dduetools/platform");

            if (platformNodes.MoveNext())
            {
                XPathNavigator platformNode = platformNodes.Current;
                string         version      = platformNode.GetAttribute("version", String.Empty);
                string         path         = platformNode.GetAttribute("path", String.Empty);
                path = Environment.ExpandEnvironmentVariables(path);
                if (!Directory.Exists(path))
                {
                    _logger.WriteLine(String.Format(
                                          "The specified target platform directory '{0}' does not exist.",
                                          path), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                if (version == "2.0")
                {
                    TargetPlatform.SetToV2(path);
                }
                else if (version == "1.1")
                {
                    TargetPlatform.SetToV1_1(path);
                }
                else if (version == "1.0")
                {
                    TargetPlatform.SetToV1(path);
                }
                else
                {
                    _logger.WriteLine(String.Format(
                                          "Unknown target platform version '{0}'.", version),
                                      BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
            }

            // create a namer
            ApiNamer       namer     = new OrcasNamer();
            XPathNavigator namerNode = documentNode.SelectSingleNode(
                "/configuration/dduetools/namer");

            if (namerNode != null)
            {
                string assemblyPath = namerNode.GetAttribute("assembly", String.Empty);
                string typeName     = namerNode.GetAttribute("type", String.Empty);

                assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);
                if (!Path.IsPathRooted(assemblyPath))
                {
                    assemblyPath = Path.Combine(configDirectory, assemblyPath);
                }

                try
                {
                    Assembly assembly = Assembly.LoadFrom(assemblyPath);
                    namer = (ApiNamer)assembly.CreateInstance(typeName);

                    if (namer == null)
                    {
                        _logger.WriteLine(String.Format(
                                              "The type '{0}' was not found in the component assembly '{1}'.",
                                              typeName, assemblyPath), BuildLoggerLevel.Error);

                        return(isSuccessful);
                    }
                }
                catch (IOException e)
                {
                    _logger.WriteLine(String.Format(
                                          "A file access error occurred while attempting to load the component assembly '{0}'. The error message is: {1}",
                                          assemblyPath, e.Message), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (UnauthorizedAccessException e)
                {
                    _logger.WriteLine(String.Format(
                                          "A file access error occurred while attempting to load the component assembly '{0}'. The error message is: {1}",
                                          assemblyPath, e.Message), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (BadImageFormatException)
                {
                    _logger.WriteLine(String.Format(
                                          "The component assembly '{0}' is not a valid managed assembly.",
                                          assemblyPath), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (TypeLoadException)
                {
                    _logger.WriteLine(String.Format(
                                          "The type '{0}' was not found in the component assembly '{1}'.",
                                          typeName, assemblyPath), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (MissingMethodException)
                {
                    _logger.WriteLine(String.Format(
                                          "No appropriate constructor exists for the type'{0}' in the component assembly '{1}'.",
                                          typeName, assemblyPath), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (TargetInvocationException e)
                {
                    _logger.WriteLine(String.Format(
                                          "An error occurred while initializing the type '{0}' in the component assembly '{1}'. The error message and stack trace follows: {2}",
                                          typeName, assemblyPath, e.InnerException.ToString()),
                                      BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (InvalidCastException)
                {
                    _logger.WriteLine(String.Format(
                                          "The type '{0}' in the component assembly '{1}' is not a component type.",
                                          typeName, assemblyPath), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
            }

            // create a resolver
            AssemblyResolver resolver     = new AssemblyResolver();
            XPathNavigator   resolverNode = documentNode.SelectSingleNode(
                "/configuration/dduetools/resolver");

            if (resolverNode != null)
            {
                string assemblyPath = resolverNode.GetAttribute("assembly", String.Empty);
                string typeName     = resolverNode.GetAttribute("type", String.Empty);

                assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);
                if (!Path.IsPathRooted(assemblyPath))
                {
                    assemblyPath = Path.Combine(configDirectory, assemblyPath);
                }

                try
                {
                    Assembly assembly = Assembly.LoadFrom(assemblyPath);
                    resolver = (AssemblyResolver)assembly.CreateInstance(typeName, false,
                                                                         BindingFlags.Public | BindingFlags.Instance, null,
                                                                         new Object[1] {
                        resolverNode
                    }, null, null);

                    if (resolver == null)
                    {
                        _logger.WriteLine(String.Format(
                                              "The type '{0}' was not found in the component assembly '{1}'.",
                                              typeName, assemblyPath), BuildLoggerLevel.Error);

                        return(isSuccessful);
                    }
                }
                catch (IOException e)
                {
                    _logger.WriteLine(String.Format(
                                          "A file access error occurred while attempting to load the component assembly '{0}'. The error message is: {1}",
                                          assemblyPath, e.Message), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (UnauthorizedAccessException e)
                {
                    _logger.WriteLine(String.Format(
                                          "A file access error occurred while attempting to load the component assembly '{0}'. The error message is: {1}",
                                          assemblyPath, e.Message), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (BadImageFormatException)
                {
                    _logger.WriteLine(String.Format(
                                          "The component assembly '{0}' is not a valid managed assembly.",
                                          assemblyPath), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (TypeLoadException)
                {
                    _logger.WriteLine(String.Format(
                                          "The type '{0}' was not found in the component assembly '{1}'.",
                                          typeName, assemblyPath), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (MissingMethodException)
                {
                    _logger.WriteLine(String.Format(
                                          "No appropriate constructor exists for the type'{0}' in the component assembly '{1}'.",
                                          typeName, assemblyPath), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (TargetInvocationException e)
                {
                    _logger.WriteLine(String.Format(
                                          "An error occurred while initializing the type '{0}' in the component assembly '{1}'. The error message and stack trace follows: {2}",
                                          typeName, assemblyPath, e.InnerException.ToString()),
                                      BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (InvalidCastException)
                {
                    _logger.WriteLine(String.Format(
                                          "The type '{0}' in the component assembly '{1}' is not a component type.",
                                          typeName, assemblyPath), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
            }
            resolver.UnresolvedAssemblyReference +=
                new EventHandler <AssemblyReferenceEventArgs>(OnUnresolvedAssemblyReferenceHandler);

            // Get a text-writer for output
            TextWriter output = null;

            if (!String.IsNullOrEmpty(_reflectionFile))
            {
                try
                {
                    output = new StreamWriter(_reflectionFile, false, Encoding.UTF8);
                }
                catch (IOException e)
                {
                    _logger.WriteLine(String.Format(
                                          "An error occurred while attempting to create an output file. The error message is: {0}",
                                          e.Message), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (UnauthorizedAccessException e)
                {
                    _logger.WriteLine(String.Format(
                                          "An error occurred while attempting to create an output file. The error message is: {0}",
                                          e.Message), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
            }
            else
            {
                output = Console.Out;
            }

            // dependency directory
            IList <string> dependencies = new List <string>();

            if (_dependencyFiles != null && _dependencyFiles.Count != 0)
            {
                for (int i = 0; i < _dependencyFiles.Count; i++)
                {
                    string dependencyDir = _dependencyFiles[i];
                    if (dependencyDir != null)
                    {
                        dependencyDir = dependencyDir.Trim();
                    }

                    if (!String.IsNullOrEmpty(dependencyDir))
                    {
                        dependencies.Add(dependencyDir);
                    }
                }
            }

            // create a builder
            ManagedReflectionWriter builder = new ManagedReflectionWriter(
                output, namer);

            // specify the resolver for the builder
            builder.Resolver = resolver;

            // builder.ApiFilter = new ExternalDocumentedFilter(documentNode.SelectSingleNode("/configuration/dduetools"));

            // specify the filter for the builder

            if (_documentInternals)
            {
                builder.ApiFilter = new AllDocumentedFilter(
                    documentNode.SelectSingleNode("/configuration/dduetools"));
            }
            else
            {
                builder.ApiFilter = new ExternalDocumentedFilter(
                    documentNode.SelectSingleNode("/configuration/dduetools"));
            }

            // register add-ins to the builder

            XPathNodeIterator addinNodes = documentNode.Select(
                "/configuration/dduetools/addins/addin");

            foreach (XPathNavigator addinNode in addinNodes)
            {
                string assemblyPath = addinNode.GetAttribute("assembly", String.Empty);
                string typeName     = addinNode.GetAttribute("type", String.Empty);

                assemblyPath = Environment.ExpandEnvironmentVariables(assemblyPath);
                if (!Path.IsPathRooted(assemblyPath))
                {
                    assemblyPath = Path.Combine(configDirectory, assemblyPath);
                }

                try
                {
                    Assembly         assembly = Assembly.LoadFrom(assemblyPath);
                    MRefBuilderAddIn addin    = (MRefBuilderAddIn)assembly.CreateInstance(
                        typeName, false, BindingFlags.Public | BindingFlags.Instance, null,
                        new Object[2] {
                        builder, addinNode
                    }, null, null);

                    if (namer == null)
                    {
                        _logger.WriteLine(String.Format(
                                              "The type '{0}' was not found in the addin assembly '{1}'.",
                                              typeName, assemblyPath), BuildLoggerLevel.Error);

                        return(isSuccessful);
                    }
                }
                catch (IOException e)
                {
                    _logger.WriteLine(String.Format(
                                          "A file access error occurred while attempting to load the addin assembly '{0}'. The error message is: {1}",
                                          assemblyPath, e.Message), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (BadImageFormatException)
                {
                    _logger.WriteLine(String.Format(
                                          "The addin assembly '{0}' is not a valid managed assembly.",
                                          assemblyPath), BuildLoggerLevel.Error);
                    return(isSuccessful);
                }
                catch (TypeLoadException)
                {
                    _logger.WriteLine(String.Format(
                                          "The type '{0}' was not found in the addin assembly '{1}'.",
                                          typeName, assemblyPath), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (MissingMethodException)
                {
                    _logger.WriteLine(String.Format(
                                          "No appropriate constructor exists for the type '{0}' in the addin assembly '{1}'.",
                                          typeName, assemblyPath), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (TargetInvocationException e)
                {
                    _logger.WriteLine(String.Format(
                                          "An error occurred while initializing the type '{0}' in the addin assembly '{1}'. The error message and stack trace follows: {2}",
                                          typeName, assemblyPath, e.InnerException.ToString()),
                                      BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
                catch (InvalidCastException)
                {
                    _logger.WriteLine(String.Format(
                                          "The type '{0}' in the addin assembly '{1}' is not an MRefBuilderAddIn type.",
                                          typeName, assemblyPath), BuildLoggerLevel.Error);

                    return(isSuccessful);
                }
            }

            try
            {
                // add a handler for unresolved assembly references
                //builder.UnresolvedModuleHandler = new System.Compiler.Module.AssemblyReferenceResolver(AssemblyNotFound);

                // load dependent bits
                foreach (string dependency in dependencies)
                {
                    try
                    {
                        builder.LoadAccessoryAssemblies(dependency);
                    }
                    catch (IOException e)
                    {
                        _logger.WriteLine(String.Format(
                                              "An error occurred while loading dependency assemblies. The error message is: {0}",
                                              e.Message), BuildLoggerLevel.Error);

                        return(isSuccessful);
                    }
                }

                // parse the bits
                foreach (string dllPath in _assemblyFiles)
                {
                    try
                    {
                        builder.LoadAssemblies(dllPath);
                    }
                    catch (IOException e)
                    {
                        _logger.WriteLine(String.Format(
                                              "An error occurred while loading assemblies for reflection. The error message is: {0}",
                                              e.Message), BuildLoggerLevel.Error);

                        return(isSuccessful);
                    }
                }

                _logger.WriteLine(String.Format(
                                      "Loaded {0} assemblies for reflection and {1} dependency assemblies.",
                                      builder.Assemblies.Length, builder.AccessoryAssemblies.Length),
                                  BuildLoggerLevel.Info);

                // register callbacks

                //builder.RegisterStartTagCallback("apis", new MRefBuilderCallback(startTestCallback));

                //MRefBuilderAddIn addin = new XamlAttachedMembersAddIn(builder, null);

                builder.VisitApis();

                _logger.WriteLine(String.Format(
                                      "Wrote information on {0} namespaces, {1} types, and {2} members",
                                      builder.Namespaces.Length, builder.Types.Length, builder.Members.Length),
                                  BuildLoggerLevel.Info);

                isSuccessful = true;
            }
            finally
            {
                resolver.UnresolvedAssemblyReference -=
                    new EventHandler <AssemblyReferenceEventArgs>(OnUnresolvedAssemblyReferenceHandler);

                builder.Dispose();
            }

            return(isSuccessful);
        }