Skip to content

Feature/7.x/low level expose deprecated paths #3814

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

Merged
merged 7 commits into from
Jun 24, 2019
Merged
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
11 changes: 8 additions & 3 deletions src/CodeGeneration/ApiGenerator/Domain/Code/CsharpNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,18 @@ public string PerPathMethodName(string path)
Func<string, bool> ms = s => Namespace != null && Namespace.StartsWith(s);
Func<string, bool> pc = path.Contains;

var method = MethodName;
// This is temporary for 7.0 transition period
// TODO: remove in master once master in elasticsearch is scrubbed
if (path.Contains("{type}") && !method.Contains("Type")) method += "UsingType";

if (ms("Indices") && !pc("{index}"))
return (MethodName + "ForAll").Replace("AsyncForAll", "ForAllAsync");
return (method + "ForAll").Replace("AsyncForAll", "ForAllAsync");

if (ms("Nodes") && !pc("{node_id}"))
return (MethodName + "ForAll").Replace("AsyncForAll", "ForAllAsync");
return (method + "ForAll").Replace("AsyncForAll", "ForAllAsync");

return MethodName;
return method;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public string DescriptorArguments()
if (!UrlParts.Any()) return codeArgs;

string Optional(UrlPart p) => !p.Required && SelectorIsOptional ? " = null" : string.Empty;
return codeArgs + string.Join(", ", UrlParts.Select(p => $"{p.ClrTypeName} {p.Name.ToCamelCase()}{Optional(p)}")) + ", ";
return codeArgs + string.Join(", ", UrlParts.Select(p => $"{p.HighLevelTypeName} {p.Name.ToCamelCase()}{Optional(p)}")) + ", ";
}

public string SelectorArguments()
Expand All @@ -116,7 +116,7 @@ string ToArg(UrlPart p)
{
if (IsDocumentRequest) return "documentWithId: document";

if (p.ClrTypeName.StartsWith("DocumentPath"))
if (p.HighLevelTypeName.StartsWith("DocumentPath"))
return "documentWithId: id?.Document, index: id?.Self?.Index, id: id?.Self?.Id";


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ public IEnumerable<FluentRouteSetter> GetFluentRouteSetters()
var routeSetter = p.Required ? "Required" : "Optional";

var code =
$"public {returnType} {p.InterfaceName}({p.ClrTypeName} {paramName}) => Assign({paramName}, (a,v)=>a.RouteValues.{routeSetter}(\"{p.Name}\", {routeValue}));";
$"public {returnType} {p.InterfaceName}({p.HighLevelTypeName} {paramName}) => Assign({paramName}, (a,v)=>a.RouteValues.{routeSetter}(\"{p.Name}\", {routeValue}));";
var xmlDoc = $"///<summary>{p.Description}</summary>";
setters.Add(new FluentRouteSetter { Code = code, XmlDoc = xmlDoc });
if (paramName == "index")
{
code = $"public {returnType} {p.InterfaceName}<TOther>() where TOther : class ";
code += $"=> Assign(typeof(TOther), (a,v)=>a.RouteValues.{routeSetter}(\"{p.Name}\", ({p.ClrTypeName})v));";
code += $"=> Assign(typeof(TOther), (a,v)=>a.RouteValues.{routeSetter}(\"{p.Name}\", ({p.HighLevelTypeName})v));";
xmlDoc = $"///<summary>a shortcut into calling {p.InterfaceName}(typeof(TOther))</summary>";
setters.Add(new FluentRouteSetter { Code = code, XmlDoc = xmlDoc });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class LowLevelClientMethod
public string PerPathMethodName { get; set; }
public string HttpMethod { get; set; }

public string DeprecatedPath { get; set; }
public DeprecatedPath DeprecatedPath { get; set; }
public UrlInformation Url { get; set; }
public bool HasBody { get; set; }
public IEnumerable<UrlPart> Parts { get; set; }
Expand All @@ -32,7 +32,9 @@ string Evaluator(Match m)
}

var url = Path.TrimStart('/');
var pattern = string.Join("|", Url.Parts.Select(p => p.Name));
var options = Url.OriginalParts?.Select(p => p.Key) ?? Enumerable.Empty<string>();

var pattern = string.Join("|", options);
var urlCode = $"\"{url}\"";
if (Path.Contains("{"))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public IReadOnlyCollection<LowLevelClientMethod> LowLevelClientMethods
_lowLevelClientMethods = new List<LowLevelClientMethod>();

var httpMethod = PreferredHttpMethod;
foreach (var path in Url.Paths)
foreach (var path in Url.PathsWithDeprecations)
{
var methodName = CsharpNames.PerPathMethodName(path.Path);
var parts = new List<UrlPart>(path.Parts);
Expand All @@ -140,7 +140,7 @@ public IReadOnlyCollection<LowLevelClientMethod> LowLevelClientMethods
PerPathMethodName = methodName,
HttpMethod = httpMethod,
OfficialDocumentationLink = OfficialDocumentationLink,
DeprecatedPath = null, //TODO
DeprecatedPath = path.Deprecation,
Path = path.Path,
Parts = parts,
Url = Url,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using CsQuery.Engine;
using CsQuery.Engine.PseudoClassSelectors;
using Newtonsoft.Json;

namespace ApiGenerator.Domain.Specification
Expand All @@ -13,8 +17,11 @@ public class UrlInformation
[JsonProperty("paths")]
private IReadOnlyCollection<string> OriginalPaths { get; set; }

[JsonProperty("parts")]
private IDictionary<string, UrlPart> OriginalParts { get; set; }
[JsonProperty("parts")]
public IDictionary<string, UrlPart> OriginalParts { get; set; }

[JsonProperty("deprecated_paths")]
private IReadOnlyCollection<DeprecatedPath> DeprecatedPaths { get; set; }

private List<UrlPath> _paths;
public IReadOnlyCollection<UrlPath> Paths
Expand All @@ -27,6 +34,42 @@ public IReadOnlyCollection<UrlPath> Paths
return _paths;
}
}

