Skip to content

Commit 1ce3183

Browse files
authored
Feature/render partial (elastic#3018)
* Generator can now implement request parameters as properties on interface only (partial) this forces the high level client to imlpement partial declared properties on the body explicitly * Pathing url parameters happens only once not for each method, can now warn if we configure overrides for params that are not declared on the spec * addressed al reported code generation warnings * another pass over configured overrides, FieldStats no longer exists as endpoint * remove stored fields from manual implemented interface part for ISearchRequest * finished XmlDoc on GlobalOverrides.RenderPartial
1 parent b5be605 commit 1ce3183

File tree

48 files changed

+1010
-1388
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1010
-1388
lines changed

src/CodeGeneration/ApiGenerator/ApiGenerator.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public class ApiGenerator
1717

1818
public static void Generate(string downloadBranch, params string[] folders)
1919
{
20+
Warnings = new List<string>();
2021
var spec = CreateRestApiSpecModel(downloadBranch, folders);
2122
var actions = new Dictionary<Action<RestApiSpec>, string>
2223
{
@@ -38,8 +39,17 @@ public static void Generate(string downloadBranch, params string[] folders)
3839
pbar.Tick("Generated " + kv.Value);
3940
}
4041
}
42+
43+
if (Warnings.Count == 0) return;
44+
45+
Console.ForegroundColor = ConsoleColor.Yellow;
46+
foreach (var warning in Warnings.Distinct().OrderBy(w=>w))
47+
Console.WriteLine(warning);
48+
Console.ResetColor();
4149
}
4250

51+
public static List<string> Warnings { get; private set; }
52+
4353
private static string[] IgnoredApis { get; } =
4454
{
4555
"xpack.ml.delete_filter.json",

src/CodeGeneration/ApiGenerator/Domain/ApiEndpoint.cs

Lines changed: 93 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Text.RegularExpressions;
5+
using ApiGenerator.Overrides;
56
using ApiGenerator.Overrides.Descriptors;
67
using CsQuery.ExtensionMethods.Internal;
78

@@ -160,12 +161,11 @@ public IEnumerable<CsharpMethod> CsharpMethods
160161
Description = this.Body.Description
161162
});
162163
}
163-
var queryStringParamName = "FluentQueryString";
164164
if (this.Url.Params == null || !this.Url.Params.Any())
165165
{
166166
this.Url.Params = new Dictionary<string, ApiQueryParameters>();
167167
}
168-
queryStringParamName = this.CsharpMethodName + "RequestParameters";
168+
var queryStringParamName = this.CsharpMethodName + "RequestParameters";
169169
var apiMethod = new CsharpMethod
170170
{
171171
QueryStringParamName = queryStringParamName,
@@ -222,8 +222,25 @@ public IEnumerable<CsharpMethod> CsharpMethods
222222
}
223223
}
224224

225+
private IEndpointOverrides GetOverrides()
226+
{
227+
var method = this.CsharpMethodName;
228+
if (CodeConfiguration.MethodNameOverrides.TryGetValue(method, out var manualOverride))
229+
method = manualOverride;
230+
231+
var typeName = "ApiGenerator.Overrides.Endpoints." + method + "Overrides";
232+
var type = CodeConfiguration.Assembly.GetType(typeName);
233+
if (type != null && Activator.CreateInstance(type) is IEndpointOverrides overrides)
234+
return overrides;
235+
return null;
236+
}
237+
238+
225239
private void PatchEndpoint()
226240
{
241+
var overrides = this.GetOverrides();
242+
PatchRequestParameters(overrides);
243+
227244
//rename the {metric} route param to something more specific on XpackWatcherStats
228245
// TODO: find a better place to do this
229246
if (this.CsharpMethodName == "XpackWatcherStats")
@@ -243,6 +260,78 @@ private void PatchEndpoint()
243260
}
244261
}
245262

