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

Fix functions as object names in go snippets #2051

Merged
merged 2 commits into from
May 17, 2024
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
14 changes: 14 additions & 0 deletions CodeSnippetsReflection.OpenAPI.Test/GoGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,20 @@ public async Task WritesEmptyPrimitiveArrays() {
Assert.Contains("SetIncludeUserActions", result);
}
[Fact]
public async Task WriteCorrectFunctionNameWithParametersAsModelName()
{
const string messageObject = "{\r\n\"displayName\": \"Display name\"\r\n}";
using var requestPayload = new HttpRequestMessage(HttpMethod.Patch, $"{ServiceRootUrl}/applications(uniqueName='app-65278')")
{
Content = new StringContent(messageObject, Encoding.UTF8, "application/json")
};
requestPayload.Headers.Add("Prefer", "create-if-missing");
var snippetModel = new SnippetModel(requestPayload, ServiceRootUrl, await GetBetaSnippetMetadata());
var result = _generator.GenerateCodeSnippet(snippetModel);
Assert.Contains("graphapplicationswithuniquename \"github.com/microsoftgraph/msgraph-sdk-go/applicationswithuniquename\"", result);
Assert.Contains("graphapplicationswithuniquename.ApplicationsWithUniqueNameRequestBuilderPatchRequestConfiguration", result);
}
[Fact]
public async Task WriteCorrectTypesForFilterParameters()
{
using var requestPayload = new HttpRequestMessage(HttpMethod.Get,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using CodeSnippetsReflection.OpenAPI.ModelGraph;
using CodeSnippetsReflection.StringExtensions;
using Microsoft.OpenApi.Services;
using System.Text.RegularExpressions;
using System.Collections;

namespace CodeSnippetsReflection.OpenAPI.LanguageGenerators
{
public class GoGenerator : ILanguageGenerator<SnippetModel, OpenApiUrlTreeNode>
{
private const string clientVarName = "graphClient";
private const string clientVarType = "GraphServiceClientWithCredentials";
private const string clientFactoryVariables = "cred, scopes";
private const string requestBodyVarName = "requestBody";
private const string requestHeadersVarName = "headers";
private const string optionsParameterVarName = "options";
Expand All @@ -29,6 +27,10 @@

private static readonly Regex PropertyNameRegex = new Regex(@"@(.*)", RegexOptions.Compiled, TimeSpan.FromMilliseconds(200));

private static readonly Regex FunctionRegex = new Regex(@"(\w+)\(([^)]*)\)", RegexOptions.Compiled, TimeSpan.FromMilliseconds(200));

private static readonly Regex ParamRegex = new Regex(@"(\w+)\s*=\s*'[^']*'", RegexOptions.Compiled, TimeSpan.FromMilliseconds(200));

static IImmutableSet<string> GetNativeTypes()
{
return ImmutableHashSet.Create("string", "int", "float");
Expand Down Expand Up @@ -142,9 +144,24 @@

private static String ProcessNameSpaceName(String nameSpace)
{
return (nameSpace != null ? nameSpace.Split(".", StringSplitOptions.RemoveEmptyEntries)
if (String.IsNullOrEmpty(nameSpace))
return "";

// process function names and parameters
var functionNameMatch = FunctionRegex.Match(nameSpace);
if (functionNameMatch.Success)
{
var paramMatches = ParamRegex.Matches(functionNameMatch.Groups[2].Value);
var paramNames = paramMatches.Cast<Match>().Select(static m => m.Groups[1].Value).ToList();

return functionNameMatch.Groups[1].Value + "With" + string.Join("With", paramNames);
}

var processedName = (nameSpace.Split(".", StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Equals("Me", StringComparison.OrdinalIgnoreCase) ? "Users" : x)
.Aggregate((current, next) => current + "." + next) : "models").Replace(".microsoft.graph", "");
.Aggregate(static (current, next) => current + "." + next)).Replace(".microsoft.graph", "");

return processedName;
}

private static String ProcessFinalNameSpaceName(String nameSpace)
Expand Down Expand Up @@ -182,7 +199,7 @@
{
if (property.Children != null && property.Children.Count != 0)
{
var existingChild = property.Children.FirstOrDefault(x => x.PropertyType == propertyType);

Check warning on line 202 in CodeSnippetsReflection.OpenAPI/LanguageGenerators/GoGenerator.cs

View workflow job for this annotation

GitHub Actions / Build

"Find" method should be used instead of the "FirstOrDefault" extension method. (https://rules.sonarsource.com/csharp/RSPEC-6602)
return propertyType == existingChild.PropertyType;
}
return property.PropertyType == propertyType;
Expand Down Expand Up @@ -299,14 +316,14 @@
var isCollection = nodes.First().Segment.IsCollectionIndex();
var isSingleElement = nodes.Count() == 1;

var filteredNodes = (isCollection && !isSingleElement) ? nodes.Skip(2) : isCollection ? nodes.Skip(1) : nodes; // skip first element if its not only element

Check warning on line 319 in CodeSnippetsReflection.OpenAPI/LanguageGenerators/GoGenerator.cs

View workflow job for this annotation

GitHub Actions / Build

Extract this nested ternary operation into an independent statement. (https://rules.sonarsource.com/csharp/RSPEC-3358)
if (!(filteredNodes?.Any() ?? false)) return string.Empty;

Check warning on line 320 in CodeSnippetsReflection.OpenAPI/LanguageGenerators/GoGenerator.cs

View workflow job for this annotation

GitHub Actions / Build

Remove this unnecessary check for null. (https://rules.sonarsource.com/csharp/RSPEC-2589)

Check warning on line 320 in CodeSnippetsReflection.OpenAPI/LanguageGenerators/GoGenerator.cs

View workflow job for this annotation

GitHub Actions / Build

Remove this unnecessary check for null. Some code paths are unreachable. (https://rules.sonarsource.com/csharp/RSPEC-2583)
return filteredNodes.Select(static x =>
{
if (x.Segment.IsCollectionIndex())
return "Item";
else
return x.Segment.ToFirstCharacterUpperCase();
return EscapeFunctionNames(x.Segment.ToFirstCharacterUpperCase());
})
.Aggregate(static (x, y) =>
{
Expand All @@ -316,6 +333,22 @@
});
}

private static string EscapeFunctionNames(String objectName)
{
if (String.IsNullOrEmpty(objectName))
return objectName;

var match = FunctionRegex.Match(objectName);
if (match.Success)
{
var paramMatches = ParamRegex.Matches(match.Groups[2].Value);
var paramNames = paramMatches.Cast<Match>().Select(static m => m.Groups[1].Value.ToFirstCharacterUpperCase()).ToList();

return match.Groups[1].Value + "With" + string.Join("With", paramNames);
}
return objectName;
}

private static string evaluateParameter(CodeProperty param)
{
if (param.PropertyType == PropertyType.Array)
Expand Down Expand Up @@ -358,7 +391,7 @@

private static string GetResultVarName(SnippetCodeGraph codeGraph)
{
var path = codeGraph.Nodes.LastOrDefault(x => !x.IsParameter)?.Path?.Split("\\").Last(static x => !string.IsNullOrWhiteSpace(x)).Split("(").First()

Check warning on line 394 in CodeSnippetsReflection.OpenAPI/LanguageGenerators/GoGenerator.cs

View workflow job for this annotation

GitHub Actions / Build

Indexing at 0 should be used instead of the "Enumerable" extension method "First" (https://rules.sonarsource.com/csharp/RSPEC-6608)
.Split(".")
.Select(static s => s.ToFirstCharacterUpperCase())
.Aggregate(static (a, b) => $"{a}{b}")
Expand Down Expand Up @@ -423,7 +456,7 @@
builder.AppendLine(objectBuilder.ToString());
}

var typeDefinition = codeProperty.TypeDefinition?.ToLowerInvariant()?.Trim();

Check warning on line 459 in CodeSnippetsReflection.OpenAPI/LanguageGenerators/GoGenerator.cs

View workflow job for this annotation

GitHub Actions / Build

Remove this unnecessary check for null. (https://rules.sonarsource.com/csharp/RSPEC-2589)

String typeName;
if (NativeTypes.Contains(typeDefinition))
Expand All @@ -447,7 +480,7 @@

}

private static void WriteCodeProperty(string propertyAssignment, StringBuilder builder, CodeProperty codeProperty, CodeProperty child, IndentManager indentManager, int childPosition = 0, bool declarationOnly = false)

Check warning on line 483 in CodeSnippetsReflection.OpenAPI/LanguageGenerators/GoGenerator.cs

View workflow job for this annotation

GitHub Actions / Build

Refactor this method to reduce its Cognitive Complexity from 23 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)
{
var isArray = codeProperty.PropertyType == PropertyType.Array;
var isMap = codeProperty.PropertyType == PropertyType.Map;
Expand Down Expand Up @@ -606,7 +639,7 @@
.Aggregate(new List<String>(), (current, next) =>
{
var element = next.Contains("ByTypeId", StringComparison.OrdinalIgnoreCase) ?
next.Replace("ByTypeId", $"By{current.Last().Replace("s().", string.Empty, StringComparison.OrdinalIgnoreCase)}Id") :

Check warning on line 642 in CodeSnippetsReflection.OpenAPI/LanguageGenerators/GoGenerator.cs

View workflow job for this annotation

GitHub Actions / Build

Indexing at Count-1 should be used instead of the "Enumerable" extension method "Last" (https://rules.sonarsource.com/csharp/RSPEC-6608)
$"{next.Replace("$", string.Empty, StringComparison.OrdinalIgnoreCase).ToFirstCharacterUpperCase()}";

current.Add(element);
Expand Down
Loading