private List<UrlPath> _pathsWithDeprecation;
public IReadOnlyCollection<UrlPath> PathsWithDeprecations
{
get
{
if (_pathsWithDeprecation != null && _pathsWithDeprecation.Count > 0) return _pathsWithDeprecation;

var paths = Paths ?? new UrlPath[] {};
if (DeprecatedPaths == null || DeprecatedPaths.Count == 0) return Paths;

//some deprecated paths describe aliases to the canonical using the same path e.g
// PUT /{index}/_mapping/{type}
// PUT /{index}/{type}/_mappings
//
//The following routine dedups these occasions and prefers either the cononical path
//or the first duplicate deprecated path

var canonicalPartNameLookup = paths.Select(path => new HashSet<string>(path.Parts.Select(p => p.Name))).ToList();
var withoutDeprecatedAliases = DeprecatedPaths
.Select(deprecatedPath => new
{
deprecatedPath,
parts = new HashSet<string>(OriginalParts.Keys.Where(k => deprecatedPath.Path.Contains($"{{{k}}}")))
})
.GroupBy(t => t.parts, HashSet<string>.CreateSetComparer())
.Where(grouped => !canonicalPartNameLookup.Any(set => set.SetEquals(grouped.Key)))
.Select(grouped => grouped.First().deprecatedPath);


_pathsWithDeprecation = paths
.Concat(withoutDeprecatedAliases.Select(p => new UrlPath(p, OriginalParts, Paths)))
.ToList();
return _pathsWithDeprecation;
}
}


public IReadOnlyCollection<UrlPart> Parts => Paths.SelectMany(p => p.Parts).DistinctBy(p => p.Name).ToList();
Expand Down
31 changes: 22 additions & 9 deletions src/CodeGeneration/ApiGenerator/Domain/Specification/UrlPart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,45 @@

