Skip to content

Commit

Permalink
Add use import statements for PHP Snippets (#2000)
Browse files Browse the repository at this point in the history
* Draft php imports in snippets

* fix import paths for models and request builders php

* add imports after opening php tag

* fix request builder namespace paths

* fix request builder namespace and path

* do not transform imports parts to lowercase or snake case

* replace . with \\ in requestbuilder namespace path

* replace . with \\ in requestbuilder namespace path

* remove double slashes on request builder path

* fix replace dots with slashes on import paths

* fix replace dots with slashes on import paths -change case

* fix dot to slash replacement

* fix dot to slash replacement

* Update request builder path

* Update request builder path - change casing

* remove double slashes on request builder paths

* remove equest builder name- use namespace only for imports

* remove model name - use model namespace without fqcn

* remove model name - use model namespace without fqcn

* unit tests for php use statements

* add unit tests for use statements in php snippets

* move tests to php generator test

* fix code coverage

* remove request builder imports - namespaces are enough

* add request builder filename to import

* add model and request builder class name import

* fix tests include class names on imports

* fix import class names

* improve code readability

* fix indentation

* update classname in imports

* fix casing for request builder name

* fix casing for request builder name

* Update tests to reflect request builde class names

* remove duplicate unit tests

* fix failing tests

* fix failing tests

* Convert importsgenerator to static class

* Fix snippet import tests

* remove duplcate unit tests
  • Loading branch information
shemogumbe authored Mar 26, 2024
1 parent 656e5c4 commit 94e5641
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 10 deletions.
1 change: 1 addition & 0 deletions CodeSnippetsReflection.OpenAPI.Test/PhpGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public async Task GeneratesTheCorrectFluentApiPathForIndexedCollections()
var snippetModel = new SnippetModel(requestPayload, ServiceRootUrl, await GetV1SnippetMetadata());
var result = _generator.GenerateCodeSnippet(snippetModel);
Assert.Contains("->me()->messages()->byMessageId('message-id')", result);

}

[Fact]
Expand Down
78 changes: 78 additions & 0 deletions CodeSnippetsReflection.OpenAPI.Test/PhpImportGeneratorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using CodeSnippetsReflection.OpenAPI.LanguageGenerators;
using Xunit;

namespace CodeSnippetsReflection.OpenAPI.Test;

