Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/test for semanticdiff #3

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ApiGenerator/ApiGenerator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
<PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CSharpier.Core" Version="0.28.2" />
<PackageReference Include="Glob" Version="1.1.9" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NSwag.Core" Version="14.1.0" />
<PackageReference Include="Proc" Version="0.8.1" />
<PackageReference Include="YamlDotNet" Version="16.0.0" />
<PackageReference Include="SemanticVersioning" Version="2.0.2" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
Expand Down
8 changes: 4 additions & 4 deletions src/ApiGenerator/CodeTemplatePage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ namespace ApiGenerator;

public abstract class CodeTemplatePage<TModel> : TemplatePage<TModel>
{
protected new Task IncludeAsync(string key, object model = null)
=> base.IncludeAsync(key.Replace('/', '.'), model);
protected new Task IncludeAsync(string key, object model = null)
=> base.IncludeAsync(key.Replace('/', '.'), model);

protected async Task IncludeLegacyGeneratorNotice() => await IncludeAsync("GeneratorNotice", true);
protected async Task IncludeLegacyGeneratorNotice() => await IncludeAsync("GeneratorNotice", true);

protected async Task IncludeGeneratorNotice() => await IncludeAsync("GeneratorNotice", false);
protected async Task IncludeGeneratorNotice() => await IncludeAsync("GeneratorNotice", false);
}
80 changes: 40 additions & 40 deletions src/ApiGenerator/Configuration/CodeConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,31 @@
namespace ApiGenerator.Configuration
{
public static class CodeConfiguration
{
private static readonly Glob[] OperationsToInclude =
{
new("{create,delete}_pit"),
new("{delete,get}_all_pits"),
{
private static readonly Glob[] OperationsToInclude =
{
new("{create,delete}_pit"),
new("{delete,get}_all_pits"),

new("cat.*"),
new("cluster.*"),
new("dangling_indices.*"),
new("cat.*"),
new("cluster.*"),
new("dangling_indices.*"),

new("indices.{delete,exists,get,put}_index_template"),
new("indices.{delete,exists,get,put}_index_template"),

new("ingest.*"),
new("ingest.*"),
new("nodes.*"),
new("snapshot.*"),
new("tasks.*")
};
new("snapshot.*"),
new("tasks.*")
};

public static bool IncludeOperation(string name) => OperationsToInclude.Any(g => g.IsMatch(name));
public static bool IncludeOperation(string name) => OperationsToInclude.Any(g => g.IsMatch(name));

/// <summary>
/// <summary>
/// Map API default names for API's we are only supporting on the low level client first
/// </summary>
private static readonly Dictionary<string, string> LowLevelApiNameMapping = new()
{
{
};

/// <summary>
Expand All @@ -69,10 +69,10 @@ public static class CodeConfiguration
/// </summary>
public static readonly Dictionary<string, string> HighLevelApiNameMapping =
(from f in new DirectoryInfo(GeneratorLocations.OpenSearchClientFolder).GetFiles("*.cs", SearchOption.AllDirectories)
let contents = File.ReadAllText(f.FullName)
let c = Regex.Replace(contents, @"^.+\[MapsApi\(""([^ \r\n]+)""\)\].*$", "$1", RegexOptions.Singleline)
where !c.Contains(" ") //filter results that did not match
select new { Value = f.Name.Replace("Request", ""), Key = c.Replace(".json", "") })
let contents = File.ReadAllText(f.FullName)
let c = Regex.Replace(contents, @"^.+\[MapsApi\(""([^ \r\n]+)""\)\].*$", "$1", RegexOptions.Singleline)
where !c.Contains(" ") //filter results that did not match
select new { Value = f.Name.Replace("Request", ""), Key = c.Replace(".json", "") })
.DistinctBy(v => v.Key)
.ToDictionary(k => k.Key, v => v.Value.Replace(".cs", ""));

Expand All @@ -84,7 +84,7 @@ public static bool IsNewHighLevelApi(string apiFileName) =>

public static bool IgnoreHighLevelApi(string apiFileName)
{
//always generate already mapped requests
//always generate already mapped requests

if (HighLevelApiNameMapping.ContainsKey(apiFileName.Replace(".json", ""))) return false;

Expand Down Expand Up @@ -119,20 +119,20 @@ public static Dictionary<string, string> ApiNameMapping
/// </summary>
public static readonly Dictionary<string, string> ResponseBuilderInClientCalls =
(from f in new DirectoryInfo(GeneratorLocations.OpenSearchClientFolder).GetFiles("*.cs", SearchOption.AllDirectories)
from l in File.ReadLines(f.FullName)
where Regex.IsMatch(l, ResponseBuilderAttributeRegex)
let c = Regex.Replace(l, @"^.+\[ResponseBuilderWithGeneric\(""([^ \r\n]+)""\)\].*$", "$1", RegexOptions.Singleline)
select new { Key = f.Name.Replace(".cs", ""), Value = c })
from l in File.ReadLines(f.FullName)
where Regex.IsMatch(l, ResponseBuilderAttributeRegex)
let c = Regex.Replace(l, @"^.+\[ResponseBuilderWithGeneric\(""([^ \r\n]+)""\)\].*$", "$1", RegexOptions.Singleline)
select new { Key = f.Name.Replace(".cs", ""), Value = c })
.DistinctBy(v => v.Key)
.ToDictionary(k => k.Key, v => v.Value);

public static readonly Dictionary<string, string> DescriptorGenericsLookup =
(from f in new DirectoryInfo(GeneratorLocations.OpenSearchClientFolder).GetFiles("*Request.cs", SearchOption.AllDirectories)
let name = Path.GetFileNameWithoutExtension(f.Name).Replace("Request", "")
let contents = File.ReadAllText(f.FullName)
let c = Regex.Replace(contents, $@"^.+class ({name}Descriptor(?:<[^>\r\n]+>)?[^ \r\n]*).*$", "$1", RegexOptions.Singleline)
let key = $"{name}Descriptor"
select new { Key = key, Value = Regex.Replace(c, @"^.*?(?:(\<.+>).*?)?$", "$1") })
let name = Path.GetFileNameWithoutExtension(f.Name).Replace("Request", "")
let contents = File.ReadAllText(f.FullName)
let c = Regex.Replace(contents, $@"^.+class ({name}Descriptor(?:<[^>\r\n]+>)?[^ \r\n]*).*$", "$1", RegexOptions.Singleline)
let key = $"{name}Descriptor"
select new { Key = key, Value = Regex.Replace(c, @"^.*?(?:(\<.+>).*?)?$", "$1") })
.DistinctBy(v => v.Key)
.OrderBy(v => v.Key)
.ToDictionary(k => k.Key, v => v.Value);
Expand All @@ -142,16 +142,16 @@ where Regex.IsMatch(l, ResponseBuilderAttributeRegex)
// find all files in OSC ending with Request.cs
from f in new DirectoryInfo(GeneratorLocations.OpenSearchClientFolder).GetFiles("*Request.cs", SearchOption.AllDirectories)
from l in File.ReadLines(f.FullName)
// attempt to locate all Request interfaces lines
// attempt to locate all Request interfaces lines
where Regex.IsMatch(l, @"^.+interface [^ \r\n]+Request")
//grab the interface name including any generics declared on it
let c = Regex.Replace(l, @"^.+interface ([^ \r\n]+Request(?:<[^>\r\n]+>)?[^ \r\n]*).*$", "$1", RegexOptions.Singleline)
where c.StartsWith("I") && c.Contains("Request")
let request = Regex.Replace(c, "<.*$", "")
let generics = Regex.Replace(c, @"^.*?(?:(\<.+>).*?)?$", "$1")
select Tuple.Create(request, generics)
select Tuple.Create(request, generics)
)
.OrderBy(v=>v.Item1)
.OrderBy(v => v.Item1)
.ToList();

public static readonly HashSet<string> GenericOnlyInterfaces = new HashSet<string>(AllKnownRequestInterfaces
Expand All @@ -164,7 +164,7 @@ select Tuple.Create(request, generics)
// find all files in OSC ending with Request.cs
from f in new DirectoryInfo(GeneratorLocations.OpenSearchClientFolder).GetFiles("*Request.cs", SearchOption.AllDirectories)
from l in File.ReadLines(f.FullName)
// attempt to locate all Request interfaces lines
// attempt to locate all Request interfaces lines
where Regex.IsMatch(l, @"^.+interface [^ \r\n]+Request")
where l.Contains("IDocumentRequest")
let c = Regex.Replace(l, @"^.+interface ([^ \r\n]+Request(?:<[^>\r\n]+>)?[^ \r\n]*).*$", "$1", RegexOptions.Singleline)
Expand All @@ -189,8 +189,8 @@ where Regex.IsMatch(l, re)

public static readonly Dictionary<string, string> RequestInterfaceGenericsLookup =
AllKnownRequestInterfaces
.GroupBy(v=>v.Item1)
.Select(g=>g.Last())
.GroupBy(v => v.Item1)
.Select(g => g.Last())
.ToDictionary(k => k.Item1, v => v.Item2);

/// <summary>
Expand All @@ -213,17 +213,17 @@ where Regex.IsMatch(l, re)
// find all files in OSC ending with Request.cs
from f in new DirectoryInfo(GeneratorLocations.OpenSearchClientFolder).GetFiles("*Response.cs", SearchOption.AllDirectories)
from l in File.ReadLines(f.FullName)
// attempt to locate all Response class lines
// attempt to locate all Response class lines
where Regex.IsMatch(l, @"^.+public class [^ \r\n]+Response")
//grab the response name including any generics declared on it
let c = Regex.Replace(l, @"^.+public class ([^ \r\n]+Response(?:<[^>\r\n]+>)?[^ \r\n]*).*$", "$1", RegexOptions.Singleline)
where c.Contains("Response")
let response = Regex.Replace(c, "<.*$", "")
let generics = Regex.Replace(c, @"^.*?(?:(\<.+>).*?)?$", "$1")
select (response, (response, generics))
select (response, (response, generics))
)
.Concat(ResponseReroute.Select(kv=>(kv.Key, (kv.Value.Item1, kv.Value.Item2))))
.ToDictionary(t=>t.Item1, t=>t.Item2));
.Concat(ResponseReroute.Select(kv => (kv.Key, (kv.Value.Item1, kv.Value.Item2))))
.ToDictionary(t => t.Item1, t => t.Item2));

}
}
54 changes: 28 additions & 26 deletions src/ApiGenerator/Configuration/GeneratorLocations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,42 +31,44 @@

