Skip to content

Commit

Permalink
- updates dotnet generation so the backing store is now hardcoded any…
Browse files Browse the repository at this point in the history
…more
  • Loading branch information
baywet committed Aug 12, 2021
1 parent 7c2b993 commit e056227
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 28 deletions.
3 changes: 2 additions & 1 deletion src/Kiota.Builder/CodeDOM/CodeParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ public enum CodeParameterKind
HttpCore,
CurrentPath,
Options,
Serializer
Serializer,
BackingStore
}

public class CodeParameter : CodeTerminal, ICloneable, IDocumentedElement
Expand Down
5 changes: 1 addition & 4 deletions src/Kiota.Builder/GenerationConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@ public class GenerationConfiguration {
public string ApiRootUrl { get; set; } = "https://graph.microsoft.com/v1.0";
public List<string> PropertiesPrefixToStrip { get; set; } = new() { "@odata."};
public HashSet<string> IgnoredRequestContentTypes { get; set; } = new();
public string BackingStore { get; set; } = string.Empty;
public bool UsesBackingStore { get; set; }
public List<string> Serializers { get; set; } = new();
public bool UsesBackingStore {
get => !string.IsNullOrEmpty(BackingStore);
}
public List<string> Deserializers { get; set; } = new();
}
}
38 changes: 33 additions & 5 deletions src/Kiota.Builder/KiotaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,35 @@ private void CreatePathManagement(CodeClass currentClass, OpenApiUrlTreeNode cur
Description = httpCoreProperty.Description,
ParameterKind = CodeParameterKind.HttpCore,
});
if(isApiClientClass && config.UsesBackingStore) {
var backingStoreParam = new CodeParameter(constructor) {
Name = "backingStore",
Optional = true,
Description = "The backing store to use for the models.",
ParameterKind = CodeParameterKind.BackingStore,
};
var factoryInterfaceName = $"{backingStoreInterface}Factory";
backingStoreParam.Type = new CodeType(backingStoreParam) {
Name = factoryInterfaceName,
IsNullable = true,
};
constructor.AddParameter(backingStoreParam);
var backingStoreInterfaceUsing = new CodeUsing(currentClass) {
Name = factoryInterfaceName,
};
backingStoreInterfaceUsing.Declaration = new CodeType(backingStoreInterfaceUsing) {
Name = storeNamespaceName,
IsExternal = true,
};
var backingStoreSingletonUsing = new CodeUsing(currentClass) {
Name = backingStoreSingleton,
};
backingStoreSingletonUsing.Declaration = new CodeType(backingStoreSingletonUsing) {
Name = storeNamespaceName,
IsExternal = true,
};
currentClass.AddUsing(backingStoreInterfaceUsing, backingStoreSingletonUsing);
}
}
private static Func<CodeClass, int> shortestNamespaceOrder = (x) => x.Parent.Name.Split('.').Length;
/// <summary>
Expand Down Expand Up @@ -751,6 +780,7 @@ private void CreatePropertiesForModelClass(OpenApiUrlTreeNode currentNode, OpenA
private const string additionalDataPropName = "AdditionalData";
private const string backingStorePropertyName = "BackingStore";
private const string backingStoreInterface = "IBackingStore";
private const string backingStoreSingleton = "BackingStoreFactorySingleton";
private const string backedModelInterface = "IBackedModel";
private const string storeNamespaceName = "Microsoft.Kiota.Abstractions.Store";
private void AddSerializationMembers(CodeClass model, bool includeAdditionalProperties) {
Expand Down Expand Up @@ -809,12 +839,10 @@ private void AddSerializationMembers(CodeClass model, bool includeAdditionalProp
if(!model.ContainsMember(backingStorePropertyName) &&
config.UsesBackingStore &&
!(model.GetGreatestGrandparent(model)?.ContainsMember(backingStorePropertyName) ?? false)) {
var storeImplFragments = config.BackingStore.Split('.');
var storeImplClassName = storeImplFragments.Last();
var backingStoreProperty = new CodeProperty(model) {
Name = backingStorePropertyName,
Access = AccessModifier.Public,
DefaultValue = $"new {storeImplClassName}()",
DefaultValue = $"BackingStoreFactorySingleton.Instance.CreateBackingStore()",
PropertyKind = CodePropertyKind.BackingStore,
Description = "Stores model information.",
ReadOnly = true,
Expand All @@ -841,10 +869,10 @@ private void AddSerializationMembers(CodeClass model, bool includeAdditionalProp
IsExternal = true
};
var storeImplUsing = new CodeUsing(model) {
Name = storeImplClassName,
Name = backingStoreSingleton,
};
storeImplUsing.Declaration = new CodeType(storeImplUsing) {
Name = storeImplFragments.SkipLast(1).Aggregate((x, y) => $"{x}.{y}"),
Name = storeNamespaceName,
IsExternal = true,
};
model.AddUsing(backingStoreUsing, backedModelUsing, storeImplUsing);
Expand Down
2 changes: 1 addition & 1 deletion src/Kiota.Builder/Writers/CSharp/CSharpWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public CSharpWriter(string rootPath, string clientNamespaceName, bool usesBackin
AddCodeElementWriter(new CodeClassEndWriter(conventionService));
AddCodeElementWriter(new CodeEnumWriter(conventionService));
AddCodeElementWriter(new CodeIndexerWriter(conventionService));
AddCodeElementWriter(new CodeMethodWriter(conventionService, usesBackingStore));
AddCodeElementWriter(new CodeMethodWriter(conventionService));
AddCodeElementWriter(new CodePropertyWriter(conventionService));
AddCodeElementWriter(new CodeTypeWriter(conventionService));

Expand Down
10 changes: 4 additions & 6 deletions src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
namespace Kiota.Builder.Writers.CSharp {
public class CodeMethodWriter : BaseElementWriter<CodeMethod, CSharpConventionService>
{
private readonly bool _usesBackingStore;
public CodeMethodWriter(CSharpConventionService conventionService, bool usesBackingStore): base(conventionService) {
_usesBackingStore = usesBackingStore;
}
public CodeMethodWriter(CSharpConventionService conventionService): base(conventionService) { }
public override void WriteCodeElement(CodeMethod codeElement, LanguageWriter writer)
{
if(codeElement == null) throw new ArgumentNullException(nameof(codeElement));
Expand Down Expand Up @@ -67,12 +64,13 @@ public override void WriteCodeElement(CodeMethod codeElement, LanguageWriter wri
private void WriteApiConstructorBody(CodeClass parentClass, CodeMethod method, LanguageWriter writer) {
var httpCoreProperty = parentClass.GetChildElements(true).OfType<CodeProperty>().FirstOrDefault(x => x.IsOfKind(CodePropertyKind.HttpCore));
var httpCoreParameter = method.Parameters.FirstOrDefault(x => x.IsOfKind(CodeParameterKind.HttpCore));
var backingStoreParameter = method.Parameters.FirstOrDefault(x => x.IsOfKind(CodeParameterKind.BackingStore));
var httpCorePropertyName = httpCoreProperty.Name.ToFirstCharacterUpperCase();
writer.WriteLine($"{httpCorePropertyName} = {httpCoreParameter.Name};");
WriteSerializationRegistration(method.SerializerModules, writer, "RegisterDefaultSerializer");
WriteSerializationRegistration(method.DeserializerModules, writer, "RegisterDefaultDeserializer");
if(_usesBackingStore)
writer.WriteLine($"{httpCorePropertyName}.EnableBackingStore();");
if(backingStoreParameter != null)
writer.WriteLine($"{httpCorePropertyName}.EnableBackingStore({backingStoreParameter.Name});");
}
private static void WriteSerializationRegistration(List<string> serializationClassNames, LanguageWriter writer, string methodName) {
if(serializationClassNames != null)
Expand Down
8 changes: 4 additions & 4 deletions src/kiota/KiotaHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public RootCommand GetRootCommand()
var descriptionOption = new Option("--openapi", "The path to the OpenAPI description file used to generate the code files.") {Argument = new Argument<string>(() => "openapi.yml")};
descriptionOption.AddAlias("-d");

var backingStoreOption = new Option("--backing-store", "The fully qualified name for the backing store class to use.") {Argument = new Argument<string>()};
var backingStoreOption = new Option("--backing-store", "Enables backing store for models.") {Argument = new Argument<bool>()};
backingStoreOption.AddAlias("-b");

var serializerOption = new Option<List<String>>("--serializer", "The fully qualified class names for serializers.") { Argument = new Argument<List<string>>(() => new List<string> {"Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory"}) };
Expand All @@ -63,13 +63,13 @@ private void AssignIfNotNullOrEmpty(string input, Action<GenerationConfiguration
if (!string.IsNullOrEmpty(input))
assignment.Invoke(Configuration, input);
}
private delegate Task HandleCommandCallDel(string output, GenerationLanguage? language, string openapi, string backingstore, string classname, LogLevel loglevel, string namespacename, List<string> serializer, List<string> deserializer);
private async Task HandleCommandCall(string output, GenerationLanguage? language, string openapi, string backingstore, string classname, LogLevel loglevel, string namespacename, List<string> serializer, List<string> deserializer) {
private delegate Task HandleCommandCallDel(string output, GenerationLanguage? language, string openapi, bool backingstore, string classname, LogLevel loglevel, string namespacename, List<string> serializer, List<string> deserializer);
private async Task HandleCommandCall(string output, GenerationLanguage? language, string openapi, bool backingstore, string classname, LogLevel loglevel, string namespacename, List<string> serializer, List<string> deserializer) {
AssignIfNotNullOrEmpty(output, (c, s) => c.OutputPath = s);
AssignIfNotNullOrEmpty(openapi, (c, s) => c.OpenAPIFilePath = s);
AssignIfNotNullOrEmpty(classname, (c, s) => c.ClientClassName = s);
AssignIfNotNullOrEmpty(namespacename, (c, s) => c.ClientNamespaceName = s);
AssignIfNotNullOrEmpty(backingstore, (c, s) => c.BackingStore = s.TrimQuotes()); //npm modules can start with @ which prompts some terminals to read response files and quotes are not automatically trimmed by the framework
Configuration.UsesBackingStore = backingstore;
if (language.HasValue)
Configuration.Language = language.Value;
if(serializer?.Any() ?? false)
Expand Down
12 changes: 6 additions & 6 deletions tests/Kiota.Builder.IntegrationTests/GenerateSample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ public class GenerateSample
[InlineData(GenerationLanguage.Java, null)]
[InlineData(GenerationLanguage.TypeScript, null)]
[InlineData(GenerationLanguage.Ruby, null)]
[InlineData(GenerationLanguage.CSharp, "Microsoft.Kiota.Abstractions.Store.InMemoryBackingStore")]
[InlineData(GenerationLanguage.Java, "com.microsoft.kiota.store.InMemoryBackingStore")]
[InlineData(GenerationLanguage.TypeScript, "@microsoft/kiota-abstractions.InMemoryBackingStore")]
[InlineData(GenerationLanguage.CSharp, true)]
[InlineData(GenerationLanguage.Java, true)]
[InlineData(GenerationLanguage.TypeScript, true)]
[Theory]
public async Task GeneratesTodo(GenerationLanguage language, string backingStore) {
public async Task GeneratesTodo(GenerationLanguage language, bool backingStore) {
var logger = LoggerFactory.Create((builder) => {
}).CreateLogger<KiotaBuilder>();

var backingStoreSuffix = string.IsNullOrEmpty(backingStore) ? string.Empty : "BackingStore";
var backingStoreSuffix = backingStore ? string.Empty : "BackingStore";
var configuration = new GenerationConfiguration
{
Language = GenerationLanguage.CSharp,
OpenAPIFilePath = "ToDoApi.yaml",
OutputPath = $".\\Generated\\{language}{backingStoreSuffix}",
BackingStore = backingStore,
UsesBackingStore = backingStore,
};
await new KiotaBuilder(logger, configuration).GenerateSDK();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ public void WritesMethodSyncDescription() {
}
[Fact]
public void Defensive() {
var codeMethodWriter = new CodeMethodWriter(new CSharpConventionService(), false);
var codeMethodWriter = new CodeMethodWriter(new CSharpConventionService());
Assert.Throws<ArgumentNullException>(() => codeMethodWriter.WriteCodeElement(null, writer));
Assert.Throws<ArgumentNullException>(() => codeMethodWriter.WriteCodeElement(method, null));
var originalParent = method.Parent;
Expand Down Expand Up @@ -370,6 +370,15 @@ public void WritesApiConstructorWithBackingStore() {
ParameterKind = CodeParameterKind.HttpCore,
Type = coreProp.Type,
});
var backingStoreParam = new CodeParameter(method) {
Name = "backingStore",
ParameterKind = CodeParameterKind.BackingStore,
};
backingStoreParam.Type = new CodeType(backingStoreParam) {
Name = "IBackingStore",
IsExternal = true,
};
method.AddParameter(backingStoreParam);
var tempWriter = LanguageWriter.GetLanguageWriter(GenerationLanguage.CSharp, defaultPath, defaultName, true);
tempWriter.SetTextWriter(tw);
tempWriter.Write(method);
Expand Down

0 comments on commit e056227

Please sign in to comment.