Esempio n. 1
0
        /// <summary>
        ///     Extract the input types for a Cmdlet.
        /// </summary>
        /// <param name="cmdletType">
        ///     The CLR type that implements the Cmdlet.
        /// </param>
        /// <returns>
        ///     A list of values, which may be empty or null.
        /// </returns>
        public List <CommandValue> GetCmdletInputTypes(TypeInfo cmdletType)
        {
            if (cmdletType == null)
            {
                throw new ArgumentNullException(nameof(cmdletType));
            }

            var inputTypeAttributes = cmdletType.GetCustomAttributes <CmdletInputTypeAttribute>().ToList();

            if (inputTypeAttributes.Count == 0)
            {
                return(null);
            }

            var inputTypes = new List <CommandValue>();

            foreach (var attribute in inputTypeAttributes)
            {
                inputTypes.Add(new CommandValue
                {
                    DataType =
                    {
                        Name = attribute.IsCLRType ? MamlGenerator.PowerShellIfyTypeName(attribute.Type) : attribute.Name,
                        Uri  = attribute.Uri
                    },
                    Description = MamlGenerator.ToParagraphs(attribute.Description)
                });
            }

            return(inputTypes);
        }
Esempio n. 2
0
        /// <summary>
        ///     Extract the examples for a Cmdlet parameter.
        /// </summary>
        /// <param name="cmdletType">
        ///     The CLR type that implements the Cmdlet.
        /// </param>
        /// <returns>
        ///     A list of example, which may be empty.
        /// </returns>
        public List <CommandExample> GetCmdletExamples(TypeInfo cmdletType)
        {
            if (cmdletType == null)
            {
                throw new ArgumentNullException(nameof(cmdletType));
            }

            var attributes = cmdletType.GetCustomAttributes <CmdletExampleAttribute>();

            if (attributes == null)
            {
                return(null);
            }

            var examples = new List <CommandExample>();

            foreach (var attribute in attributes)
            {
                examples.Add(
                    new CommandExample
                {
                    Title       = attribute.Title,
                    Description = MamlGenerator.ToParagraphs(attribute.Description),
                    Code        = attribute.Code,
                    Remarks     = MamlGenerator.ToParagraphs(attribute.Remarks)
                }
                    );
            }

            return(examples);
        }
Esempio n. 3
0
        /// <summary>
        ///     Execute the task.
        /// </summary>
        /// <returns>
        ///     <c>true</c>, if the task executed succesfully; otherwise, <c>false</c>.
        /// </returns>
        public override bool Execute()
        {
            FileInfo moduleAssemblyFile = new FileInfo(
                ModuleAssembly.GetMetadata("FullPath")
                );

            Log.LogMessage(MessageImportance.Low, "Scanning assembly '{0}'...",
                           moduleAssemblyFile.FullName
                           );

            DirectoryAssemblyLoadContext assemblyLoadContext = new DirectoryAssemblyLoadContext(
                fallbackDirectory: moduleAssemblyFile.Directory.FullName
                );

            HelpItems     help      = new HelpItems();
            MamlGenerator generator = new MamlGenerator();

            Assembly moduleAssembly = assemblyLoadContext.LoadFromAssemblyPath(moduleAssemblyFile.FullName);

            foreach (Type cmdletType in Reflector.GetCmdletTypes(moduleAssembly))
            {
                CmdletAttribute cmdletAttribute = cmdletType.GetTypeInfo().GetCustomAttribute <CmdletAttribute>();

                Log.LogMessage(MessageImportance.Low, "Generating help for cmdlet '{0}-{1}' ('{2}').",
                               cmdletAttribute.VerbName,
                               cmdletAttribute.NounName,
                               cmdletType.FullName
                               );

                help.Commands.Add(
                    generator.Generate(cmdletType)
                    );
            }

            FileInfo helpFile = new FileInfo(
                HelpFile.GetMetadata("FullPath")
                );

            if (helpFile.Exists)
            {
                helpFile.Delete();
            }

            using (StreamWriter writer = helpFile.CreateText())
            {
                help.WriteTo(writer);
            }

            Log.LogMessage(MessageImportance.Normal, "'{0}' -> '{1}'",
                           moduleAssemblyFile.Name,
                           helpFile.Name
                           );

            return(true);
        }