263+
private void PatchRequestParameters(IEndpointOverrides overrides)
264+
{
265+
if (this.Url.Params == null) return;
266+
foreach (var param in RestApiSpec.CommonApiQueryParameters)
267+
{
268+
if (!this.Url.Params.ContainsKey(param.Key))
269+
this.Url.Params.Add(param.Key, param.Value);
270+
}
271+
272+
if (this.ObsoleteQueryParameters != null)
273+
{
274+
foreach (var param in this.ObsoleteQueryParameters)
275+
{
276+
if (!this.Url.Params.ContainsKey(param.Key))
277+
this.Url.Params.Add(param.Key, param.Value);
278+
}
279+
}
280+
var declaredKeys = this.Url.Params.Select(p => p.Value.OriginalQueryStringParamName ?? p.Key).ToList();
281+
IEnumerable<string> skipList = new List<string>();
282+
IDictionary<string, string> queryStringParamsRenameList = new Dictionary<string, string>();
283+
284+
if (overrides != null)
285+
{
286+
var name = overrides.GetType().Name;
287+
skipList = overrides.SkipQueryStringParams ?? skipList;
288+
queryStringParamsRenameList = overrides.RenameQueryStringParams ?? queryStringParamsRenameList;
289+
foreach (var p in skipList.Except(declaredKeys))
290+
ApiGenerator.Warnings.Add($"On {name} skip key '{p}' is not found in spec");
291+
foreach (var p in queryStringParamsRenameList.Keys.Except(declaredKeys))
292+
ApiGenerator.Warnings.Add($"On {name} rename key '{p}' is not found in spec");
293+
}
294+
295+
var globalQueryStringRenames = new Dictionary<string, string>
296+
{
297+
{"_source", "source_enabled"},
298+
{"_source_include", "source_include"},
299+
{"_source_exclude", "source_exclude"},
300+
{"q", "query_on_query_string"},
301+
{"docvalue_fields", "doc_value_fields"},
302+
};
303+
304+
foreach (var kv in globalQueryStringRenames)
305+
if (!queryStringParamsRenameList.ContainsKey(kv.Key))
306+
queryStringParamsRenameList[kv.Key] = kv.Value;
307+
308+
var globalOverrides = new GlobalOverrides();
309+
var patchedParams = new Dictionary<string, ApiQueryParameters>();
310+
foreach (var kv in this.Url.Params)
311+
{
312+
if (kv.Value.OriginalQueryStringParamName.IsNullOrEmpty())
313+
kv.Value.OriginalQueryStringParamName = kv.Key;
314+
315+
if (skipList.Contains(kv.Key)) continue;
316+
if (globalOverrides.RenderPartial.Contains(kv.Key))
317+
kv.Value.RenderPartial = true;
318+
319+
if (!queryStringParamsRenameList.TryGetValue(kv.Key, out var newName))
320+
{
321+
patchedParams.Add(kv.Key, kv.Value);
322+
continue;
323+
}
324+
325+
if (globalOverrides.RenderPartial.Contains(newName))
326+
kv.Value.RenderPartial = true;
327+
328+
329+
patchedParams.Add(newName, kv.Value);
330+
}
331+
332+
this.Url.Params = patchedParams;
333+
}
334+
246335
private static string RenameMetricUrlPathParam(string path)
247336
{
248337
return path.Replace("{metric}", "{watcher_stats_metric}");
@@ -252,6 +341,7 @@ private static string RenameMetricUrlPathParam(string path)
252341
//or to get rid of double verbs in an method name i,e ClusterGetSettingsGet > ClusterGetSettings
253342
public void PatchMethod(CsharpMethod method)
254343
{
344+
if (method == null) return;
255345
Func<string, bool> ms = s => method.FullName.StartsWith(s);
256346
Func<string, bool> pc = s => method.Path.Contains(s);
257347

@@ -266,19 +356,7 @@ public void PatchMethod(CsharpMethod method)
266356
method.FullName =
267357
Regex.Replace(method.FullName, m, a => a.Index != method.FullName.IndexOf(m, StringComparison.Ordinal) ? "" : m);
268358

269-
foreach (var param in RestApiSpec.CommonApiQueryParameters)
270-
{
271-
if (!method.Url.Params.ContainsKey(param.Key))
272-
method.Url.Params.Add(param.Key, param.Value);
273-
}
274-
if (this.ObsoleteQueryParameters != null)
275-
{
276-
foreach (var param in this.ObsoleteQueryParameters)
277-
{
278-
if (!method.Url.Params.ContainsKey(param.Key))
279-
method.Url.Params.Add(param.Key, param.Value);
280-
}
281-
}
359+
method = this.GetOverrides()?.PatchMethod(method) ?? method;
282360

283361
var key = method.QueryStringParamName.Replace("RequestParameters", "");
284362
if (CodeConfiguration.MethodNameOverrides.TryGetValue(key, out var manualOverride))
@@ -294,60 +372,6 @@ public void PatchMethod(CsharpMethod method)
294372
method.DescriptorTypeGeneric = generic;
295373
else method.Unmapped = true;
296374

297-
try
298-
{
299-
IEnumerable<string> skipList = new List<string>();
300-
IDictionary<string, string> queryStringParamsRenameList = new Dictionary<string, string>();
301-
302-
var typeName = "ApiGenerator.Overrides.Descriptors." + method.DescriptorType + "Overrides";
303-
var type = CodeConfiguration.Assembly.GetType(typeName);
304-
if (type != null)
305-
{
306-
var overrides = Activator.CreateInstance(type) as IDescriptorOverrides;
307-
if (overrides != null)
308-
{
309-
skipList = overrides.SkipQueryStringParams ?? skipList;
310-
queryStringParamsRenameList = overrides.RenameQueryStringParams ?? queryStringParamsRenameList;
311-
method = overrides.PatchMethod(method);
312-
}
313-
}
314-
315-
var globalQueryStringRenames = new Dictionary<string, string>
316-
{
317-
{"_source", "source_enabled"},
318-
{"_source_include", "source_include"},
319-
{"_source_exclude", "source_exclude"},
320-
{"q", "query_on_query_string"},
321-
};
322-
323-
foreach (var kv in globalQueryStringRenames)
324-
if (!queryStringParamsRenameList.ContainsKey(kv.Key))
325-
queryStringParamsRenameList[kv.Key] = kv.Value;
326-
327-
var patchedParams = new Dictionary<string, ApiQueryParameters>();
328-
foreach (var kv in method.Url.Params)
329-
{
330-
if (kv.Value.OriginalQueryStringParamName.IsNullOrEmpty())
331-
kv.Value.OriginalQueryStringParamName = kv.Key;
332-
if (skipList.Contains(kv.Key))
333-
continue;
334-
335-
string newName;
336-
if (!queryStringParamsRenameList.TryGetValue(kv.Key, out newName))
337-
{
338-
patchedParams.Add(kv.Key, kv.Value);
339-
continue;
340-
}
341-
342-
patchedParams.Add(newName, kv.Value);
343-
}
344-
345-
method.Url.Params = patchedParams;
346-
}
347-
// ReSharper disable once EmptyGeneralCatchClause
348-
catch
349-
{
350-
}
351375
}
352376
}
353377
}

