Skip to content

Commit

Permalink
Make Swagger Parser Pull in Properties referenced in other files (#6009)
Browse files Browse the repository at this point in the history
  • Loading branch information
chidozieononiwu authored Apr 26, 2023
1 parent a046f15 commit b3301af
Show file tree
Hide file tree
Showing 9 changed files with 397 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ static async Task HandleGenerateCodeFile(IEnumerable<string> swaggers, string ou

foreach (var swaggerSpec in swaggerSpecs)
{
root.AddSwaggerSpec(swaggerSpec, swaggerSpec.swaggerFilePath, packageName, swaggerSpec.swaggerLink);
await root.AddSwaggerSpec(swaggerSpec, swaggerSpec.swaggerFilePath, packageName, swaggerSpec.swaggerLink);
}

var codeFile = root.GenerateCodeFile();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace SwaggerApiParser;

public class SwaggerApiViewGenerator
{
public static SwaggerApiViewSpec GenerateSwaggerApiView(SwaggerSpec swaggerSpec, string swaggerFilePath, SchemaCache schemaCache, string packageName = "", string swaggerLink = "")
public static async Task<SwaggerApiViewSpec> GenerateSwaggerApiView(SwaggerSpec swaggerSpec, string swaggerFilePath, SchemaCache schemaCache, string packageName = "", string swaggerLink = "")
{
SwaggerApiViewSpec ret = new SwaggerApiViewSpec
{
Expand Down Expand Up @@ -70,6 +71,7 @@ public static SwaggerApiViewSpec GenerateSwaggerApiView(SwaggerSpec swaggerSpec,
};

if (value.parameters != null)
{
foreach (var parameter in value.parameters)
{
var param = parameter;
Expand All @@ -82,7 +84,18 @@ public static SwaggerApiViewSpec GenerateSwaggerApiView(SwaggerSpec swaggerSpec,

if (param == null)
{
continue;
if (!Path.IsPathFullyQualified(parameter.Ref))
{
var referenceSwaggerFilePath = Utils.GetReferencedSwaggerFile(parameter.Ref, currentSwaggerFilePath);
var referenceSwaggerSpec = await SwaggerDeserializer.Deserialize(referenceSwaggerFilePath);
referenceSwaggerSpec.swaggerFilePath = Path.GetFullPath(referenceSwaggerFilePath);
AddDefinitionsToCache(referenceSwaggerSpec, referenceSwaggerFilePath, schemaCache);
param = schemaCache.GetParameterFromCache(parameter.Ref, referenceSwaggerFilePath);
}
else
{
continue;
}
}

var swaggerApiViewOperationParameter = new SwaggerApiViewParameter
Expand Down Expand Up @@ -114,8 +127,6 @@ public static SwaggerApiViewSpec GenerateSwaggerApiView(SwaggerSpec swaggerSpec,
break;
}
}

{
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace SwaggerApiParser;

Expand All @@ -19,9 +20,9 @@ public SwaggerApiViewRoot(string resourceProvider, string packageName)
this.schemaCache = new SchemaCache();
}

public void AddSwaggerSpec(SwaggerSpec swaggerSpec, string swaggerFilePath, string resourceProvider = "", string swaggerLink="")
public async Task AddSwaggerSpec(SwaggerSpec swaggerSpec, string swaggerFilePath, string resourceProvider = "", string swaggerLink="")
{
var swaggerApiViewSpec = SwaggerApiViewGenerator.GenerateSwaggerApiView(swaggerSpec, swaggerFilePath, this.schemaCache, resourceProvider, swaggerLink);
var swaggerApiViewSpec = await SwaggerApiViewGenerator.GenerateSwaggerApiView(swaggerSpec, swaggerFilePath, this.schemaCache, resourceProvider, swaggerLink);

if (swaggerApiViewSpec != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,6 @@ public void AddParameter(string swaggerFilePath, string key, Parameter parameter
parameterCache.TryAdd(key, parameter);
}

private static string GetReferencedSwaggerFile(string Ref, string currentSwaggerFilePath)
{
if (string.IsNullOrEmpty(Ref))
{
return currentSwaggerFilePath;
}

var idx = Ref.IndexOf("#", StringComparison.Ordinal);
var relativePath = Ref[..idx];
if (relativePath == "")
{
relativePath = ".";
}
else
{
currentSwaggerFilePath = Path.GetDirectoryName(currentSwaggerFilePath);
}

var referenceSwaggerFilePath = Path.GetFullPath(relativePath, currentSwaggerFilePath!);
return referenceSwaggerFilePath;
}

public static string GetRefKey(string Ref)
{
var key = Ref.Split("/").Last();
Expand All @@ -79,7 +57,7 @@ public static string RemoveCrossFileReferenceFromRef(string Ref)

public static string GetResolvedCacheRefKey(string Ref, string currentSwaggerFilePath)
{
return RemoveCrossFileReferenceFromRef(Ref) + GetReferencedSwaggerFile(Ref, currentSwaggerFilePath);
return RemoveCrossFileReferenceFromRef(Ref) + Utils.GetReferencedSwaggerFile(Ref, currentSwaggerFilePath);
}

private BaseSchema GetSchemaFromResolvedCache(string Ref, string currentSwaggerFilePath)
Expand All @@ -94,7 +72,7 @@ private BaseSchema GetSchemaFromCache(string Ref, string currentSwaggerFilePath)
// try get from resolved cache.


var referenceSwaggerFilePath = GetReferencedSwaggerFile(Ref, currentSwaggerFilePath);
var referenceSwaggerFilePath = Utils.GetReferencedSwaggerFile(Ref, currentSwaggerFilePath);


this.Cache.TryGetValue(referenceSwaggerFilePath, out var swaggerSchema);
Expand All @@ -119,7 +97,7 @@ public Parameter GetParameterFromCache(string Ref, string currentSwaggerFilePath
// try get from resolved cache.


var referenceSwaggerFilePath = GetReferencedSwaggerFile(Ref, currentSwaggerFilePath);
var referenceSwaggerFilePath = Utils.GetReferencedSwaggerFile(Ref, currentSwaggerFilePath);


this.ParametersCache.TryGetValue(referenceSwaggerFilePath, out var parameterCache);
Expand Down Expand Up @@ -184,7 +162,7 @@ public BaseSchema GetResolvedSchema(BaseSchema root, string currentSwaggerFilePa
// get from original schema cache.
refChain.AddLast(GetResolvedCacheRefKey(root.Ref, currentSwaggerFilePath));
var schema = this.GetSchemaFromCache(root.Ref, currentSwaggerFilePath);
var ret = this.GetResolvedSchema(schema, GetReferencedSwaggerFile(root.Ref, currentSwaggerFilePath), refChain);
var ret = this.GetResolvedSchema(schema, Utils.GetReferencedSwaggerFile(root.Ref, currentSwaggerFilePath), refChain);
// write back resolved cache
this.ResolvedCache.TryAdd(GetResolvedCacheRefKey(root.Ref, currentSwaggerFilePath), schema);
refChain.RemoveLast();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public string GetTypeFormat()
var typeFormat = this.format != null ? $"/{this.format}" : "";


if (this.type is "array")
if (this.type is "array" && this.items is not null)
{
var reference = this.items.originalRef ?? this.items.Ref;
var arrayType = Utils.GetDefinitionType(reference) ?? this.items.type;
Expand Down Expand Up @@ -180,11 +180,10 @@ private CodeFileToken[] TokenSerializeInternal(SerializeContext context, BaseSch
TokenSerializeProperties(new SerializeContext(context.intent + 2, context.IteratorPath), schema, schema.allOfProperities, ret, ref flattenedTableItems, serializeRef);
}

if (schema.type == "array")
if (schema.type == "array" && schema.items is not null)
{
SchemaTableItem arrayItem = new SchemaTableItem {Description = schema.description};
var arrayType = schema.items.type != null ? $"array<{schema.items.type}>" : $"array<{Utils.GetDefinitionType(schema.items.originalRef)}>";
arrayItem.TypeFormat = arrayType;
arrayItem.TypeFormat = schema.items.type != null ? $"array<{schema.items.type}>" : $"array<{Utils.GetDefinitionType(schema.items.originalRef)}>";
flattenedTableItems.Add(arrayItem);
TokenSerializeArray(context, ret, schema, ref flattenedTableItems, serializeRef);
}
Expand Down
22 changes: 22 additions & 0 deletions tools/apiview/parsers/swagger-api-parser/SwaggerApiParser/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,26 @@ public static string GetRefDefinitionIdPath(string Ref)

return "";
}

public static string GetReferencedSwaggerFile(string Ref, string currentSwaggerFilePath)
{
if (string.IsNullOrEmpty(Ref))
{
return currentSwaggerFilePath;
}

var idx = Ref.IndexOf("#", StringComparison.Ordinal);
var relativePath = Ref[..idx];
if (relativePath == "")
{
relativePath = ".";
}
else
{
currentSwaggerFilePath = Path.GetDirectoryName(currentSwaggerFilePath);
}

var referenceSwaggerFilePath = Path.GetFullPath(relativePath, currentSwaggerFilePath!);
return referenceSwaggerFilePath;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public async Task TestGenerateSwaggerApiViewGroupedModelProperties()
{
var runCommandsFilePath = Path.GetFullPath("./fixtures/communicationserviceschat.json");
var swaggerSpec = await SwaggerDeserializer.Deserialize(runCommandsFilePath);
var apiView = SwaggerApiViewGenerator.GenerateSwaggerApiView(swaggerSpec, runCommandsFilePath, new SchemaCache());
var apiView = await SwaggerApiViewGenerator.GenerateSwaggerApiView(swaggerSpec, runCommandsFilePath, new SchemaCache());

var codeFile = apiView.GenerateCodeFile();
//var outputFilePath = Path.GetFullPath("./communicationserviceschat_output.json");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public async Task TestComputeOneFile()
var swaggerSpec = await SwaggerDeserializer.Deserialize(runCommandFilePath);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.Compute", "Microsoft.Compute");
root.AddSwaggerSpec(swaggerSpec, Path.GetFullPath(runCommandFilePath), "Microsoft.Compute");
await root.AddSwaggerSpec(swaggerSpec, Path.GetFullPath(runCommandFilePath), "Microsoft.Compute");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./compute_root_one_file_codefile.json");
Expand All @@ -40,7 +40,7 @@ public async Task TestMediaComposition()
var swaggerSpec = await SwaggerDeserializer.Deserialize(runCommandFilePath);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.Media", "Microsoft.Media");
root.AddSwaggerSpec(swaggerSpec, Path.GetFullPath(runCommandFilePath), "Microsoft.Media");
await root.AddSwaggerSpec(swaggerSpec, Path.GetFullPath(runCommandFilePath), "Microsoft.Media");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./media_codefile.json");
Expand All @@ -60,8 +60,8 @@ public async Task TestComputeTwoFiles()
var computeSwaggerSpec = await SwaggerDeserializer.Deserialize(computeFilePath);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.Compute", "Microsoft.Compute");
root.AddSwaggerSpec(runCommandsSwaggerSpec, Path.GetFullPath(runCommandFilePath), "Microsoft.Compute");
root.AddSwaggerSpec(computeSwaggerSpec, Path.GetFullPath(computeFilePath), "Microsoft.Compute");
await root.AddSwaggerSpec(runCommandsSwaggerSpec, Path.GetFullPath(runCommandFilePath), "Microsoft.Compute");
await root.AddSwaggerSpec(computeSwaggerSpec, Path.GetFullPath(computeFilePath), "Microsoft.Compute");


var codeFile = root.GenerateCodeFile();
Expand All @@ -79,7 +79,7 @@ public async Task TestPetStore()
var petStoreSwaggerSpec = await SwaggerDeserializer.Deserialize(petStoreFilePath);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.PetStore", "Microsoft.PetStore");
root.AddSwaggerSpec(petStoreSwaggerSpec, Path.GetFullPath(petStoreFilePath), "Microsoft.PetStore");
await root.AddSwaggerSpec(petStoreSwaggerSpec, Path.GetFullPath(petStoreFilePath), "Microsoft.PetStore");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./petstore_codefile.json");
Expand All @@ -95,7 +95,7 @@ public async Task TestDeviceUpdate()
var deviceUpdateSwagger = await SwaggerDeserializer.Deserialize(deviceUpdatePath);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.DeviceUpdate", "Microsoft.DeviceUpdate");
root.AddSwaggerSpec(deviceUpdateSwagger, Path.GetFullPath(deviceUpdatePath), "Microsoft.DeviceUpdate");
await root.AddSwaggerSpec(deviceUpdateSwagger, Path.GetFullPath(deviceUpdatePath), "Microsoft.DeviceUpdate");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./deviceupdate_codefile.json");
Expand All @@ -111,7 +111,7 @@ public async Task TestService()
var serviceSwagger = await SwaggerDeserializer.Deserialize(deviceUpdatePath);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.Service", "Microsoft.Service");
root.AddSwaggerSpec(serviceSwagger, Path.GetFullPath(deviceUpdatePath), "Microsoft.Service");
await root.AddSwaggerSpec(serviceSwagger, Path.GetFullPath(deviceUpdatePath), "Microsoft.Service");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./service_codefile.json");
Expand All @@ -127,7 +127,7 @@ public async Task TestDeviceUpdateSmall()
var deviceUpdateSwagger = await SwaggerDeserializer.Deserialize(deviceUpdatePath);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.DeviceUpdate", "Microsoft.DeviceUpdate");
root.AddSwaggerSpec(deviceUpdateSwagger, Path.GetFullPath(deviceUpdatePath), "Microsoft.DeviceUpdate");
await root.AddSwaggerSpec(deviceUpdateSwagger, Path.GetFullPath(deviceUpdatePath), "Microsoft.DeviceUpdate");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./deviceupdatesmall_codefile.json");
Expand All @@ -143,7 +143,7 @@ public async Task TestContentModerator()
var contentModeratorSwagger = await SwaggerDeserializer.Deserialize(contentModerator);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.ContentModerator", "Microsoft.ContentModerator");
root.AddSwaggerSpec(contentModeratorSwagger, Path.GetFullPath(contentModerator), "Microsoft.ContentModerator");
await root.AddSwaggerSpec(contentModeratorSwagger, Path.GetFullPath(contentModerator), "Microsoft.ContentModerator");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./contentModerator_codefile.json");
Expand All @@ -159,7 +159,7 @@ public async Task TestAzureOpenai()
var openaiSwagger = await SwaggerDeserializer.Deserialize(openai);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.OpenAI", "Microsoft.OpenAI");
root.AddSwaggerSpec(openaiSwagger, Path.GetFullPath(openai), "Microsoft.OpenAI");
await root.AddSwaggerSpec(openaiSwagger, Path.GetFullPath(openai), "Microsoft.OpenAI");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./openai_codefile.json");
Expand All @@ -175,7 +175,7 @@ public async Task TestPersonalize()
var personalizeSwagger = await SwaggerDeserializer.Deserialize(personal);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.Personalize", "Microsoft.Personalize");
root.AddSwaggerSpec(personalizeSwagger, Path.GetFullPath(personal), "Microsoft.Personalize");
await root.AddSwaggerSpec(personalizeSwagger, Path.GetFullPath(personal), "Microsoft.Personalize");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./personal_codefile.json");
Expand All @@ -191,7 +191,7 @@ public async Task TestMultivariate()
var multiVariateSwagger = await SwaggerDeserializer.Deserialize(multiVariateSwaggerFile);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.CognitiveService", "Microsoft.CognitiveService");
root.AddSwaggerSpec(multiVariateSwagger, Path.GetFullPath(multiVariateSwaggerFile), "Microsoft.CognitiveService");
await root.AddSwaggerSpec(multiVariateSwagger, Path.GetFullPath(multiVariateSwaggerFile), "Microsoft.CognitiveService");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./multivariate_codefile.json");
Expand All @@ -207,7 +207,7 @@ public async Task TestCommunicate()
var multiVariateSwagger = await SwaggerDeserializer.Deserialize(multiVariateSwaggerFile);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.Communicate", "Microsoft.Communicate");
root.AddSwaggerSpec(multiVariateSwagger, Path.GetFullPath(multiVariateSwaggerFile), "Microsoft.Communicate");
await root.AddSwaggerSpec(multiVariateSwagger, Path.GetFullPath(multiVariateSwaggerFile), "Microsoft.Communicate");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./communicate_codefile.json");
Expand All @@ -223,7 +223,7 @@ public async Task TestDevCenterEnvironment()
var devCenter = await SwaggerDeserializer.Deserialize(devCenterSwaggerFile);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.DevCenter", "Microsoft.DevCenter");
root.AddSwaggerSpec(devCenter, Path.GetFullPath(devCenterSwaggerFile), "Microsoft.DevCenter");
await root.AddSwaggerSpec(devCenter, Path.GetFullPath(devCenterSwaggerFile), "Microsoft.DevCenter");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./devCenter_codefile.json");
Expand All @@ -243,8 +243,8 @@ public async Task TestSignalRCrossFileReferenceCommonTypes()
var commonTypeSwagger = await SwaggerDeserializer.Deserialize(commonTypeFilePath);

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.SignalR", "Microsoft.SignalR");
root.AddSwaggerSpec(commonTypeSwagger, Path.GetFullPath(commonTypeFilePath), "Microsoft.SignalR");
root.AddSwaggerSpec(signalRSwagger, Path.GetFullPath(signalRFilePath), "Microsoft.SignalR");
await root.AddSwaggerSpec(commonTypeSwagger, Path.GetFullPath(commonTypeFilePath), "Microsoft.SignalR");
await root.AddSwaggerSpec(signalRSwagger, Path.GetFullPath(signalRFilePath), "Microsoft.SignalR");

var codeFile = root.GenerateCodeFile();

Expand All @@ -267,8 +267,8 @@ public async Task TestCommunicationEmailWithHeaderParameters()

SwaggerApiViewRoot root = new SwaggerApiViewRoot("Microsoft.Communication", "Microsoft.Communication");
root.AddDefinitionToCache(commonSpec, commonTypeFilePath);
root.AddSwaggerSpec(commonSpec, commonTypeFilePath);
root.AddSwaggerSpec(swaggerSpec, Path.GetFullPath(swaggerFilePath), "Microsoft.Communication");
await root.AddSwaggerSpec(commonSpec, commonTypeFilePath);
await root.AddSwaggerSpec(swaggerSpec, Path.GetFullPath(swaggerFilePath), "Microsoft.Communication");

var codeFile = root.GenerateCodeFile();
var outputFilePath = Path.GetFullPath("./communication_codefile.json");
Expand Down
Loading

0 comments on commit b3301af

Please sign in to comment.