Esempio n. 4
0
        /// <summary>
        ///     The main program entry-point.
        /// </summary>
        /// <param name="args">
        ///     Command-line arguments.
        /// </param>
        static void Main(string[] args)
        {
            if (args.Length < 2 || args.Length > 3 || args[0] != "gen-help")
            {
                Console.WriteLine("Usage:\n\tdotnet reptile gen-help <Module.dll> [Module.dll-Help.xml]");

                return;
            }

            try
            {
                string modulePath = Path.GetFullPath(args[1]);

                // If the module's dependencies are not available from
                // the usual places (e.g. dotnet-reptile's base directory)
                // then load them from the module directory.
                DirectoryAssemblyLoadContext loadContext = new DirectoryAssemblyLoadContext(
                    Path.GetDirectoryName(modulePath)
                    );
                Assembly  moduleAssembly = loadContext.LoadFromAssemblyPath(modulePath);
                HelpItems help           = new MamlGenerator().Generate(moduleAssembly);

                FileInfo helpFile = new FileInfo(
                    fileName: args.Length == 3 ? Path.GetFullPath(args[2]) : modulePath + "-Help.xml"
                    );
                if (helpFile.Exists)
                {
                    helpFile.Delete();
                }

                using (StreamWriter writer = helpFile.CreateText())
                {
                    help.WriteTo(writer);
                }

                Console.WriteLine($"Generated '{helpFile.FullName}'.");
            }
            catch (ReflectionTypeLoadException typeLoadError)
            {
                Console.WriteLine(typeLoadError);
                Console.WriteLine(
                    new String('=', 80)
                    );
                foreach (Exception loaderException in typeLoadError.LoaderExceptions)
                {
                    Console.WriteLine(loaderException);
                }
            }
            catch (Exception unexpectedError)
            {
                Console.WriteLine(unexpectedError);
            }
        }
Esempio n. 5
0
        /// <summary>
        ///     Extract the description for a Cmdlet parameter.
        /// </summary>
        /// <param name="parameterProperty">
        ///     The property that represents the parameter.
        /// </param>
        /// <returns>
        ///     The description, or <c>null</c> if no description could be extracted by this extractor.
        ///
        ///     An empty list means a description was extracted, but the description is empty (this is legal).
        /// </returns>
        public List <string> GetParameterDescription(PropertyInfo parameterProperty)
        {
            if (parameterProperty == null)
            {
                throw new ArgumentNullException(nameof(parameterProperty));
            }

            var assemblyDoc = GetAssemblyDocumentation(parameterProperty);

            if (assemblyDoc == null)
            {
                return(null);
            }

            return(MamlGenerator.ToParagraphs(assemblyDoc.GetSummary(parameterProperty)));
        }
Esempio n. 6
0
        /// <summary>
        ///     Extract the description for a Cmdlet parameter.
        /// </summary>
        /// <param name="parameterProperty">
        ///     The property that represents the parameter.
        /// </param>
        /// <returns>
        ///     The description, or <c>null</c> if no description could be extracted by this extractor.
        ///
        ///     An empty list means a description was extracted, but the description is empty (this is legal).
        /// </returns>
        public List <string> GetParameterDescription(PropertyInfo parameterProperty)
        {
            if (parameterProperty == null)
            {
                throw new ArgumentNullException(nameof(parameterProperty));
            }

            var descriptionAttribute = parameterProperty.GetCustomAttributes <ParameterAttribute>().Last();

            if (descriptionAttribute == null)
            {
                return(null);
            }

            // TODO: Handle resource-based messages (with locale).

            return(MamlGenerator.ToParagraphs(descriptionAttribute.HelpMessage?.Trim()));
        }
