From 9804c53f4c48ae1a362e9f5a21f96ea08fccb602 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Wed, 21 Apr 2021 10:36:00 +0100 Subject: [PATCH] Add mechanism to escape C# keywords for path parts (#5563) --- .../Domain/Code/LowLevel/LowLevelClientMethod.cs | 3 +-- src/ApiGenerator/Domain/Specification/UrlPart.cs | 9 +++------ src/ApiGenerator/Domain/Specification/UrlPath.cs | 13 ++++++------- src/ApiGenerator/Extensions.cs | 7 +++++-- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/ApiGenerator/Domain/Code/LowLevel/LowLevelClientMethod.cs b/src/ApiGenerator/Domain/Code/LowLevel/LowLevelClientMethod.cs index 2f61a3294b7..097ae45914f 100644 --- a/src/ApiGenerator/Domain/Code/LowLevel/LowLevelClientMethod.cs +++ b/src/ApiGenerator/Domain/Code/LowLevel/LowLevelClientMethod.cs @@ -33,9 +33,8 @@ public string UrlInCode { string Evaluator(Match m) { - var arg = m.Groups[^1].Value.ToCamelCase(); - return $"{{{arg}:{arg}}}"; + return $"{{{arg.ReservedKeywordReplacer()}:{arg}}}"; } var url = Path.TrimStart('/'); diff --git a/src/ApiGenerator/Domain/Specification/UrlPart.cs b/src/ApiGenerator/Domain/Specification/UrlPart.cs index bdf370310ac..a5c28e1c6c4 100644 --- a/src/ApiGenerator/Domain/Specification/UrlPart.cs +++ b/src/ApiGenerator/Domain/Specification/UrlPart.cs @@ -139,17 +139,14 @@ public string InterfaceName } public string Name { get; set; } - public string NameAsArgument => Name.ToCamelCase(); + public string NameAsArgument => Name.ToCamelCase().ReservedKeywordReplacer(); public IEnumerable Options { get; set; } public bool Required { get; set; } public bool Deprecated { get; set; } public string Type { get; set; } - private string CleanUpDescription(string value) - { - if (string.IsNullOrWhiteSpace(value)) return value; - return value.Replace("use `_all` or empty string", "use the special string `_all` or Indices.All"); - } + + private static string CleanUpDescription(string value) => string.IsNullOrWhiteSpace(value) ? value : value.Replace("use `_all` or empty string", "use the special string `_all` or Indices.All"); } } diff --git a/src/ApiGenerator/Domain/Specification/UrlPath.cs b/src/ApiGenerator/Domain/Specification/UrlPath.cs index 844df50667f..ac3fd59a61e 100644 --- a/src/ApiGenerator/Domain/Specification/UrlPath.cs +++ b/src/ApiGenerator/Domain/Specification/UrlPath.cs @@ -55,17 +55,16 @@ orderby path.IndexOf($"{{{name}}}", StringComparison.Ordinal) public string TypedSubClassBaseArguments => string.Join(", ", Parts.Select(p => p.NameAsArgument)); - private static string[] ResolvabeFromT = { "index"}; + private static readonly string[] ResolvableFromT = { "index"}; + public bool HasResolvableArguments => Parts.Any(p => ResolvableFromT.Contains(p.Name)); + public string AutoResolveConstructorArguments => string.Join(", ", Parts.Where(p => !ResolvableFromT.Contains(p.Name)).Select(p => $"{p.HighLevelTypeName} {p.NameAsArgument}")); - 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.HighLevelTypeName} {p.NameAsArgument}")); - - public string AutoResolveBaseArguments(string generic) => string.Join(", ", Parts.Select(p => !ResolvabeFromT.Contains(p.Name) ? p.Name : $"typeof({generic})")); + public string AutoResolveBaseArguments(string generic) => string.Join(", ", Parts.Select(p => !ResolvableFromT.Contains(p.Name) ? p.Name : $"typeof({generic})")); public string DocumentPathBaseArgument(string generic) => string.Join(", ", _additionalPartsForConstructor.Select(p => p.Name =="id" ? $"id ?? Nest.Id.From(documentWithId)" - : ResolvabeFromT.Contains(p.Name) ? $"{p.Name} ?? typeof({generic})" : p.Name)); + : ResolvableFromT.Contains(p.Name) ? $"{p.Name} ?? typeof({generic})" : p.Name)); public string DocumentPathConstructorArgument(string generic) => string.Join(", ", new [] { $"{generic} documentWithId" }.Concat(_additionalPartsForConstructor.Select(p => $"{p.HighLevelTypeName} {p.NameAsArgument} = null"))); @@ -73,7 +72,7 @@ public string DocumentPathConstructorArgument(string generic) => string.Join(", public string GetXmlDocs(string indent, bool skipResolvable = false, bool documentConstructor = false) { var doc = $@"///{Path}"; - var parts = Parts.Where(p => !skipResolvable || !ResolvabeFromT.Contains(p.Name)).ToList(); + var parts = Parts.Where(p => !skipResolvable || !ResolvableFromT.Contains(p.Name)).ToList(); if (!parts.Any()) return doc; doc += indent; diff --git a/src/ApiGenerator/Extensions.cs b/src/ApiGenerator/Extensions.cs index f8babf171b0..b7d05d92a9d 100644 --- a/src/ApiGenerator/Extensions.cs +++ b/src/ApiGenerator/Extensions.cs @@ -43,7 +43,10 @@ public static string ToCamelCase(this string s) return pascal[0].ToLower() + pascal.Substring(1); } - public static string SplitPascalCase(this string s) => - Regex.Replace(s, "([A-Z]+[a-z]*)", " $1").Trim(); + private static readonly Dictionary ReservedNames = new() { { "namespace", "@namespace" } }; + + public static string ReservedKeywordReplacer(this string name) => ReservedNames.ContainsKey(name) ? ReservedNames[name] : name; + + public static string SplitPascalCase(this string s) => Regex.Replace(s, "([A-Z]+[a-z]*)", " $1").Trim(); } }