src/CodeGeneration/ApiGenerator/Domain/ApiQueryParameters.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,20 @@ public IEnumerable<string> HighLevelTypeDescription(string paramName)
6565
public string HighLevelType(string paramName)
6666
{
6767
if (paramName == "routing") return "Routing";
68+
var o = OriginalQueryStringParamName;
69+
var isFields = (o.Contains("fields") || o.Contains("source_include") || o.Contains("source_exclude"));
6870

6971
var csharpType = this.CsharpType(paramName);
7072
switch (csharpType)
7173
{
7274
case "TimeSpan": return "Time";
75+
}
76+
switch (this.Type)
77+
{
78+
79+
case "list" when isFields:
80+
case "string" when isFields: return "Fields";
81+
case "string" when o.Contains("field"): return "Field";
7382
default:
7483
return csharpType;
7584
}
@@ -80,5 +89,7 @@ public string HighLevelType(string paramName)
8089
$"public {fieldType} {mm} {{ get {{ return Q<{fieldType}>(\"{original}\"); }} set {{ Q(\"{original}\", {setter}); }} }}";
8190

8291
public Func<string, string, string, string, string> FluentGenerator { get; set; }
92+
93+
public bool RenderPartial { get; set; }
8394
}
8495
}

src/CodeGeneration/ApiGenerator/Overrides/Descriptors/AnalyzeDescriptorOverrides.cs

Lines changed: 0 additions & 19 deletions
This file was deleted.

src/CodeGeneration/ApiGenerator/Overrides/Descriptors/ClearCacheDescriptorOverrides.cs

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/CodeGeneration/ApiGenerator/Overrides/Descriptors/FieldStatsDescriptorOverrides.cs

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/CodeGeneration/ApiGenerator/Overrides/Descriptors/GetCategoriesDescriptorOverrides.cs

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/CodeGeneration/ApiGenerator/Overrides/Descriptors/MultiTermVectorsDescriptorOverrides.cs

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/CodeGeneration/ApiGenerator/Overrides/Descriptors/NodesHotThreadsDescriptorOverrides.cs

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/CodeGeneration/ApiGenerator/Overrides/Descriptors/PutIndexTemplateDescriptorOverrides.cs

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)