Esempio n. 7
0
        /// <summary>
        ///     Extract the input types for a Cmdlet.
        /// </summary>
        /// <param name="cmdletType">
        ///     The CLR type that implements the Cmdlet.
        /// </param>
        /// <returns>
        ///     A list of values, which may be empty or null.
        /// </returns>
        public List <CommandValue> GetCmdletInputTypes(TypeInfo cmdletType)
        {
            if (cmdletType == null)
            {
                throw new ArgumentNullException(nameof(cmdletType));
            }

            var assemblyDoc = GetAssemblyDocumentation(cmdletType);

            if (assemblyDoc == null)
            {
                return(null);
            }
            var inputElements = assemblyDoc.GetInputs(cmdletType);

            var inputTypes = new List <CommandValue>();

            foreach (var element in inputElements)
            {
                var see         = element.Element("sees");
                var paras       = element.Elements("para")?.Select(e => MamlGenerator.ToParagraphs(e?.Value?.Trim())).ToList() ?? new List <List <string> >();
                var description = new List <string>();

                if (see == null && paras.Count == 0)
                {
                    description.AddRange(MamlGenerator.ToParagraphs(element.Value?.Trim()));
                }
                else
                {
                    foreach (var list in paras)
                    {
                        description.AddRange(list);
                    }
                }

                if (see == null || !see.HasAttributes)
                {
                    var first = description[0];
                    description.RemoveAt(0);
                    element.Add(
                        new CommandValue
                    {
                        DataType    = { Name = first },
                        Description = description
                    }
                        );
                    continue;
                }

                var name = see.Attribute("cref")?.Value?.Trim() ?? string.Empty;
                if (name != null)
                {
                    try {
                        var type = Type.GetType(name);
                        if (type != null)
                        {
                            name = MamlGenerator.PowerShellIfyTypeName(type);
                        }
                    } catch (ArgumentException)
                    {
                        // Ignore this exception
                    } catch (TypeLoadException)
                    {
                        // Ignore this exception
                    }
                }

                element.Add(
                    new CommandValue
                {
                    DataType =
                    {
                        Name        = name ?? string.Empty,
                        Uri         = see.Attribute("uri")?.Value?.Trim(),
                        Description = MamlGenerator.ToParagraphs(see.Value?.Trim())
                    },
                    Description = description
                }
                    );
            }

            return(inputTypes);
        }
Esempio n. 8
0
        /// <summary>
        ///     Extract the return values for a Cmdlet.
        /// </summary>
        /// <param name="cmdletType">
        ///     The CLR type that implements the Cmdlet.
        /// </param>
        /// <returns>
        ///     A list of values, which may be empty or null.
        /// </returns>
        public List <CommandValue> GetCmdletReturnValues(TypeInfo cmdletType)
        {
            if (cmdletType == null)
            {
                throw new ArgumentNullException(nameof(cmdletType));
            }

            var assemblyDoc = GetAssemblyDocumentation(cmdletType);

            if (assemblyDoc == null)
            {
                return(null);
            }
            var returnElements = assemblyDoc.GetReturns(cmdletType);

            var returnValues = new List <CommandValue>();

            foreach (var returnElement in returnElements)
            {
                var see         = returnElement.Element("sees");
                var paras       = returnElement.Elements("para")?.Select(e => MamlGenerator.ToParagraphs(e?.Value?.Trim())).ToList() ?? new List <List <string> >();
                var description = new List <string>();

                if (see == null && paras.Count == 0)
                {
                    description.AddRange(MamlGenerator.ToParagraphs(returnElement.Value?.Trim()));
                }
                else
                {
                    foreach (var list in paras)
                    {
                        description.AddRange(list);
                    }
                }

                if (see == null || !see.HasAttributes)
                {
                    var first = description[0];
                    description.RemoveAt(0);
                    returnValues.Add(
                        new CommandValue
                    {
                        DataType    = { Name = first },
                        Description = description
                    }
                        );
                    continue;
                }

                returnValues.Add(
                    new CommandValue
                {
                    DataType =
                    {
                        Name        = see.Attribute("cref")?.Value?.Trim() ?? string.Empty,
                        Uri         = see.Attribute("uri")?.Value?.Trim(),
                        Description = MamlGenerator.ToParagraphs(see.Value?.Trim())
                    },
                    Description = description
                }
                    );
            }

            return(returnValues);
        }