public class PhpImportTests : OpenApiSnippetGeneratorTestBase
{
private readonly PhpGenerator _generator = new();

[Fact]
public async Task GeneratesRequestBuilderImports()
{
using var requestPayload = new HttpRequestMessage(HttpMethod.Get, $"{ServiceRootUrl}/me/calendar/events?$filter=startsWith(subject,'All')");
var snippetModel = new SnippetModel(requestPayload, ServiceRootUrl, await GetV1SnippetMetadata());
var result = _generator.GenerateCodeSnippet(snippetModel);
Assert.Contains("use Microsoft\\Graph\\GraphServiceClient;", result);
Assert.Contains("use Microsoft\\Graph\\Generated\\Users\\Item\\Calendar\\Events\\EventsRequestBuilderGetRequestConfiguration;", result);
}

[Fact]
public async Task GenerateModelImports(){
var bodyContent = @"{
""displayName"": ""New display name""
}";
using var requestPayload = new HttpRequestMessage(HttpMethod.Patch, $"{ServiceRootUrl}/applications/{{id}}")
{
Content = new StringContent(bodyContent, Encoding.UTF8, "application/json")
};
var snippetModel = new SnippetModel(requestPayload, ServiceRootUrl, await GetV1SnippetMetadata());
var result = _generator.GenerateCodeSnippet(snippetModel);
Assert.Contains("use Microsoft\\Graph\\GraphServiceClient;", result);
Assert.Contains("use Microsoft\\Graph\\Generated\\Models\\Application;", result);

}
[Fact]
public async Task GenerateComplexModelImports(){
var bodyContent = @"{
""subject"": ""Annual review"",
""body"": {
""contentType"": ""HTML"",
""content"": ""You should be proud!""
},
""toRecipients"": [
{
""emailAddress"": {
""address"": ""[email protected]""
}
}
],
""extensions"": [
{
""@odata.type"": ""microsoft.graph.openTypeExtension"",
""extensionName"": ""Com.Contoso.Referral"",
""companyName"": ""Wingtip Toys"",
""expirationDate"": ""2015-12-30T11:00:00.000Z"",
""dealValue"": 10000
}
]
}";
using var requestPayload = new HttpRequestMessage(HttpMethod.Post, $"{ServiceRootUrl}/me/messages/")
{
Content = new StringContent(bodyContent, Encoding.UTF8, "application/json")
};
var snippetModel = new SnippetModel(requestPayload, ServiceRootUrl, await GetV1SnippetMetadata());
var result = _generator.GenerateCodeSnippet(snippetModel);
Assert.Contains("use Microsoft\\Graph\\GraphServiceClient;", result);
Assert.Contains("use Microsoft\\Graph\\Generated\\Models\\Message;", result);
Assert.Contains("use Microsoft\\Graph\\Generated\\Models\\ItemBody;", result);
Assert.Contains("use Microsoft\\Graph\\Generated\\Models\\Recipient;", result);
Assert.Contains("use Microsoft\\Graph\\Generated\\Models\\EmailAddress;", result);
Assert.Contains("use Microsoft\\Graph\\Generated\\Models\\Extension;", result);
Assert.Contains("use Microsoft\\Graph\\Generated\\Models\\OpenTypeExtension;", result);
}
}
6 changes: 2 additions & 4 deletions CodeSnippetsReflection.OpenAPI.Test/SnippetImportTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ public async Task TestGenerateImportTemplatesForModelImports()
Content = new StringContent(userJsonObject, Encoding.UTF8, "application/json")
};
var snippetModel = new SnippetModel(requestPayload, ServiceRootUrl, await GetV1SnippetMetadata());
var importsGenerator = new ImportsGenerator();
var result = importsGenerator.GenerateImportTemplates(snippetModel);
var result = ImportsGenerator.GenerateImportTemplates(snippetModel);
Assert.NotNull(result);
Assert.IsType<List<ImportTemplate>>(result);
Assert.Equal(2, result.Count);
Expand All @@ -36,8 +35,7 @@ public async Task TestGenerateImportTemplatesForRequestBuilderImports()
{
using var requestPayload = new HttpRequestMessage(HttpMethod.Get, $"{ServiceRootUrl}/me/calendar/events?$filter=startsWith(subject,'All')");
var snippetModel = new SnippetModel(requestPayload, ServiceRootUrl, await GetV1SnippetMetadata());
var importsGenerator = new ImportsGenerator();
var result = importsGenerator.GenerateImportTemplates(snippetModel);
var result = ImportsGenerator.GenerateImportTemplates(snippetModel);
Assert.NotNull(result);
Assert.IsType<List<ImportTemplate>>(result);
Assert.NotNull(result[0].Path);
Expand Down
45 changes: 45 additions & 0 deletions CodeSnippetsReflection.OpenAPI/LanguageGenerators/PhpGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,54 @@ public string GenerateCodeSnippet(SnippetModel snippetModel)
WriteObjectProperty(RequestBodyVarName, payloadSb, codeGraph.Body, indentManager);
}
WriteRequestExecutionPath(codeGraph, payloadSb, indentManager);
var importStatements = GetImportStatements(snippetModel);
var phpTagIndex = payloadSb.ToString().IndexOf("<?php");
if (phpTagIndex >= 0)
{
var insertPosition = phpTagIndex + "<?php".Length + Environment.NewLine.Length;
payloadSb.Insert(insertPosition, string.Join(Environment.NewLine, importStatements) + Environment.NewLine);
}
else
{
payloadSb.Insert(0, string.Join(Environment.NewLine, importStatements) + Environment.NewLine);
}
return payloadSb.ToString().Trim();
}
private static HashSet<string> GetImportStatements(SnippetModel snippetModel)
{
const string modelImportPrefix = "use Microsoft\\Graph\\Generated\\Models";
const string requestBuilderImportPrefix = "use Microsoft\\Graph\\Generated";

var snippetImports = new HashSet<string>();

snippetImports.Add("use Microsoft\\Graph\\GraphServiceClient;");

var imports = ImportsGenerator.GenerateImportTemplates(snippetModel);
foreach (var import in imports)
{
switch (import.Kind)
{
case ImportKind.Model:
var typeDefinition = import.ModelProperty.TypeDefinition;
if (typeDefinition != null){
snippetImports.Add($"{modelImportPrefix}\\{typeDefinition};");
// check if model has a nested namespace and append it to the import statement
}
break;

case ImportKind.Path:
if (!string.IsNullOrEmpty(import.Path) && !string.IsNullOrEmpty(import.RequestBuilderName))
{
//construct path to request builder
var importPath = import.Path.Split('.')
.Select(static s => s.ToFirstCharacterUpperCase()).ToArray();
snippetImports.Add($"{requestBuilderImportPrefix}{string.Join("\\", importPath).Replace("\\Me\\", "\\Users\\Item\\")}\\{import.RequestBuilderName}{import.HttpMethod.ToLowerInvariant().ToFirstCharacterUpperCase()}RequestConfiguration;");
}
break;
}
}
return snippetImports;
}
private static void WriteRequestExecutionPath(SnippetCodeGraph codeGraph, StringBuilder payloadSb, IndentManager indentManager)
{
var method = codeGraph.HttpMethod.Method.ToLower();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ private static HashSet<string> GetImportStatements(SnippetModel snippetModel)

snippetImports.Add("from msgraph import GraphServiceClient");

var importsGenerator = new ImportsGenerator();
var imports = importsGenerator.GenerateImportTemplates(snippetModel);
var imports = ImportsGenerator.GenerateImportTemplates(snippetModel);
foreach (var import in imports)
{
switch (import.Kind)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using CodeSnippetsReflection.StringExtensions;
using Microsoft.OpenApi.Services;


namespace CodeSnippetsReflection.OpenAPI.LanguageGenerators
{
public enum ImportKind
Expand Down Expand Up @@ -33,13 +34,17 @@ public string RequestBuilderName
{
get; set;
}
public string HttpMethod
{
get; set;
}
}

public class ImportsGenerator
public static class ImportsGenerator
{
public List<ImportTemplate> imports = new();
public static List<ImportTemplate> imports = new();

public List<ImportTemplate> GenerateImportTemplates(SnippetModel snippetModel)
public static List<ImportTemplate> GenerateImportTemplates(SnippetModel snippetModel)
{
var codeGraph = new SnippetCodeGraph(snippetModel);
var imports = new List<ImportTemplate>();
Expand All @@ -55,7 +60,8 @@ public List<ImportTemplate> GenerateImportTemplates(SnippetModel snippetModel)
{
Kind = ImportKind.Path,
Path = Regex.Replace(path.Replace("\\", ".").Replace("()", ""), @"\{[^}]*-id\}", "item", RegexOptions.Compiled, TimeSpan.FromSeconds(60)),
RequestBuilderName = requestBuilderName
RequestBuilderName = requestBuilderName,
HttpMethod = codeGraph.HttpMethod.ToString()
});
}
}
Expand Down

0 comments on commit 94e5641

Please sign in to comment.