Skip to content

Commit

Permalink
Adds unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rkodev committed Sep 26, 2024
1 parent 8a667d0 commit 89b36a7
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 104 deletions.
182 changes: 78 additions & 104 deletions src/Kiota.Builder/Refiners/GoRefiner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ public override Task RefineAsync(CodeNamespace generatedCode, CancellationToken
generatedCode
);
cancellationToken.ThrowIfCancellationRequested();
CorrectCyclicReference(generatedCode);
CopyModelClassesAsInterfaces(
generatedCode,
x => $"{x.Name}able"
Expand All @@ -214,7 +215,6 @@ public override Task RefineAsync(CodeNamespace generatedCode, CancellationToken
"Error",
() => new CodeType { Name = "string", IsNullable = false, IsExternal = true }
);
CorrectCyclicReference(generatedCode);
GenerateCodeFiles(generatedCode);
}, cancellationToken);
}
Expand All @@ -240,116 +240,19 @@ private void CorrectCyclicReference(CodeElement currentElement)
{
var dupNS = cycleReference[^2]; // 2nd last element is target base namespace
var nameSpace = modelsNameSpace.FindNamespaceByName(dupNS, true);
var rootNameSpace = cycle.Key.Equals(modelsNameSpace.Name, StringComparison.OrdinalIgnoreCase)
? modelsNameSpace
: modelsNameSpace.FindNamespaceByName(cycle.Key, true);
migratedNamespaces[dupNS] = cycle.Key;
MigrateNameSpace(nameSpace!, rootNameSpace!);
}
}

CorrectReferencesToMigratedModels(currentElement, migratedNamespaces);
}

private void CorrectReferencesToMigratedModels(CodeElement currentElement, Dictionary<string, string> migratedNamespaces)
{
if (currentElement is CodeNamespace cn)
{
var usings = cn.GetChildElements()
.SelectMany(static x => x.GetChildElements(false))
.OfType<ProprietableBlockDeclaration>()
.SelectMany(static x => x.Usings)
.Where(x => migratedNamespaces.ContainsKey(x.Name))
.ToArray();
migratedNamespaces[dupNS] = modelsNameSpace.Name;
MigrateNameSpace(nameSpace!, modelsNameSpace);

foreach (var codeUsing in usings)
{
if (codeUsing.Parent is not ProprietableBlockDeclaration blockDeclaration ||
codeUsing.Declaration?.TypeDefinition?.GetImmediateParentOfType<CodeNamespace>().Name !=
migratedNamespaces[codeUsing.Name])
if (!cycle.Key.Equals(modelsNameSpace.Name, StringComparison.OrdinalIgnoreCase) && !migratedNamespaces.ContainsKey(cycle.Key))
{
continue;
migratedNamespaces[cycle.Key] = modelsNameSpace.Name;
MigrateNameSpace(modelsNameSpace.FindNamespaceByName(cycle.Key, true)!, modelsNameSpace);
}

blockDeclaration.RemoveUsings(codeUsing);
blockDeclaration.AddUsings(new CodeUsing
{
Name = migratedNamespaces[codeUsing.Name],
Declaration = codeUsing.Declaration
});
}
}

CrawlTree(currentElement, x => CorrectReferencesToMigratedModels(x, migratedNamespaces));
}

private void MigrateReferencesToMigratedModels1(CodeElement currentElement, Dictionary<string, string> migratedNamespaces)
{
if (currentElement is ProprietableBlockDeclaration bd)
{
if (bd.Usings.Any(x => migratedNamespaces.ContainsKey(x.Name)))
{
foreach (var usingStatement in bd.Usings)
{
if (migratedNamespaces.TryGetValue(usingStatement.Name, out var newName))
{
bd.RemoveUsingsByDeclarationName(usingStatement.Name);
bd.AddUsings(new CodeUsing
{
Name = usingStatement.Declaration?.TypeDefinition?.Name!,
Declaration = new CodeType
{
Name = usingStatement.Declaration?.TypeDefinition?.Name!,
TypeDefinition = usingStatement.Declaration?.TypeDefinition,
}
});
}
}
}
}

CrawlTree(currentElement, x => MigrateReferencesToMigratedModels1(x, migratedNamespaces));
}

private void MigrateNameSpace(CodeNamespace currentNameSpace, CodeNamespace targetNameSpace)
{
currentNameSpace.Classes.ToList().ForEach(x =>
{
currentNameSpace.RemoveChildElement(x);
x.Name = GetComposedName(x);
x.Parent = targetNameSpace;
targetNameSpace.AddClass(x);
});
currentNameSpace.Enums.ToList().ForEach(x =>
{
currentNameSpace.RemoveChildElement(x);
x.Name = GetComposedName(x);
x.Parent = targetNameSpace;
targetNameSpace.AddEnum(x);
});
currentNameSpace.Interfaces.ToList().ForEach(x =>
{
currentNameSpace.RemoveChildElement(x);
x.Name = GetComposedName(x);
x.Parent = targetNameSpace;
targetNameSpace.AddInterface(x);
});
currentNameSpace.Functions.ToList().ForEach(x =>
{
currentNameSpace.RemoveChildElement(x);
x.Name = GetComposedName(x);
x.Parent = targetNameSpace;
targetNameSpace.AddFunction(x);
});
currentNameSpace.Constants.ToList().ForEach(x =>
{
currentNameSpace.RemoveChildElement(x);
x.Name = GetComposedName(x);
x.Parent = targetNameSpace;
targetNameSpace.AddConstant(x);
});

currentNameSpace.Namespaces.ToList().ForEach(x => MigrateNameSpace(x, targetNameSpace));
CorrectReferencesToMigratedModels(currentElement, migratedNamespaces);
}