namespace ApiGenerator.Configuration
{
public static class GeneratorLocations
{
public static string OpenApiSpecFile { get; } = $"{Root}opensearch-openapi.yaml";
public static class GeneratorLocations
{
public static string OpenApiSpecFile { get; } = $"{Root}opensearch-openapi.yaml";

public static string OpenSearchNetFolder { get; } = $"{Root}../../src/OpenSearch.Net/";
public static string OpenSearchNetFolder { get; } = $"{Root}../../src/OpenSearch.Net/";

public static string OpenSearchClientFolder { get; } = $"{Root}../../src/OpenSearch.Client/";
public static string OpenSearchClientFolder { get; } = $"{Root}../../src/OpenSearch.Client/";

public static string LowLevelGeneratedFolder { get; } = $"{OpenSearchNetFolder}_Generated/";
public static string LowLevelGeneratedFolder { get; } = $"{OpenSearchNetFolder}_Generated/";

public static string HighLevelGeneratedFolder { get; } = $"{OpenSearchClientFolder}_Generated/";
public static string HighLevelGeneratedFolder { get; } = $"{OpenSearchClientFolder}_Generated/";

public static string HighLevel(params string[] paths) => HighLevelGeneratedFolder + string.Join("/", paths);
public static string HighLevel(params string[] paths) => HighLevelGeneratedFolder + string.Join("/", paths);

public static string LowLevel(params string[] paths) => LowLevelGeneratedFolder + string.Join("/", paths);
public static string LowLevel(params string[] paths) => LowLevelGeneratedFolder + string.Join("/", paths);

public static readonly Assembly Assembly = typeof(Generator.ApiGenerator).Assembly;
public static string SolutionFolder { get; } = $"{Root}../../";

private static string _root;
public static readonly Assembly Assembly = typeof(Generator.ApiGenerator).Assembly;

public static string Root
{
get
{
if (_root != null) return _root;
private static string _root;

var directoryInfo = new DirectoryInfo(Directory.GetCurrentDirectory());
public static string Root
{
get
{
if (_root != null) return _root;

var dotnetRun =
directoryInfo.Name == "ApiGenerator" &&
directoryInfo.Parent != null &&
directoryInfo.Parent.Name == "src";
var directoryInfo = new DirectoryInfo(Directory.GetCurrentDirectory());

_root = dotnetRun ? "" : "../../../";
return _root;
}
}
}
var dotnetRun =
directoryInfo.Name == "ApiGenerator" &&
directoryInfo.Parent != null &&
directoryInfo.Parent.Name == "src";

_root = dotnetRun ? "" : "../../../";
return _root;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace ApiGenerator.Configuration.Overrides
{
public abstract class EndpointOverridesBase : IEndpointOverrides
{
public virtual IDictionary<string, string> RenameUrlParts { get; } = new SortedDictionary<string, string>();
public virtual IDictionary<string, string> RenameUrlParts { get; } = new SortedDictionary<string, string>();

public virtual IDictionary<string, string> ObsoleteQueryStringParams { get; set; } = new SortedDictionary<string, string>();

Expand Down
14 changes: 7 additions & 7 deletions src/ApiGenerator/Configuration/Overrides/GlobalOverrides.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@
namespace ApiGenerator.Configuration.Overrides
{
public class GlobalOverrides : EndpointOverridesBase
{
public static readonly GlobalOverrides Instance = new();
{
public static readonly GlobalOverrides Instance = new();

private GlobalOverrides() { }
private GlobalOverrides() { }

public IDictionary<string, string> RenameEnums { get; } = new Dictionary<string, string>
{
{ "ExpandWildcard", "ExpandWildcards" }
};
public IDictionary<string, string> RenameEnums { get; } = new Dictionary<string, string>
{
{ "ExpandWildcard", "ExpandWildcards" }
};

public override IDictionary<string, string> ObsoleteQueryStringParams { get; set; } = new Dictionary<string, string>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ namespace ApiGenerator.Configuration.Overrides
/// </summary>
public interface IEndpointOverrides
{
/// <summary>
/// Override how the url part is exposed to the client.
/// </summary>
IDictionary<string, string> RenameUrlParts { get; }
/// <summary>
/// Override how the url part is exposed to the client.
/// </summary>
IDictionary<string, string> RenameUrlParts { get; }

/// <summary>
/// A map of key -> obsolete message for properties in the spec that should not be used any longer
Expand Down
44 changes: 22 additions & 22 deletions src/ApiGenerator/Domain/ApiRequestParametersPatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,22 @@ namespace ApiGenerator.Domain
{
public static class ApiRequestParametersPatcher
{
public static void PatchUrlPaths(string endpointName, IList<UrlPath> source, IEndpointOverrides overrides)
{
var declaredKeys = source.SelectMany(p => p.Parts).Select(p => p.Name).ToHashSet();
var renameLookup = CreateUrlPartRenameLookup(overrides, declaredKeys);

foreach (var path in source)
{
foreach (var part in path.Parts)
{
if (!renameLookup.TryGetValue(part.Name, out var newName)) continue;

path.Path = path.Path.Replace($"{{{part.Name}}}", $"{{{newName}}}");
part.Name = newName;
}
}
}
public static void PatchUrlPaths(string endpointName, IList<UrlPath> source, IEndpointOverrides overrides)
{
var declaredKeys = source.SelectMany(p => p.Parts).Select(p => p.Name).ToHashSet();
var renameLookup = CreateUrlPartRenameLookup(overrides, declaredKeys);

foreach (var path in source)
{
foreach (var part in path.Parts)
{
if (!renameLookup.TryGetValue(part.Name, out var newName)) continue;

path.Path = path.Path.Replace($"{{{part.Name}}}", $"{{{newName}}}");
part.Name = newName;
}
}
}

public static SortedDictionary<string, QueryParameters> PatchQueryParameters(
string endpointName,
Expand All @@ -69,7 +69,7 @@ IEndpointOverrides overrides
var patchedParams = new SortedDictionary<string, QueryParameters>();
foreach (var (queryStringKey, value) in source)
{
value.QueryStringKey = queryStringKey;
value.QueryStringKey = queryStringKey;

if (!renameLookup.TryGetValue(queryStringKey, out var preferredName)) preferredName = queryStringKey;

Expand All @@ -84,7 +84,7 @@ IEndpointOverrides overrides
//make sure source_enabled takes a boolean only
if (preferredName == "source_enabled") value.Type = "boolean";

patchedParams[preferredName] = value;
patchedParams[preferredName] = value;
}

return patchedParams;
Expand All @@ -97,8 +97,8 @@ private static string CreateCSharpName(string queryStringKey, string endpointNam
if (queryStringKey == "format" && endpointName == "text_structure.find_structure")
return "TextStructureFindStructureFormat";

return queryStringKey.ToPascalCase();
}
return queryStringKey.ToPascalCase();
}

private static IList<string> CreateSkipList(IEndpointOverrides local, ICollection<string> declaredKeys) =>
CreateList(local, "skip", e => e.SkipQueryStringParams, declaredKeys);
Expand Down Expand Up @@ -142,8 +142,8 @@ Func<IEndpointOverrides, IEnumerable<string>> @from, ICollection<string> declare
return list.Distinct().ToList();
}

private static IDictionary<string, string> CreateUrlPartRenameLookup(IEndpointOverrides local, ICollection<string> declaredKeys) =>
CreateLookup(local, "url_part_rename", e => e.RenameUrlParts, declaredKeys);
private static IDictionary<string, string> CreateUrlPartRenameLookup(IEndpointOverrides local, ICollection<string> declaredKeys) =>
CreateLookup(local, "url_part_rename", e => e.RenameUrlParts, declaredKeys);

private static IDictionary<string, string> CreateRenameLookup(IEndpointOverrides local, ICollection<string> declaredKeys) =>
CreateLookup(local, "rename", e => e.RenameQueryStringParams, declaredKeys);
Expand Down
Loading