Skip to content

Commit

Permalink
Updates to permissions tables generation (#284)
Browse files Browse the repository at this point in the history
* Account for HTML annotations that are differently formatted

* Add check to identify permissions block from annotations

* Simplify how we compute where to start looking for the next permissions table after finding the first one
  • Loading branch information
millicentachieng authored Aug 8, 2024
1 parent bf8d5c7 commit 7b6c9ce
Showing 1 changed file with 83 additions and 49 deletions.
132 changes: 83 additions & 49 deletions ApiDoctor.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2034,7 +2034,8 @@ private static string GenerateSnippetsTabSectionForMethod(MethodDefinition metho
{
sampleCodeIncludeText = $"[!INCLUDE [sample-code](../{ReplaceWindowsByLinuxPathSeparators(Path.Combine(relativePathFolder, codeFenceString, versionString, snippetFileName))})]";
}
else{
else
{
sampleCodeIncludeText = $"[!INCLUDE [sample-code](../{ReplaceWindowsByLinuxPathSeparators(Path.Combine(relativePathFolder, codeFenceString, snippetFileName))})]";
}
var tabText = $"# [{language}](#tab/{codeFenceString})\r\n" +
Expand All @@ -2047,7 +2048,7 @@ private static string GenerateSnippetsTabSectionForMethod(MethodDefinition metho
if (codeSnippet != null)
{
var snippetFileContents = "---\r\ndescription: \"Automatically generated file. DO NOT MODIFY\"\r\n---\r\n\r\n" + //header
$"```{codeFenceString.Replace("cli","bash")}\r\n\r\n" + // code fence
$"```{codeFenceString.Replace("cli", "bash")}\r\n\r\n" + // code fence
$"{codeSnippet}\r\n\r\n" + // generated code snippet
"```"; // closing fence

Expand Down Expand Up @@ -2645,8 +2646,8 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
int foundPermissionTablesOrBlocks = 0, foundHttpRequestBlocks = 0;
bool finishedParsing = false, isBootstrapped = false, ignorePermissionTableUpdate = false,
foundAllPermissionTables = false, mergePermissions = false;
int insertionStartLine = -1, insertionEndLine = -1, httpRequestStartLine = -1, httpRequestEndLine = -1,
boilerplateStartLine = -1, boilerplateEndLine = -1, permissionsHeaderIndex = -1, codeBlockAnnotationEndLine = -1;
int insertionStartLine = -1, insertionEndLine = -1, httpRequestStartLine = -1, httpRequestEndLine = -1, boilerplateStartLine = -1,
boilerplateEndLine = -1, permissionsHeaderIndex = -1, codeBlockAnnotationEndLine = -1, permissionsBlockLineCount = -1;
string[] requestUrlsForPermissions = null;
for (var currentIndex = 0; currentIndex < originalFileContents.Length && !finishedParsing; currentIndex++)
{
Expand All @@ -2666,33 +2667,10 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
ignorePermissionTableUpdate = true;
}

// Extract HTML comment
if (codeBlockAnnotationEndLine != -1 && (requestUrlsForPermissions != null || !mergePermissions))
{
var htmlComment = insertionStartLine == codeBlockAnnotationEndLine
? originalFileContents[insertionStartLine]
: string.Join(" ", originalFileContents.Skip(insertionStartLine).Take(codeBlockAnnotationEndLine + 1 - insertionStartLine));
var metadataJsonString = DocFile.StripHtmlCommentTags(htmlComment);
var annotation = CodeBlockAnnotation.ParseMetadata(metadataJsonString);
requestUrlsForPermissions = annotation?.RequestUrls;
mergePermissions = annotation?.MergePermissions ?? false;
}

if (currentLine.StartsWith("<!-- {") || currentLine.Contains("<!--{"))
{
insertionStartLine = currentIndex;
if (currentLine.Contains("} -->") || currentLine.Contains("}-->"))
{
codeBlockAnnotationEndLine = currentIndex;
}
}
else if (currentLine.Contains("} -->") || currentLine.Contains("}-->"))
{
codeBlockAnnotationEndLine = currentIndex;
}
else if (currentLine.Contains("[!INCLUDE [permissions-table](", StringComparison.OrdinalIgnoreCase)) // bootstrapping already took place
if (currentLine.Contains("[!INCLUDE [permissions-table](", StringComparison.OrdinalIgnoreCase)) // bootstrapping already took place
{
foundPermissionTablesOrBlocks++;
insertionEndLine = currentIndex; // [!INCLUDE [permissions-table]... is the end of the insertion block
if (ignorePermissionTableUpdate)
{
FancyConsole.WriteLine(ConsoleColor.Yellow, $"Skipping update of permissions table ({foundPermissionTablesOrBlocks}) in {docFile.DisplayName}");
Expand All @@ -2701,13 +2679,65 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
}

isBootstrapped = true;

if (!options.BootstrappingOnly)
{
insertionEndLine = currentIndex; // [!INCLUDE [permissions-table]... is the end of the insertion block
parseStatus = (requestUrlsForPermissions?.Length ?? 0) == 0
? PermissionsInsertionState.FindHttpRequestHeading
: PermissionsInsertionState.InsertPermissionBlock;
break;
// find the permissions block start line
var previousContents = "";
for (var i = currentIndex - 1; i > 0; i--)
{
var lineContents = originalFileContents[i].Trim();
if (lineContents.EndsWith("-->"))
{
codeBlockAnnotationEndLine = i;
}
if (lineContents.StartsWith("<!--") && (lineContents[4..].Trim().StartsWith('{') || previousContents.StartsWith('{')))
{
insertionStartLine = i;
parseStatus = PermissionsInsertionState.FindHttpRequestHeading;
break;
}
previousContents = lineContents;
}

// Extract HTML comment
if (codeBlockAnnotationEndLine != -1 && insertionStartLine != -1)
{
var htmlComment = insertionStartLine == codeBlockAnnotationEndLine
? originalFileContents[insertionStartLine]
: string.Join(" ", originalFileContents.Skip(insertionStartLine).Take(codeBlockAnnotationEndLine + 1 - insertionStartLine));
var metadataJsonString = DocFile.StripHtmlCommentTags(htmlComment);
try
{
var annotation = CodeBlockAnnotation.ParseMetadata(metadataJsonString);
if (annotation.BlockType == CodeBlockType.Permissions)
{
requestUrlsForPermissions = annotation?.RequestUrls;
mergePermissions = annotation?.MergePermissions ?? false;
}
else // Something's wrong with the metadata
{
ignorePermissionTableUpdate = true;
parseStatus = PermissionsInsertionState.FindNextPermissionBlock;
FancyConsole.WriteLine(ConsoleColor.Red, $"The HTML metadata for permissions table({foundPermissionTablesOrBlocks}) in {docFile.DisplayName} is wrong)");
break;
}
}
catch (Exception ex)
{
ignorePermissionTableUpdate = true;
parseStatus = PermissionsInsertionState.FindNextPermissionBlock;
FancyConsole.WriteLine(ConsoleColor.Red, $"Unable to parse permissions block metadata in '{docFile.DisplayName}', line: {insertionStartLine + 1}", ex);
break;
}
}
else
{
// If we are here, the metadata for the permissions table is missing or incomplete. Aim to add it.
codeBlockAnnotationEndLine = insertionStartLine = currentIndex;
parseStatus = PermissionsInsertionState.FindHttpRequestHeading;
break;
}
}
}
else if (currentLine.Contains('|') && currentLine.Contains("Permission type", StringComparison.OrdinalIgnoreCase)) // found the permissions table
Expand All @@ -2730,12 +2760,12 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
for (int index = permissionsHeaderIndex + 1; index < currentIndex; index++)
{
// if the line is not empty and is not a sub header, this is the boilerplate start line
if (!string.IsNullOrWhiteSpace(originalFileContents[index]) && !originalFileContents[index].StartsWith('#'))
{
if (!string.IsNullOrWhiteSpace(originalFileContents[index]) && !originalFileContents[index].StartsWith('#'))
{
if (boilerplateStartLine == permissionsHeaderIndex)
boilerplateStartLine = index;
boilerplateEndLine = index;
}
}
}
}
}
Expand Down Expand Up @@ -2826,7 +2856,7 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
if (!isBootstrapped)
{
var existingPermissionsTable = originalFileContents.Skip(insertionStartLine + 2).Take(insertionEndLine - insertionStartLine - 1);
permissionFileContents = $"{includeFileMetadata}{ConvertToThreeColumnPermissionsTable(existingPermissionsTable)}";
permissionFileContents = $"{includeFileMetadata}{ConvertToThreeColumnPermissionsTable(existingPermissionsTable)}";
}

if (!options.BootstrappingOnly)
Expand All @@ -2843,7 +2873,7 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
var httpRequests = (requestUrlsForPermissions?.Length ?? 0) != 0
? requestUrlsForPermissions
: originalFileContents.Skip(httpRequestStartLine + 1).Take(httpRequestEndLine - httpRequestStartLine - 1).Where(x => !string.IsNullOrWhiteSpace(x));
var newPermissionFileContents = GetPermissionsMarkdownTableForHttpRequestBlock(permissionsDocument, httpRequests,
var newPermissionFileContents = GetPermissionsMarkdownTableForHttpRequestBlock(permissionsDocument, httpRequests,
mergePermissions, docFile.DisplayName, foundPermissionTablesOrBlocks); // get from Kibali
if (!string.IsNullOrWhiteSpace(newPermissionFileContents))
{
Expand All @@ -2868,15 +2898,16 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
if (foundPermissionTablesOrBlocks == 1)
{
// We do not have a boilerplate text in this case, add new next line
if(boilerplateStartLine == permissionsHeaderIndex)
if (boilerplateStartLine == permissionsHeaderIndex)
{
// insert a new line to hold boilerplate text
originalFileContents = FileSplicer(originalFileContents, boilerplateStartLine, Constants.PermissionConstants.DefaultBoilerPlateText).ToArray();
boilerplateStartLine++;
insertionStartLine++;
insertionEndLine++;
}
else {
else
{
if (boilerplateEndLine > boilerplateStartLine)
{
int extraLinesToRemove = boilerplateEndLine - boilerplateStartLine;
Expand All @@ -2887,7 +2918,8 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
originalFileContents[boilerplateStartLine] = Constants.PermissionConstants.DefaultBoilerPlateText;
}
}
else if (foundPermissionTablesOrBlocks == 2) {
else if (foundPermissionTablesOrBlocks == 2)
{
originalFileContents[boilerplateStartLine] = Constants.PermissionConstants.MultipleTableBoilerPlateText;
}
}
Expand All @@ -2908,7 +2940,8 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
await File.WriteAllTextAsync(permissionsMarkdownFilePath, permissionFileContents);

// insert permissions block text into doc file
var permissionsBlockText = GeneratePermissionsBlockText(docFileName, Path.Combine(permissionsFileRelativePath, permissionsFileName), requestUrlsForPermissions, mergePermissions);
var permissionsBlockText = GeneratePermissionsBlockText(docFileName, Path.Combine(permissionsFileRelativePath, permissionsFileName), requestUrlsForPermissions, mergePermissions);
permissionsBlockLineCount = permissionsBlockText.Split(Environment.NewLine).Length;
IEnumerable<string> updatedFileContents = originalFileContents;
updatedFileContents = updatedFileContents.Splice(insertionStartLine, insertionEndLine + 1 - insertionStartLine);
updatedFileContents = FileSplicer(updatedFileContents.ToArray(), insertionStartLine - 1, permissionsBlockText);
Expand All @@ -2919,11 +2952,12 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
if (!ignorePermissionTableUpdate)
{
var newFileContents = await File.ReadAllLinesAsync(docFile.FullPath);
currentIndex = newFileContents.Length == originalFileContents.Length
currentIndex = newFileContents.Length == originalFileContents.Length
? insertionEndLine
: codeBlockAnnotationEndLine - (originalFileContents.Length - newFileContents.Length) + 1;
: insertionStartLine + permissionsBlockLineCount - 1;
originalFileContents = newFileContents;
insertionStartLine = insertionEndLine = httpRequestStartLine = httpRequestEndLine = codeBlockAnnotationEndLine = - 1;
insertionStartLine = insertionEndLine = httpRequestStartLine = httpRequestEndLine =
codeBlockAnnotationEndLine = permissionsBlockLineCount = -1;
mergePermissions = false;
requestUrlsForPermissions = null;
foundHttpRequestBlocks = 0;
Expand Down Expand Up @@ -2996,11 +3030,11 @@ private static string GeneratePermissionsBlockText(string docFileName, string pe
return permissionsBlockText;
}

private static string GetPermissionsMarkdownTableForHttpRequestBlock(PermissionsDocument permissionsDocument, IEnumerable<string> httpRequests, bool mergePermissions,
private static string GetPermissionsMarkdownTableForHttpRequestBlock(PermissionsDocument permissionsDocument, IEnumerable<string> httpRequests, bool mergePermissions,
string docFileName, int permissionsTablePosition)
{
var requestPaths = new List<HttpRequest>();

// check validity of request paths
foreach (var request in httpRequests)
{
Expand Down Expand Up @@ -3051,7 +3085,7 @@ private static string GetPermissionsMarkdownTableForHttpRequestBlock(Permissions
var requestPermissions = generator.GenerateTable();
newPermissionFileContents ??= requestPermissions;

if (!newPermissionFileContents.Equals(requestPermissions, StringComparison.OrdinalIgnoreCase))
if (!newPermissionFileContents.Equals(requestPermissions, StringComparison.OrdinalIgnoreCase))
{
FancyConsole.WriteLine(ConsoleColor.Yellow, $"Encountered request URL(s) for permissions table ({permissionsTablePosition}) in {docFileName} with a different set of permissions");
}
Expand Down

0 comments on commit 7b6c9ce

Please sign in to comment.