in tools/apiview/parsers/swagger-api-parser/SwaggerApiParser/SwaggerTokenSerializer.cs [606:709]
private void VisitObject(JsonElement obj, SwaggerTree nav, string navigationIdPrefix, string scopeStart = "{", string scopeEnd = "}")
{
bool multiLine = !FitsOnOneLine(obj);
using (_writer.Scope(scopeStart, scopeEnd, multiLine))
{
// Optionally sort the values
IEnumerable<JsonProperty> values = obj.EnumerateObject();
if (nav?.IsRoot != true)
{
values = nav?.IsPath == true ? values.OrderBy(p => GetString(p.Value, "operationId") ?? p.Name, new OperationComparer()) : values.OrderBy(p => p.Name);
}
Fenceposter fencepost = new();
// Generate the listing for each property
foreach (JsonProperty property in values)
{
Boolean IsCurObjCollapsible()
{
bool isPathScope = nav is { Text: "paths" or "x-ms-paths" };
bool isMethod = nav is { IsPath: true };
bool isDefinition = nav is { Text: "definitions" };
bool isMethodParameters = nav is { Parent: { IsPath: true } } && property.Name == "parameters";
bool isXmsExamples = nav is { Parent: { IsPath: true } } && property.Name == "x-ms-examples";
bool isResponses = nav is { Text: "responses" };
bool isParameters = nav is { Text: "parameters" };
bool isSecurityDefinitions = nav is { Text: "securityDefinitions" };
return isPathScope || isDefinition || isParameters || isSecurityDefinitions;
}
// Add the property to the current path
_path.Add(property.Name);
var isCollapsible = IsCurObjCollapsible();
// Write the property name
_writer.Write(CodeFileTokenKind.Punctuation, "\"");
var propertyType = isCollapsible ? CodeFileTokenKind.TypeName : CodeFileTokenKind.MemberName;
_writer.Write(propertyType, property.Name);
// Create an ID for this property
var idPrefix = navigationIdPrefix.Length == 0 ? "" : $"{navigationIdPrefix}_";
string id = $"{idPrefix}{string.Join('-', _path).TrimStart('#')}";
_writer.AnnotateDefinition(id);
if (isCollapsible)
{
_writer.Write(CodeFileTokenKind.FoldableSectionHeading, id);
}
// Optionally add a navigation tree node
SwaggerTree next = null;
if (nav?.HasNavigableChildren == true || (nav?.Parent.IsPath == true && property.Name is "responses" or "parameters"))
{
string name = property.Name;
string longText = property.Name;
if (nav.IsPath)
{
name = GetString(property.Value, "operationId") ?? name;
}
next = nav.Add(name, id, null);
}
// Visit the value
if (isCollapsible)
{
_writer.Write(CodeFileTokenKind.Punctuation, "\": ");
this._writer.WriteLine();
this._writer.Write(CodeFileTokenKind.FoldableSectionContentStart, null);
Visit(property.Value, next, navigationIdPrefix);
if (property.Name != values.Last().Name)
{
_writer.Write(CodeFileTokenKind.Punctuation, ", ");
if (multiLine) { _writer.WriteLine(); }
}
this._writer.Write(CodeFileTokenKind.FoldableSectionContentEnd, null);
}
else
{
_writer.Write(CodeFileTokenKind.Punctuation, "\": ");
Visit(property.Value, next, navigationIdPrefix);
if (property.Name != values.Last().Name)
{
_writer.Write(CodeFileTokenKind.Punctuation, ", ");
if (multiLine) { _writer.WriteLine(); }
}
}
// Make $refs linked
if (property.Name == "$ref" &&
property.Value.ValueKind == JsonValueKind.String &&
property.Value.GetString().StartsWith("#/")) // Ignore external docs
{
_writer.AnnotateLink($"{idPrefix}{property.Value.GetString().TrimStart('#').Replace('/', '-')}", CodeFileTokenKind.StringLiteral);
}
// Remove the property from the current path
_path.RemoveAt(_path.Count - 1);
}
}
}