private string GetComposedName(CodeElement codeClass)
Expand Down Expand Up @@ -431,6 +334,77 @@ static void SearchCycles(string parentNode, string node, Dictionary<string, Hash
stack.Pop();
}

private void MigrateNameSpace(CodeNamespace currentNameSpace, CodeNamespace targetNameSpace)
{
currentNameSpace.Classes.ToList().ForEach(x =>
{
currentNameSpace.RemoveChildElement(x);
x.Name = GetComposedName(x);
x.Parent = targetNameSpace;
targetNameSpace.AddClass(x);
});
currentNameSpace.Enums.ToList().ForEach(x =>
{
currentNameSpace.RemoveChildElement(x);
x.Name = GetComposedName(x);
x.Parent = targetNameSpace;
targetNameSpace.AddEnum(x);
});
currentNameSpace.Interfaces.ToList().ForEach(x =>
{
currentNameSpace.RemoveChildElement(x);
x.Name = GetComposedName(x);
x.Parent = targetNameSpace;
targetNameSpace.AddInterface(x);
});
currentNameSpace.Functions.ToList().ForEach(x =>
{
currentNameSpace.RemoveChildElement(x);
x.Name = GetComposedName(x);
x.Parent = targetNameSpace;
targetNameSpace.AddFunction(x);
});
currentNameSpace.Constants.ToList().ForEach(x =>
{
currentNameSpace.RemoveChildElement(x);
x.Name = GetComposedName(x);
x.Parent = targetNameSpace;
targetNameSpace.AddConstant(x);
});

currentNameSpace.Namespaces.ToList().ForEach(x => MigrateNameSpace(x, targetNameSpace));
}
private void CorrectReferencesToMigratedModels(CodeElement currentElement, Dictionary<string, string> migratedNamespaces)
{
if (currentElement is CodeNamespace cn)
{
var usings = cn.GetChildElements()
.SelectMany(static x => x.GetChildElements(false))
.OfType<ProprietableBlockDeclaration>()
.SelectMany(static x => x.Usings)
.Where(x => migratedNamespaces.ContainsKey(x.Name))
.ToArray();

foreach (var codeUsing in usings)
{
if (codeUsing.Parent is not ProprietableBlockDeclaration blockDeclaration ||
codeUsing.Declaration?.TypeDefinition?.GetImmediateParentOfType<CodeNamespace>().Name !=
migratedNamespaces[codeUsing.Name])
{
continue;
}

blockDeclaration.RemoveUsings(codeUsing);
blockDeclaration.AddUsings(new CodeUsing
{
Name = migratedNamespaces[codeUsing.Name],
Declaration = codeUsing.Declaration
});
}
}

CrawlTree(currentElement, x => CorrectReferencesToMigratedModels(x, migratedNamespaces));
}
private void GenerateCodeFiles(CodeElement currentElement)
{
if (currentElement is CodeInterface codeInterface && currentElement.Parent is CodeNamespace codeNamespace)
Expand Down
47 changes: 47 additions & 0 deletions tests/Kiota.Builder.Tests/Refiners/GoLanguageRefinerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,53 @@ public async Task ReplacesDurationByNativeTypeAsync()
Assert.NotEmpty(model.StartBlock.Usings);
Assert.Equal("ISODuration", method.ReturnType.Name);
}
[Fact]
public async Task CorrectesCircularDependencies()
{
var modelsNS = root.AddNamespace("ApiSdk.models");

var subANamespace = modelsNS.AddNamespace($"{modelsNS.Name}.suba");
var modelA = subANamespace.AddClass(new CodeClass
{
Kind = CodeClassKind.Model,
Name = "ModelA",
}).First();

var subBNamespace = modelsNS.AddNamespace($"{modelsNS.Name}.subb");
var modelB = subBNamespace.AddClass(new CodeClass
{
Kind = CodeClassKind.Model,
Name = "ModelB",
}).First();

modelA.StartBlock.AddUsings(new CodeUsing
{
Name = subBNamespace.Name,
Declaration = new()
{
Name = modelB.Name,
TypeDefinition = modelB,
IsExternal = false
}
});

modelB.StartBlock.AddUsings(new CodeUsing
{
Name = subANamespace.Name,
Declaration = new()
{
Name = modelA.Name,
TypeDefinition = modelA,
IsExternal = false
}
});

await ILanguageRefiner.RefineAsync(new GenerationConfiguration { Language = GenerationLanguage.Go }, root);
Assert.Equal("ApiSdk.models", modelB.GetImmediateParentOfType<CodeNamespace>().Name); // migrated to root namespace
Assert.Equal("ApiSdk.models", modelA.GetImmediateParentOfType<CodeNamespace>().Name); // migrated to root namespace
Assert.Equal("SubaModelA", modelA.Name); // renamed to avoid conflict
Assert.Equal("SubbModelB", modelB.Name); // renamed to avoid conflict
}
#endregion

#region GoRefinerTests
Expand Down

0 comments on commit 89b36a7

Please sign in to comment.