Esempio n. 9
0
        /// <summary>
        ///     Extract the examples for a Cmdlet parameter.
        /// </summary>
        /// <param name="cmdletType">
        ///     The CLR type that implements the Cmdlet.
        /// </param>
        /// <returns>
        ///     A list of example, which may be empty.
        /// </returns>
        public List <CommandExample> GetCmdletExamples(TypeInfo cmdletType)
        {
            if (cmdletType == null)
            {
                throw new ArgumentNullException(nameof(cmdletType));
            }

            var assemblyDoc = GetAssemblyDocumentation(cmdletType);

            if (assemblyDoc == null)
            {
                return(null);
            }
            var rawExamples = assemblyDoc.GetExamples(cmdletType);

            var examples = new List <CommandExample>();

            foreach (var example in rawExamples)
            {
                var para = example.Elements("para");

                var descriptions = para.Where(e => e.Attribute("type")?.Value == "description").Select(e => MamlGenerator.ToParagraphs(e.Value.Trim()));
                var description  = new List <string>();
                foreach (var d in descriptions)
                {
                    description.AddRange(d);
                }

                var remarks = para.Where(e => e.Attribute("type")?.Value != "description").Select(e => MamlGenerator.ToParagraphs(e.Value.Trim()));
                var remark  = new List <string>();
                foreach (var r in remarks)
                {
                    remark.AddRange(r);
                }

                examples.Add(
                    new CommandExample
                {
                    Title       = example.Element("title")?.Value.Trim() ?? "Example",
                    Description = description,
                    Code        = string.Join("\n", example.Elements("code")?.InDocumentOrder().Select(e => e.Value)),
                    Remarks     = remark
                }
                    );
            }

            return(examples);
        }
