Пример #1
0
        public static void Main(string[] args)
        {
            const string StrictSwitch = "-strict";

            bool treatWarningsAsErrors = false;
            var arguments = args.ToList();
            if (arguments.Contains(StrictSwitch))
            {
                treatWarningsAsErrors = true;
                arguments.Remove(StrictSwitch);
            }

            if (arguments.Count != 1)
            {
                Console.Error.WriteLine("Usage: XmlDoc2CmdletDoc.exe [{0}] assemblyPath", StrictSwitch);
                Environment.Exit(-1);
            }
            else
            {
                var options = new Options(treatWarningsAsErrors, arguments.First());
                Console.WriteLine(options);
                var engine = new Engine();
                var exitCode = engine.GenerateHelp(options);
                Console.WriteLine("GenerateHelp completed with exit code '{0}'", exitCode);
                Environment.Exit((int)exitCode);
            }
        }
Пример #2
0
        public void SetUp()
        {
            // ARRANGE
            var assemblyPath = typeof(TestManualElementsCommand).Assembly.Location;
            var cmdletXmlHelpPath = Path.ChangeExtension(assemblyPath, ".dll-Help.xml");
            if (File.Exists(cmdletXmlHelpPath))
            {
                File.Delete(cmdletXmlHelpPath);
            }

            // ACT
            var options = new Options(false, assemblyPath);
            var engine = new Engine();
            engine.GenerateHelp(options);

            // ASSERT
            Assert.That(File.Exists(cmdletXmlHelpPath));

            using (var stream = File.OpenRead(cmdletXmlHelpPath))
            {
                var document = XDocument.Load(stream);
                rootElement = document.Root;
            }
            testManualElementsCommandElement = rootElement.XPathSelectElement("command:command[command:details/command:name/text() = 'Test-ManualElements']", resolver);
            testMamlElementsCommandElement = rootElement.XPathSelectElement("command:command[command:details/command:name/text() = 'Test-MamlElements']", resolver);
            testReferencesCommandElement = rootElement.XPathSelectElement("command:command[command:details/command:name/text() = 'Test-References']", resolver);
            testInputTypesCommandElement = rootElement.XPathSelectElement("command:command[command:details/command:name/text() = 'Test-InputTypes']", resolver);
        }