namespace ApiGenerator.Domain.Specification
{

//TODO once https://github.com/elastic/elasticsearch/pull/42346 lands
// Rename this type to Deprecation and remove Path duplication
public class DeprecatedPath
{
public string Version { get; set; }
public string Path { get; set; }
public string Description { get; set; }
}


public class UrlPart
{
private string _description;

public string Argument
public string Argument => $"{LowLevelTypeName} {NameAsArgument}";

public string LowLevelTypeName
{
get
{
//TODO treat list with fixed options as Flags Enum
switch (Type)
{
case "int":
case "int": //does not occur on part
case "number": //does not occur on part
case "string":
return Type + " " + NameAsArgument;
return Type;
case "list":
return "string " + NameAsArgument;
return "string";
case "enum":
return Name.ToPascalCase() + " " + NameAsArgument;
case "number":
return "string " + NameAsArgument;
return Name.ToPascalCase();
default:
return Type + " " + NameAsArgument;
return Type;
}
}
}

public string ClrTypeName
public string HighLevelTypeName
{
get
{
Expand Down Expand Up @@ -116,6 +128,7 @@ public string InterfaceName
public string NameAsArgument => Name.ToCamelCase();
public IEnumerable<string> Options { get; set; }
public bool Required { get; set; }
public bool Deprecated { get; set; }
public string Type { get; set; }

private string CleanUpDescription(string value)
Expand Down
22 changes: 19 additions & 3 deletions src/CodeGeneration/ApiGenerator/Domain/Specification/UrlPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,23 @@ public class UrlPath
{
private readonly List<UrlPart> _additionalPartsForConstructor;
public string Path { get; }
public DeprecatedPath Deprecation { get; }


public List<UrlPart> Parts { get; }

//TODO mark the parts that are deprecated
//TODO this will all go away once https://github.com/elastic/elasticsearch/pull/42346 lands
public UrlPath(DeprecatedPath path, IDictionary<string, UrlPart> originalParts, IReadOnlyCollection<UrlPath> allNonDeprecatedPaths)
: this(path.Path, originalParts)
{
Deprecation = path;
foreach (var part in Parts)
{
if (!part.Deprecated && !allNonDeprecatedPaths.Any(p => p.Path.Contains($"{{{part.Name}}}")))
part.Deprecated = true;
}
}
public UrlPath(string path, IDictionary<string, UrlPart> allParts, List<UrlPart> additionalPartsForConstructor = null)
{
_additionalPartsForConstructor = additionalPartsForConstructor ?? new List<UrlPart>();
Expand All @@ -30,16 +44,18 @@ orderby path.IndexOf($"{{{name}}}", StringComparison.Ordinal)
Parts = parts.ToList();
}

public string ConstructorArguments => string.Join(", ", Parts.Select(p => $"{p.ClrTypeName} {p.NameAsArgument}"));
public string ConstructorArguments => string.Join(", ", Parts.Select(p => $"{p.HighLevelTypeName} {p.NameAsArgument}"));
public string RequestBaseArguments =>
!Parts.Any() ? string.Empty
: "r => r." + string.Join(".", Parts.Select(p => $"{(p.Required ? "Required" : "Optional")}(\"{p.Name}\", {p.NameAsArgument})"));

public string TypedSubClassBaseArguments => string.Join(", ", Parts.Select(p => p.NameAsArgument));

private static string[] ResolvabeFromT = { "index"};


public bool HasResolvableArguments => Parts.Any(p => ResolvabeFromT.Contains(p.Name));
public string AutoResolveConstructorArguments => string.Join(", ", Parts.Where(p => !ResolvabeFromT.Contains(p.Name)).Select(p => $"{p.ClrTypeName} {p.NameAsArgument}"));
public string AutoResolveConstructorArguments => string.Join(", ", Parts.Where(p => !ResolvabeFromT.Contains(p.Name)).Select(p => $"{p.HighLevelTypeName} {p.NameAsArgument}"));

public string AutoResolveBaseArguments(string generic) => string.Join(", ", Parts.Select(p => !ResolvabeFromT.Contains(p.Name) ? p.Name : $"typeof({generic})"));

Expand All @@ -48,7 +64,7 @@ public string DocumentPathBaseArgument(string generic) => string.Join(", ",
: ResolvabeFromT.Contains(p.Name) ? $"{p.Name} ?? typeof({generic})" : p.Name));

public string DocumentPathConstructorArgument(string generic) => string.Join(", ",
new [] { $"{generic} documentWithId" }.Concat(_additionalPartsForConstructor.Select(p => $"{p.ClrTypeName} {p.NameAsArgument} = null")));
new [] { $"{generic} documentWithId" }.Concat(_additionalPartsForConstructor.Select(p => $"{p.HighLevelTypeName} {p.NameAsArgument} = null")));

public string GetXmlDocs(string indent, bool skipResolvable = false, bool documentConstructor = false)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
"url": {
"path": "/_search/scroll",
"paths": [ "/_search/scroll" ],
"parts": {
"scroll_id": {
"type" : "list",
"description" : "A comma-separated list of scroll IDs to clear"
}
},
"deprecated_paths": [
{
"version": "7.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
// values part of the url path
@foreach (UrlPart part in d.Parts)
{
<text> @(Raw(part.ClrTypeName)) @(Raw(baseInterface)).@(part.InterfaceName) => Self.RouteValues.Get@(Raw(string.Format("<{0}>",part.ClrTypeName)))("@(part.Name)");
<text> @(Raw(part.HighLevelTypeName)) @(Raw(baseInterface)).@(part.InterfaceName) => Self.RouteValues.Get@(Raw(string.Format("<{0}>",part.HighLevelTypeName)))("@(part.Name)");
</text>
}
@foreach (FluentRouteSetter c in d.GetFluentRouteSetters())
Expand Down Expand Up @@ -83,8 +83,9 @@
}
@if (names.DescriptorNotFoundInCodebase)
{<text>
//TODO THIS METHOD IS UNMAPPED!
</text>
[Obsolete("Unmapped, blacklist this API in CodeConfiguration.cs or implement @names.DescriptorName and @names.RequestName in a file called @(names.RequestName).cs in NEST's codebase", true)]
public bool IsUnmapped => true;
</text>
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
@foreach (var part in r.Parts)
{
<text> [IgnoreDataMember]
@(Raw(part.ClrTypeName)) @(Raw(r.InterfaceName)).@(part.InterfaceName) => Self.RouteValues.Get@(Raw(string.Format("<{0}>", part.ClrTypeName)))("@(part.Name)");
@(Raw(part.HighLevelTypeName)) @(Raw(r.InterfaceName)).@(part.InterfaceName) => Self.RouteValues.Get@(Raw(string.Format("<{0}>", part.HighLevelTypeName)))("@(part.Name)");
</text>
}

Expand All @@ -50,8 +50,10 @@
</text>
}
@if (names.DescriptorNotFoundInCodebase)
{<text> //TODO THIS METHOD IS UNMAPPED! Expected to find @names.DescriptorName and @names.RequestName in a file called @(names.RequestName).cs in NEST's codebase
</text>
{<text>
[Obsolete("Unmapped, blacklist this API in CodeConfiguration.cs or implement @names.DescriptorName and @names.RequestName in a file called @(names.RequestName).cs in NEST's codebase", true)]
public bool IsUnmapped => true;
</text>
}
}
@if (r.NeedsGenericImplementation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
@foreach (UrlPart part in i.UrlParts)
{
<text> [IgnoreDataMember]
@(Raw(part.ClrTypeName)) @(part.InterfaceName) { get; }
@(Raw(part.HighLevelTypeName)) @(part.InterfaceName) { get; }
</text>
}
@foreach (var partialParam in i.PartialParameters)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</text>
}
///@Raw(@"<param name=""requestParameters"">Request specific configuration such as querystring parameters &amp; request specific connection settings.</param>")
@if (!string.IsNullOrEmpty(method.DeprecatedPath))
@if (method.DeprecatedPath != null)
{
<text> [Obsolete("@method.DeprecatedPath")]
<text> [Obsolete("Deprecated in version @(method.DeprecatedPath.Version): @Raw(method.DeprecatedPath.Description)")]
</text>}
Loading