Esempio n. 10
0
        public void GenerateXml_From_Cmdlet()
        {
            string expected = @"
<?xml version=""1.0"" encoding=""utf-16""?>
<command:command xmlns:maml=""http://schemas.microsoft.com/maml/2004/10"" xmlns:dev=""http://schemas.microsoft.com/maml/dev/2004/10"" xmlns:command=""http://schemas.microsoft.com/maml/dev/command/2004/10"">
  <command:details>
    <command:name>Get-Greeting</command:name>
    <maml:description>
      <maml:para>A simple Cmdlet that outputs a greeting to the pipeline</maml:para>
    </maml:description>
    <command:verb>Get</command:verb>
    <command:noun>Greeting</command:noun>
  </command:details>
  <maml:description>
    <maml:para>This Cmdlet works with greetings.</maml:para>
    <maml:para>It gets them.</maml:para>
    <maml:para>I can't see how to make it any clearer than that.</maml:para>
  </maml:description>
  <command:syntax>
    <command:syntaxItem>
      <maml:name>Get-Greeting</maml:name>
      <command:parameter required=""true"" variableLength=""true"" globbing=""false"" pipelineInput=""false"" position=""named"" aliases=""none"">
        <maml:name>Name</maml:name>
        <maml:description>
          <maml:para>The name of the person to greet</maml:para>
        </maml:description>
        <command:parameterValue required=""true"" variableLength=""false"">String</command:parameterValue>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required=""false"" variableLength=""true"" globbing=""false"" pipelineInput=""true (ByPropertyName, FromRemainingArguments)"" position=""named"" aliases=""Honorific"">
        <maml:name>Title</maml:name>
        <maml:description>
          <maml:para>Title of the person to greet, sans period.</maml:para>
        </maml:description>
        <command:parameterValue required=""true"" variableLength=""false"">String</command:parameterValue>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required=""true"" variableLength=""true"" globbing=""false"" pipelineInput=""true (ByValue)"" position=""named"" aliases=""none"">
        <maml:name>Greeting</maml:name>
        <maml:description>
          <maml:para>The last greeting to use.</maml:para>
        </maml:description>
        <command:parameterValue required=""true"" variableLength=""false"">String</command:parameterValue>
        <dev:defaultValue>Hello</dev:defaultValue>
      </command:parameter>
    </command:syntaxItem>
    <command:syntaxItem>
      <maml:name>Get-Greeting</maml:name>
      <command:parameter required=""true"" variableLength=""true"" globbing=""false"" pipelineInput=""false"" position=""named"" aliases=""none"">
        <maml:name>Name</maml:name>
        <maml:description>
          <maml:para>The name of the person to greet</maml:para>
        </maml:description>
        <command:parameterValue required=""true"" variableLength=""false"">String</command:parameterValue>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required=""false"" variableLength=""true"" globbing=""false"" pipelineInput=""true (ByPropertyName, FromRemainingArguments)"" position=""named"" aliases=""Honorific"">
        <maml:name>Title</maml:name>
        <maml:description>
          <maml:para>Title of the person to greet, sans period.</maml:para>
        </maml:description>
        <command:parameterValue required=""true"" variableLength=""false"">String</command:parameterValue>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required=""true"" variableLength=""true"" globbing=""false"" pipelineInput=""true (ByValue)"" position=""named"" aliases=""none"">
        <maml:name>Greeting</maml:name>
        <maml:description>
          <maml:para>The last greeting to use.</maml:para>
        </maml:description>
        <command:parameterValue required=""true"" variableLength=""false"">String</command:parameterValue>
        <dev:defaultValue>Hello</dev:defaultValue>
      </command:parameter>
    </command:syntaxItem>
  </command:syntax>
  <command:parameters>
    <command:parameter required=""true"" variableLength=""true"" globbing=""false"" pipelineInput=""false"" position=""named"" aliases=""none"">
      <maml:name>Name</maml:name>
      <maml:description>
        <maml:para>The name of the person to greet</maml:para>
      </maml:description>
      <command:parameterValue required=""true"" variableLength=""false"">String</command:parameterValue>
      <dev:defaultValue>None</dev:defaultValue>
    </command:parameter>
    <command:parameter required=""false"" variableLength=""true"" globbing=""false"" pipelineInput=""true (ByPropertyName, FromRemainingArguments)"" position=""named"" aliases=""Honorific"">
      <maml:name>Title</maml:name>
      <maml:description>
        <maml:para>Title of the person to greet, sans period.</maml:para>
      </maml:description>
      <command:parameterValue required=""true"" variableLength=""false"">String</command:parameterValue>
      <dev:defaultValue>None</dev:defaultValue>
    </command:parameter>
    <command:parameter required=""true"" variableLength=""true"" globbing=""false"" pipelineInput=""true (ByValue)"" position=""named"" aliases=""none"">
      <maml:name>Greeting</maml:name>
      <maml:description>
        <maml:para>The last greeting to use.</maml:para>
      </maml:description>
      <command:parameterValue required=""true"" variableLength=""false"">String</command:parameterValue>
      <dev:defaultValue>Hello</dev:defaultValue>
    </command:parameter>
  </command:parameters>
  <command:inputTypes />
  <command:returnValues />
  <command:examples />
</command:command>
            ".Trim();

            Command cmdletHelp = new MamlGenerator().Generate(
                typeof(SampleModule.GetGreeting)
                );

            XmlSerializerNamespaces namespacesWithPrefix = Constants.XmlNamespace.GetStandardPrefixes();
            XmlSerializer           serializer           = new XmlSerializer(typeof(Command));

            string actual;

            using (StringWriter writer = new StringWriter {
                NewLine = "\n"
            })
            {
                serializer.Serialize(writer, cmdletHelp, namespaces: namespacesWithPrefix);
                writer.Flush();

                actual = writer.ToString();
            }
            using (var k = new StreamWriter(@"C:\BHK\out.txt"))
            {
                k.Write(actual);
                k.Flush();
            }

            Assert.Equal(expected, actual);
        }