Пример #3
0
        /// <summary>
        /// Public entry point that triggers the creation of the cmdlet XML help file for a single assembly.
        /// </summary>
        /// <param name="options">Defines the locations of the input assembly, the input XML doc comments file for the
        /// assembly, and where the cmdlet XML help file should be written to.</param>
        /// <returns>A code indicating the result of the help generation.</returns>
        public EngineExitCode GenerateHelp(Options options)
        {
            try
            {
                var warnings = new List<Tuple<MemberInfo, string>>();
                ReportWarning reportWarning = (target, warningText) => warnings.Add(Tuple.Create(target, warningText));

                var assembly = LoadAssembly(options);
                var commentReader = LoadComments(options, reportWarning);
                var cmdletTypes = GetCommands(assembly);


                var document = new XDocument(new XDeclaration("1.0", "utf-8", null),
                                             GenerateHelpItemsElement(commentReader, cmdletTypes, reportWarning));

                HandleWarnings(options, warnings, assembly);

                using (var stream = new FileStream(options.OutputHelpFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
                using (var writer = new StreamWriter(stream, Encoding.UTF8))
                {
                    document.Save(writer);
                }

                return EngineExitCode.Success;
            }
            catch (Exception exception)
            {
                Console.Error.WriteLine(exception);
                var typeLoadException = exception as ReflectionTypeLoadException;
                if (typeLoadException != null)
                {
                    foreach (var loaderException in typeLoadException.LoaderExceptions)
                    {
                        Console.Error.WriteLine("Loader exception: {0}", loaderException);
                    }
                }
                var engineException = exception as EngineException;
                return engineException == null
                           ? EngineExitCode.UnhandledException
                           : engineException.ExitCode;
            }
        }
Пример #4
0
 /// <summary>
 /// Handles the list of warnings generated once the cmdlet help XML document has been generated.
 /// </summary>
 /// <param name="options">The options.</param>
 /// <param name="warnings">The warnings generated during the creation of the cmdlet help XML document. Each tuple
 /// consists of the type to which the warning pertains, and the text of the warning.</param>
 /// <param name="targetAssembly">The assembly of the PowerShell module being documented.</param>
 private static void HandleWarnings(Options options, IEnumerable<Tuple<MemberInfo, string>> warnings, Assembly targetAssembly)
 {
     var groups = warnings.Where(tuple =>
                                 {
                                     // Exclude warnings about types outside of the assembly being documented.
                                     var type = tuple.Item1 as Type ?? tuple.Item1.DeclaringType;
                                     return type != null && type.Assembly == targetAssembly;
                                 })
                          .GroupBy(tuple => GetFullyQualifiedName(tuple.Item1), tuple => tuple.Item2)
                          .OrderBy(group => group.Key)
                          .ToList();
     if (groups.Any())
     {
         var writer = options.TreatWarningsAsErrors ? Console.Error : Console.Out;
         writer.WriteLine("Warnings:");
         foreach (var group in groups)
         {
             writer.WriteLine("    {0}:", group.Key);
             foreach (var warningText in group.Distinct())
             {
                 writer.WriteLine("        {0}", warningText);
             }
         }
         if (options.TreatWarningsAsErrors)
         {
             throw new EngineException(EngineExitCode.WarningsAsErrors,
                                       "Failing due to the occurence of one or more warnings");
         }
     }
 }
Пример #5
0
 /// <summary>
 /// Obtains an XML Doc comment reader for the assembly in the specified <paramref name="options"/>.
 /// </summary>
 /// <param name="options">The options.</param>
 /// <param name="reportWarning">Function used to log warnings.</param>
 /// <returns>A comment reader for the assembly in the <paramref name="options"/>.</returns>
 private ICommentReader LoadComments(Options options, ReportWarning reportWarning)
 {
     var docCommentsPath = options.DocCommentsPath;
     if (!File.Exists(docCommentsPath))
     {
         throw new EngineException(EngineExitCode.AssemblyCommentsNotFound,
                                   "Assembly comments file not found: " + docCommentsPath);
     }
     try
     {
         return new CachingCommentReader(
             new RewritingCommentReader(
                 new LoggingCommentReader(
                     new JoltCommentReader(docCommentsPath), reportWarning)));
     }
     catch (Exception exception)
     {
         throw new EngineException(EngineExitCode.DocCommentsLoadError,
                                   "Failed to load XML Doc comments from file: " + docCommentsPath,
                                   exception);
     }
 }
Пример #6
0
        /// <summary>
        /// Loads the assembly indicated in the specified <paramref name="options"/>.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <returns>The assembly indicated in the <paramref name="options"/>.</returns>
        private Assembly LoadAssembly(Options options)
        {
            var assemblyPath = options.AssemblyPath;
            if (!File.Exists(assemblyPath))
            {
                throw new EngineException(EngineExitCode.AssemblyNotFound,
                                          "Assembly file not found: " + assemblyPath);
            }
            try
            {
                var assemblyDir = Path.GetDirectoryName(assemblyPath);
                AppDomain.CurrentDomain.AssemblyResolve += // TODO: Really ought to track this handler and cleanly remove it.
                    (sender, args) =>
                    {
                        var name = args.Name;
                        var i = name.IndexOf(',');
                        if (i != -1)
                        {
                            name = name.Substring(0, i);
                        }
                        name += ".dll";
                        var path = Path.Combine(assemblyDir, name);
                        return Assembly.LoadFrom(path);
                    };

                return Assembly.LoadFile(assemblyPath);
            }
            catch (Exception exception)
            {
                throw new EngineException(EngineExitCode.AssemblyLoadError,
                                          "Failed to load assembly from file: " + assemblyPath,
                                          exception);
            }
        }