Skip to content
Open
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
3 changes: 2 additions & 1 deletion src/Kiota.Builder/Export/PublicAPIExportService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ private static ILanguageConventionService GetLanguageConventionServiceFromConfig
{
return generationConfiguration.Language switch
{
GenerationLanguage.CSharp => new CSharpConventionService(),
GenerationLanguage.CSharp => new CSharpConventionService(false),
GenerationLanguage.CSharp13 => new CSharpConventionService(true),
GenerationLanguage.Java => new JavaConventionService(),
GenerationLanguage.TypeScript => new TypeScriptConventionService(),
GenerationLanguage.PHP => new PhpConventionService(),
Expand Down
1 change: 1 addition & 0 deletions src/Kiota.Builder/GenerationLanguage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
public enum GenerationLanguage
{
CSharp,
CSharp13,
Java,
TypeScript,
PHP,
Expand Down
4 changes: 2 additions & 2 deletions src/Kiota.Builder/KiotaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1277,7 +1277,7 @@ private void AddErrorMappingToExecutorMethod(OpenApiUrlTreeNode currentNode, Ope
{
var suffix = $"{operationType}Response";
var modelType = CreateModelDeclarations(currentNode, schema, operation, parentClass, suffix);
if (modelType is not null && config.IncludeBackwardCompatible && config.Language is GenerationLanguage.CSharp or GenerationLanguage.Go && modelType.Name.EndsWith(suffix, StringComparison.Ordinal))
if (modelType is not null && config.IncludeBackwardCompatible && config.Language is GenerationLanguage.CSharp or GenerationLanguage.CSharp13 or GenerationLanguage.Go && modelType.Name.EndsWith(suffix, StringComparison.Ordinal))
{ //TODO remove for v2
var obsoleteTypeName = modelType.Name[..^suffix.Length] + "Response";
if (modelType is CodeType codeType &&
Expand Down Expand Up @@ -2530,7 +2530,7 @@ private void AddPropertyForQueryParameter(OpenApiUrlTreeNode node, OperationType

if (!parameterClass.ContainsPropertyWithWireName(prop.WireName))
{
if (addBackwardCompatibleParameter && config.IncludeBackwardCompatible && config.Language is GenerationLanguage.CSharp or GenerationLanguage.Go)
if (addBackwardCompatibleParameter && config.IncludeBackwardCompatible && config.Language is GenerationLanguage.CSharp or GenerationLanguage.CSharp13 or GenerationLanguage.Go)
{ //TODO remove for v2
var modernProp = (CodeProperty)prop.Clone();
modernProp.Name = $"{prop.Name}As{modernProp.Type.Name.ToFirstCharacterUpperCase()}";
Expand Down
1 change: 1 addition & 0 deletions src/Kiota.Builder/Refiners/ILanguageRefiner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public static async Task RefineAsync(GenerationConfiguration config, CodeNamespa
switch (config.Language)
{
case GenerationLanguage.CSharp:
case GenerationLanguage.CSharp13:
await new CSharpRefiner(config).RefineAsync(generatedCode, cancellationToken).ConfigureAwait(false);
break;
case GenerationLanguage.TypeScript:
Expand Down
4 changes: 2 additions & 2 deletions src/Kiota.Builder/Writers/CLI/CliWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
namespace Kiota.Builder.Writers.Cli;
class CliWriter : CSharpWriter
{
public CliWriter(string rootPath, string clientNamespaceName) : base(rootPath, clientNamespaceName)
public CliWriter(string rootPath, string clientNamespaceName) : base(rootPath, clientNamespaceName, false)
{
var conventionService = new CSharpConventionService();
var conventionService = new CSharpConventionService(false);
AddOrReplaceCodeElementWriter(new CodeClassDeclarationWriter(conventionService));
AddOrReplaceCodeElementWriter(new CodeBlockEndWriter(conventionService));
AddOrReplaceCodeElementWriter(new CodeEnumWriter(conventionService));
Expand Down
48 changes: 47 additions & 1 deletion src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
using static Kiota.Builder.CodeDOM.CodeTypeBase;

namespace Kiota.Builder.Writers.CSharp;
public class CSharpConventionService : CommonLanguageConventionService
public class CSharpConventionService(bool useCSharp13 = false) : CommonLanguageConventionService
{
public override string StreamTypeName => "stream";
public override string VoidTypeName => "void";
Expand All @@ -23,6 +23,7 @@ public class CSharpConventionService : CommonLanguageConventionService

public const string CS0618 = "CS0618";
public const string CS1591 = "CS1591";
public bool UseCSharp13 => useCSharp13;

public static void WriteNullableOpening(LanguageWriter writer)
{
Expand All @@ -41,6 +42,49 @@ public static void WriteNullableClosing(LanguageWriter writer)
ArgumentNullException.ThrowIfNull(writer);
writer.WriteLine("#endif", false);
}
public static void WriteStartingBlock(
LanguageWriter writer,
string line
)
{
ArgumentNullException.ThrowIfNull(writer);
writer.WriteLine(line);
writer.WriteLine("{");
}
public void WriteNullableAware(
LanguageWriter writer,
bool includeNullableReferenceType,
Action<LanguageWriter> nullableCallback,
Action<LanguageWriter> nonNullableCallback)
{
ArgumentNullException.ThrowIfNull(nullableCallback);
ArgumentNullException.ThrowIfNull(nonNullableCallback);

if (!UseCSharp13)
{
if (includeNullableReferenceType)
{
WriteNullableOpening(writer);
nullableCallback(writer);
WriteNullableMiddle(writer);
}
nonNullableCallback(writer);

if (includeNullableReferenceType)
WriteNullableClosing(writer);
}
else
{
if (includeNullableReferenceType)
{
nullableCallback(writer);
}
else
{
nonNullableCallback(writer);
}
}
}
public void WritePragmaDisable(LanguageWriter writer, string code)
{
ArgumentNullException.ThrowIfNull(writer);
Expand Down Expand Up @@ -132,6 +176,8 @@ internal void AddParametersAssignment(LanguageWriter writer, CodeTypeBase pathPa
{
if (nameof(String).Equals(ct.Name, StringComparison.OrdinalIgnoreCase))
nullCheck = $"if (!string.IsNullOrWhiteSpace({identName})) ";
else if (UseCSharp13)
nullCheck = $"if ({identName} is not null) ";
else
nullCheck = $"if ({identName} != null) ";
}
Expand Down
4 changes: 2 additions & 2 deletions src/Kiota.Builder/Writers/CSharp/CSharpWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
namespace Kiota.Builder.Writers.CSharp;
public class CSharpWriter : LanguageWriter
{
public CSharpWriter(string rootPath, string clientNamespaceName)
public CSharpWriter(string rootPath, string clientNamespaceName, bool useCSharp13)
{
PathSegmenter = new CSharpPathSegmenter(rootPath, clientNamespaceName);
var conventionService = new CSharpConventionService();
var conventionService = new CSharpConventionService(useCSharp13);
AddOrReplaceCodeElementWriter(new CodeClassDeclarationWriter(conventionService));
AddOrReplaceCodeElementWriter(new CodeBlockEndWriter(conventionService));
AddOrReplaceCodeElementWriter(new CodeEnumWriter(conventionService));
Expand Down
5 changes: 4 additions & 1 deletion src/Kiota.Builder/Writers/CSharp/CodeBlockEndWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ public override void WriteCodeElement(BlockEnd codeElement, LanguageWriter write
writer.CloseBlock();
if (codeElement?.Parent is CodeClass codeClass && codeClass.Parent is CodeNamespace)
{
writer.CloseBlock();
if (!conventions.UseCSharp13)
{
writer.CloseBlock();
}
conventions.WritePragmaRestore(writer, CSharpConventionService.CS0618);
}
}
Expand Down
11 changes: 9 additions & 2 deletions src/Kiota.Builder/Writers/CSharp/CodeClassDeclarationWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ public override void WriteCodeElement(ClassDeclaration codeElement, LanguageWrit
if (codeElement.Parent?.Parent is CodeNamespace)
{
writer.WriteLine(AutoGenerationHeader);
if (conventions.UseCSharp13)
{
writer.WriteLine(CSharpConventionService.NullableEnableDirective);
}
conventions.WritePragmaDisable(writer, CSharpConventionService.CS0618);
codeElement.Usings
.Where(x => (x.Declaration?.IsExternal ?? true) || !x.Declaration.Name.Equals(codeElement.Name, StringComparison.OrdinalIgnoreCase)) // needed for circular requests patterns like message folder
Expand All @@ -28,8 +32,11 @@ public override void WriteCodeElement(ClassDeclaration codeElement, LanguageWrit
.OrderBy(static x => x, StringComparer.Ordinal)
.ToList()
.ForEach(x => writer.WriteLine(x));
writer.WriteLine($"namespace {codeElement.Parent.Parent.Name}");
writer.StartBlock();
writer.WriteLine($"namespace {codeElement.Parent.Parent.Name}" + (conventions.UseCSharp13 ? ";" : string.Empty));
if (!conventions.UseCSharp13)
{
writer.StartBlock();
}
}

var derivedTypes = (codeElement.Inherits is null ? Enumerable.Empty<string?>() : new string?[] { conventions.GetTypeString(codeElement.Inherits, parentClass) })
Expand Down
34 changes: 15 additions & 19 deletions src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -625,27 +625,23 @@ private void WriteMethodPrototype(CodeMethod code, CodeClass parentClass, Langua
var baseSuffix = GetBaseSuffix(isConstructor, inherits, parentClass, code);
var parameters = string.Join(", ", code.Parameters.OrderBy(x => x, parameterOrderComparer).Select(p => conventions.GetParameterSignature(p, code)).ToList());
var methodName = isConstructor ? parentClass.Name.ToFirstCharacterUpperCase() : code.Name.ToFirstCharacterUpperCase();
var accessModifier = conventions.GetAccessModifier(code.Access);
var includeNullableReferenceType = code.IsOfKind(CodeMethodKind.RequestExecutor, CodeMethodKind.RequestGenerator);
if (includeNullableReferenceType)
{
var completeReturnTypeWithNullable = isConstructor || string.IsNullOrEmpty(genericTypeSuffix) ? completeReturnType : $"{completeReturnType[..^2].TrimEnd('?')}?{genericTypeSuffix} ";
var nullableParameters = string.Join(", ", code.Parameters.Order(parameterOrderComparer)
.Select(p => p.IsOfKind(CodeParameterKind.RequestConfiguration) ?
GetParameterSignatureWithNullableRefType(p, code) :
conventions.GetParameterSignature(p, code))
.ToList());
CSharpConventionService.WriteNullableOpening(writer);
writer.WriteLine($"{conventions.GetAccessModifier(code.Access)} {staticModifier}{hideModifier}{completeReturnTypeWithNullable}{methodName}({nullableParameters}){baseSuffix}");
writer.WriteLine("{");
CSharpConventionService.WriteNullableMiddle(writer);
}

writer.WriteLine($"{conventions.GetAccessModifier(code.Access)} {staticModifier}{hideModifier}{completeReturnType}{methodName}({parameters}){baseSuffix}");
writer.WriteLine("{");

if (includeNullableReferenceType)
CSharpConventionService.WriteNullableClosing(writer);
var completeReturnTypeWithNullable = isConstructor || string.IsNullOrEmpty(genericTypeSuffix) ? completeReturnType : $"{completeReturnType[..^2].TrimEnd('?')}?{genericTypeSuffix} ";
var nullableParameters = string.Join(", ", code.Parameters.Order(parameterOrderComparer)
.Select(p => p.IsOfKind(CodeParameterKind.RequestConfiguration) ?
GetParameterSignatureWithNullableRefType(p, code) :
conventions.GetParameterSignature(p, code))
.ToList());
var nullableSignature = $"{accessModifier} {staticModifier}{hideModifier}{completeReturnTypeWithNullable}{methodName}({nullableParameters}){baseSuffix}";
var nonNullableSignature = $"{accessModifier} {staticModifier}{hideModifier}{completeReturnType}{methodName}({parameters}){baseSuffix}";

conventions.WriteNullableAware(
writer,
includeNullableReferenceType,
writer => CSharpConventionService.WriteStartingBlock(writer, nullableSignature),
writer => CSharpConventionService.WriteStartingBlock(writer, nonNullableSignature)
);
}

private string GetParameterSignatureWithNullableRefType(CodeParameter parameter, CodeElement targetElement)
Expand Down
29 changes: 13 additions & 16 deletions src/Kiota.Builder/Writers/CSharp/CodePropertyWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,12 @@ public override void WriteCodeElement(CodeProperty codeElement, LanguageWriter w
CodePropertyKind.QueryParameter);// Other property types are appropriately constructor initialized
conventions.WriteShortDescription(codeElement, writer);
conventions.WriteDeprecationAttribute(codeElement, writer);
if (isNullableReferenceType)
{
CSharpConventionService.WriteNullableOpening(writer);
WritePropertyInternal(codeElement, writer, $"{propertyType}?");
CSharpConventionService.WriteNullableMiddle(writer);
}

WritePropertyInternal(codeElement, writer, propertyType);// Always write the normal way

if (isNullableReferenceType)
CSharpConventionService.WriteNullableClosing(writer);
conventions.WriteNullableAware(
writer,
isNullableReferenceType,
writer => WritePropertyInternal(codeElement, writer, $"{propertyType}?"),
writer => WritePropertyInternal(codeElement, writer, propertyType)
);
}

private void WritePropertyInternal(CodeProperty codeElement, LanguageWriter writer, string propertyType)
Expand All @@ -38,10 +33,12 @@ private void WritePropertyInternal(CodeProperty codeElement, LanguageWriter writ
var setterAccessModifier = codeElement.ReadOnly && codeElement.Access > AccessModifier.Private ? "private " : string.Empty;
var simpleBody = $"get; {setterAccessModifier}set;";
var defaultValue = string.Empty;
var accessModifier = conventions.GetAccessModifier(codeElement.Access);
var codeElementNameFirstCharacterUpperCase = codeElement.Name.ToFirstCharacterUpperCase();
switch (codeElement.Kind)
{
case CodePropertyKind.RequestBuilder:
writer.WriteLine($"{conventions.GetAccessModifier(codeElement.Access)} {propertyType} {codeElement.Name.ToFirstCharacterUpperCase()}");
writer.WriteLine($"{accessModifier} {propertyType} {codeElementNameFirstCharacterUpperCase}");
writer.StartBlock();
writer.Write("get => ");
conventions.AddRequestBuilderBody(parentClass, propertyType, writer, includeIndent: false);
Expand All @@ -52,17 +49,17 @@ private void WritePropertyInternal(CodeProperty codeElement, LanguageWriter writ
var backingStoreKey = codeElement.WireName;
var nullableOp = !codeElement.IsOfKind(CodePropertyKind.AdditionalData) ? "?" : string.Empty;
var defaultPropertyValue = codeElement.IsOfKind(CodePropertyKind.AdditionalData) ? " ?? new Dictionary<string, object>()" : string.Empty;
writer.WriteLine($"{conventions.GetAccessModifier(codeElement.Access)} {propertyType} {codeElement.Name.ToFirstCharacterUpperCase()}");
writer.WriteLine($"{accessModifier} {propertyType} {codeElementNameFirstCharacterUpperCase}");
writer.StartBlock();
writer.WriteLine($"get {{ return {backingStoreProperty.Name.ToFirstCharacterUpperCase()}{nullableOp}.Get<{propertyType}>(\"{backingStoreKey}\"){defaultPropertyValue}; }}");
writer.WriteLine($"set {{ {backingStoreProperty.Name.ToFirstCharacterUpperCase()}{nullableOp}.Set(\"{backingStoreKey}\", value); }}");
writer.CloseBlock();
break;
case CodePropertyKind.ErrorMessageOverride when parentClass.IsErrorDefinition:
if (parentClass.GetPrimaryMessageCodePath(static x => x.Name.ToFirstCharacterUpperCase(), static x => x.Name.ToFirstCharacterUpperCase(), "?.") is string primaryMessageCodePath && !string.IsNullOrEmpty(primaryMessageCodePath))
writer.WriteLine($"public override {propertyType} {codeElement.Name.ToFirstCharacterUpperCase()} {{ get => {primaryMessageCodePath} ?? string.Empty; }}");
writer.WriteLine($"public override {propertyType} {codeElementNameFirstCharacterUpperCase} {{ get => {primaryMessageCodePath} ?? string.Empty; }}");
else
writer.WriteLine($"public override {propertyType} {codeElement.Name.ToFirstCharacterUpperCase()} {{ get => base.Message; }}");
writer.WriteLine($"public override {propertyType} {codeElementNameFirstCharacterUpperCase} {{ get => base.Message; }}");
break;
case CodePropertyKind.QueryParameter when codeElement.IsNameEscaped:
writer.WriteLine($"[QueryParameter(\"{codeElement.SerializationName}\")]");
Expand All @@ -71,7 +68,7 @@ private void WritePropertyInternal(CodeProperty codeElement, LanguageWriter writ
defaultValue = $" = new {propertyType}();";
goto default;
default:
writer.WriteLine($"{conventions.GetAccessModifier(codeElement.Access)} {propertyType} {codeElement.Name.ToFirstCharacterUpperCase()} {{ {simpleBody} }}{defaultValue}");
writer.WriteLine($"{accessModifier} {propertyType} {codeElementNameFirstCharacterUpperCase} {{ {simpleBody} }}{defaultValue}");
break;
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/Kiota.Builder/Writers/LanguageWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ public static LanguageWriter GetLanguageWriter(GenerationLanguage language, stri
{
return language switch
{
GenerationLanguage.CSharp => new CSharpWriter(outputPath, clientNamespaceName),
GenerationLanguage.CSharp => new CSharpWriter(outputPath, clientNamespaceName, false),
GenerationLanguage.CSharp13 => new CSharpWriter(outputPath, clientNamespaceName, true),
GenerationLanguage.Java => new JavaWriter(outputPath, clientNamespaceName),
GenerationLanguage.TypeScript => new TypeScriptWriter(outputPath, clientNamespaceName),
GenerationLanguage.Ruby => new RubyWriter(outputPath, clientNamespaceName),
Expand Down
Loading
Loading