Skip to content

Commit e254cbb

Browse files
authored
Fix issues scanning for aliases in markdown. (#690)
Aliases are not a list, but unparsed markdown. Add some improved diagnostics for parsing yaml (more to do here) Improve diagnostics for alias scanning in markdown. Fix an issue in SyntaxItem parameter sorting to handle cases where a position may not be know (such as command help as generated by MAML). Change yaml serialization for aliases to use yaml serializer. Add copyright to exportyamlmodulefile tests. Add a new get-childitem v2 help file for testing aliases.
1 parent 8271054 commit e254cbb

File tree

9 files changed

+1328
-33
lines changed

9 files changed

+1328
-33
lines changed

src/Command/Update-CommandHelp.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,13 @@ CommandHelp Merge(CommandHelp fromMarkdown, CommandHelp fromCmdlet)
113113
syntaxDiagnostics.ForEach(d => helpCopy.Diagnostics.TryAddDiagnostic(d));
114114

115115
// Alias - there are no aliases to be found in the cmdlet, but we shouldn't add the boiler plate.
116+
// If the boiler plate is found, we'll clear the aliases.
116117
helpCopy.AliasHeaderFound = true;
118+
if (helpCopy.Aliases.Any(s => s.IndexOf(Constants.AliasMessage2, StringComparison.OrdinalIgnoreCase) >= 0))
119+
{
120+
helpCopy.Aliases?.Clear();
121+
}
122+
117123

118124
// Parameters
119125
if (TryGetMergedParameters(helpCopy.Parameters, fromCmdlet.Parameters, out var mergedParametersList, out var paramDiagnostics))

src/Common/YamlUtils.cs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,33 +185,55 @@ internal static CommandHelp ConvertDictionaryToCommandHelp(OrderedDictionary? di
185185
if (dictionary["metadata"] is IDictionary<object, object> metadata)
186186
{
187187
help.Metadata = GetMetadataFromDictionary(metadata);
188+
help.Diagnostics.TryAddDiagnostic(DiagnosticMessageSource.General, "Found Metadata", DiagnosticSeverity.Information, "yaml metadata", -1);
188189
}
189190

190191
if (dictionary["synopsis"] is string synopsis)
191192
{
193+
help.Diagnostics.TryAddDiagnostic(DiagnosticMessageSource.Synopsis, $"Synopsis length: {synopsis.Length} ", DiagnosticSeverity.Information, "yaml synopsis", -1);
192194
help.Synopsis = synopsis;
193195
}
196+
else
197+
{
198+
help.Diagnostics.TryAddDiagnostic(DiagnosticMessageSource.Synopsis, "No synopsis", DiagnosticSeverity.Warning, "yaml synopsis", -1);
199+
}
194200

195201
if (dictionary["title"] is string title)
196202
{
203+
help.Diagnostics.TryAddDiagnostic(DiagnosticMessageSource.General, $"Title length: {title.Length} ", DiagnosticSeverity.Information, "yaml title", -1);
197204
help.Title = title;
198205
}
206+
else
207+
{
208+
help.Diagnostics.TryAddDiagnostic(DiagnosticMessageSource.General, "No title", DiagnosticSeverity.Warning, "yaml title", -1);
209+
}
199210

200211
if (dictionary["description"] is string description)
201212
{
213+
help.Diagnostics.TryAddDiagnostic(DiagnosticMessageSource.Description, $"Description length: {description.Length} ", DiagnosticSeverity.Information, "yaml description", -1);
202214
help.Description = description;
203215
}
216+
else
217+
{
218+
help.Diagnostics.TryAddDiagnostic(DiagnosticMessageSource.Description, "No description", DiagnosticSeverity.Warning, "yaml description", -1);
219+
}
204220

205221
if (dictionary["notes"] is string notes)
206222
{
223+
help.Diagnostics.TryAddDiagnostic(DiagnosticMessageSource.Notes, $"notes length: {notes.Length} ", DiagnosticSeverity.Information, "yaml notes", -1);
207224
help.Notes = notes;
208225
}
209226
else
210227
{
228+
help.Diagnostics.TryAddDiagnostic(DiagnosticMessageSource.Notes, "No description", DiagnosticSeverity.Information, "yaml notes", -1);
211229
help.Notes = string.Empty;
212230
}
213231

214232
help.Syntax.AddRange(GetSyntaxFromDictionary(dictionary));
233+
if (help.Aliases is not null)
234+
{
235+
help.Aliases.AddRange(GetAliasesFromDictionary(dictionary));
236+
}
215237
help.Examples?.AddRange(GetExamplesFromDictionary(dictionary));
216238
help.Parameters.AddRange(GetParametersFromDictionary(dictionary));
217239
help.Inputs.AddRange(GetInputsFromDictionary(dictionary));
@@ -225,9 +247,6 @@ internal static CommandHelp ConvertDictionaryToCommandHelp(OrderedDictionary? di
225247
if (help.Metadata is not null)
226248
{
227249
help.ModuleGuid = help.Metadata.Contains("ModuleGuid") ? new Guid(help.Metadata["ModuleGuid"].ToString()) : null;
228-
// help.ExternalHelpFile = help.Metadata.Contains("external help file") ? help.Metadata["external help file"].ToString() : string.Empty;
229-
// help.OnlineVersionUrl = help.Metadata.Contains("HelpUri") ? help.Metadata["HelpUri"].ToString() : string.Empty;
230-
// help.SchemaVersion = help.Metadata.Contains("PlatyPS schema version") ? help.Metadata["PlatyPS schema version"].ToString() : string.Empty;
231250
help.ModuleName = help.Metadata.Contains("Module Name") ? help.Metadata["Module Name"].ToString() : string.Empty;
232251
}
233252

@@ -559,6 +578,19 @@ private static List<Links> GetRelatedLinksFromDictionary(OrderedDictionary dicti
559578
return links;
560579
}
561580

581+
private static List<string> GetAliasesFromDictionary(OrderedDictionary dictionary)
582+
{
583+
List<string> aliases = new();
584+
if (dictionary["aliases"] is List<object> aliasList)
585+
{
586+
foreach(var alias in aliasList)
587+
{
588+
aliases.Add(alias.ToString());
589+
}
590+
}
591+
return aliases;
592+
}
593+
562594
private static List<Example> GetExamplesFromDictionary(OrderedDictionary dictionary)
563595
{
564596
List<Example> examples = new();

src/MarkdownReader/CommandHelpMarkdownReader.cs

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -746,8 +746,14 @@ internal static List<string> GetAliasesFromMarkdown(ParsedMarkdownContent markdo
746746
return new List<string>();
747747
}
748748

749-
var aliasList = GetAliases(markdownContent.Ast, start + 1);
750-
diagnostics.Add(new DiagnosticMessage(DiagnosticMessageSource.Alias, "ALIASES header found", DiagnosticSeverity.Information, $"{aliasList.Count} aliases found", markdownContent.GetTextLine(start)));
749+
var end = markdownContent.FindHeader(2, string.Empty);
750+
751+
var aliasList = GetAliases(markdownContent, start + 1);
752+
diagnostics.Add(new DiagnosticMessage(DiagnosticMessageSource.Alias, "ALIASES header found", DiagnosticSeverity.Information, $"{aliasList.Count} alias strings found", markdownContent.GetTextLine(start)));
753+
int totalAliasLength = 0;
754+
aliasList.ForEach(a => totalAliasLength += a.Length);
755+
diagnostics.Add(new DiagnosticMessage(DiagnosticMessageSource.Alias, "Alias string length", DiagnosticSeverity.Information, $"alias string length: {totalAliasLength}", markdownContent.GetTextLine(start+1)));
756+
751757
aliasHeaderFound = true;
752758
return aliasList;
753759
}
@@ -787,32 +793,15 @@ internal static string GetSynopsisFromMarkdown(ParsedMarkdownContent markdownCon
787793
}
788794

789795
// Avoid turning boilerplate into an alias
790-
internal static List<string> GetAliases(MarkdownDocument md, int startIndex)
796+
internal static List<string> GetAliases(ParsedMarkdownContent md, int startIndex)
791797
{
792798
List<string> aliases = new List<string>();
793799

794-
while (md[startIndex] is not HeadingBlock)
800+
var lines = GetLinesTillNextHeader(md, 2, startIndex);
801+
// don't include the boilerplate
802+
if (lines.IndexOf(Constants.AliasMessage2) == -1)
795803
{
796-
if (md[startIndex] is ParagraphBlock pb)
797-
{
798-
var item = pb?.Inline?.FirstChild;
799-
800-
while (item != null)
801-
{
802-
if (item is LiteralInline line)
803-
{
804-
var alias = line.ToString();
805-
if (! ContainsAliasBoilerPlate(alias))
806-
{
807-
aliases.Add(alias);
808-
}
809-
}
810-
811-
item = item.NextSibling;
812-
}
813-
}
814-
815-
startIndex++;
804+
aliases.Add(lines);
816805
}
817806

818807
return aliases;

src/Model/SyntaxItem.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public void SortParameters()
114114

115115
if (positionList.Count > 0)
116116
{
117-
sortedList.AddRange(positionList.OrderBy(p => int.Parse(p.Position)));
117+
sortedList.AddRange(positionList.OrderBy(p => int.TryParse(p.Position, out var pos) ? pos : int.MaxValue));
118118
}
119119

120120
if (mandatoryList.Count > 0)

src/YamlWriter/CommandHelpYamlWriter.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,10 @@ internal override void WriteAliases(CommandHelp help)
117117
{
118118
if (help.Aliases?.Count > 0)
119119
{
120-
string aliasString = string.Join(", ", help.Aliases);
121-
sb.AppendLine($"{Constants.yamlAliasHeader} {aliasString}");
120+
Hashtable aliasHash = new();
121+
aliasHash.Add("aliases", help.Aliases);
122+
string aliasString = YamlUtils.SerializeElement(aliasHash).Trim();
123+
sb.AppendLine(aliasString);
122124
}
123125
else
124126
{

test/Pester/ExportYamlModuleFile.Tests.ps1

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
14
Describe "Export-YamlModuleFile tests" {
25
BeforeAll {
36
$moduleFileNames = "Microsoft.PowerShell.Archive.md", "Microsoft.PowerShell.Core.md",
@@ -69,4 +72,4 @@ Describe "Export-YamlModuleFile tests" {
6972
$observed | Should -Be $expected
7073
}
7174
}
72-
}
75+
}

test/Pester/MeasurePlatyPSMarkdown.Tests.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ Describe "Export-MarkdownModuleFile" {
1313

1414
It "Should identify all the '<fileType>' assets" -TestCases @(
1515
@{ fileType = "unknown"; expectedCount = 2 }
16-
@{ fileType = "CommandHelp"; expectedCount = 32 }
16+
@{ fileType = "CommandHelp"; expectedCount = 33 }
1717
@{ fileType = "ModuleFile"; expectedCount = 14 }
1818
@{ fileType = "V1Schema"; expectedCount = 45 }
19-
@{ fileType = "V2Schema"; expectedCount = 1 }
19+
@{ fileType = "V2Schema"; expectedCount = 2 }
2020
) {
2121
param ($fileType, $expectedCount)
2222
$idents.Where({($_.FileType -band $fileType) -eq $fileType}).Count | Should -Be $expectedCount
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
Describe "Miscellaneous tests" {
5+
Context "Alias preservation" {
6+
BeforeAll {
7+
$cmdHelpPath = [io.path]::Combine($PSScriptRoot, "assets", "Get-ChildItem.V2.md")
8+
$ch_md = Import-MarkdownCommandHelp $cmdHelpPath
9+
$fPath = $ch_md | Export-YamlCommandHelp -output $TESTDRIVE -Force
10+
$ch_yaml = Import-YamlCommandHelp $fPath
11+
}
12+
13+
It "Should preserve the aliases" {
14+
$ch_md.Aliases | Should -Not -BeNullOrEmpty
15+
$ch_md.Aliases | Should -Be $ch_yaml.Aliases
16+
}
17+
18+
It "Should have the correct diagnostic message from the markdown parse" {
19+
$message = $ch_md.Diagnostics.Messages.Where({$_.source -eq "alias" -and $_.Identifier -match "length"})
20+
$message | Should -Not -BeNullOrEmpty
21+
$message.Identifier | Should -Match "118"
22+
}
23+
24+
}
25+
}

0 commit comments

Comments
 (0)