Skip to content
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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ internal sealed partial class SourceGenerationContext : JsonSerializerContext;
```
- It's all! Now you can build your project and use the generated code with full trimming/nativeAOT support.

## Known Errors

### Generator error: "Could not write to output file 'Path/to/file'. Could not find part of the path"

This error happens if the generated file path is too long. This happens if you didn't activated long path support on windows.
To enable it follow the offical docs:
https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry#registry-setting-to-enable-long-paths

## 📚Examples of use in real SDKs📚
- https://github.com/tryAGI/OpenAI
- https://github.com/tryAGI/Ollama
Expand Down
63 changes: 63 additions & 0 deletions src/libs/AutoSDK/Helpers/Box.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace AutoSDK.Helpers;

public static class BoxEtensions
{
public static T Unbox<T>(this Box box)
{
return (T)box.Value;
}
public static Box Box<T>(this T tobox)
{
return new Box() { Value = tobox };

Check warning on line 11 in src/libs/AutoSDK/Helpers/Box.cs

View workflow job for this annotation

GitHub Actions / Test / Build, test and publish

Possible null reference assignment.

Check warning on line 11 in src/libs/AutoSDK/Helpers/Box.cs

View workflow job for this annotation

GitHub Actions / Test / Build, test and publish

Possible null reference assignment.

Check warning on line 11 in src/libs/AutoSDK/Helpers/Box.cs

View workflow job for this annotation

GitHub Actions / Test / Build, test and publish

Possible null reference assignment.

Check warning on line 11 in src/libs/AutoSDK/Helpers/Box.cs

View workflow job for this annotation

GitHub Actions / Test / Build, test and publish

Possible null reference assignment.

Check warning on line 11 in src/libs/AutoSDK/Helpers/Box.cs

View workflow job for this annotation

GitHub Actions / Test / Build, test and publish

Possible null reference assignment.

Check warning on line 11 in src/libs/AutoSDK/Helpers/Box.cs

View workflow job for this annotation

GitHub Actions / Test / Build, test and publish

Possible null reference assignment.

Check warning on line 11 in src/libs/AutoSDK/Helpers/Box.cs

View workflow job for this annotation

GitHub Actions / Test / Build, test and publish

Possible null reference assignment.

Check warning on line 11 in src/libs/AutoSDK/Helpers/Box.cs

View workflow job for this annotation

GitHub Actions / Test / Build, test and publish

Possible null reference assignment.

Check warning on line 11 in src/libs/AutoSDK/Helpers/Box.cs

View workflow job for this annotation

GitHub Actions / Test / Build, test and publish

Possible null reference assignment.

Check warning on line 11 in src/libs/AutoSDK/Helpers/Box.cs

View workflow job for this annotation

GitHub Actions / Test / Build, test and publish

Possible null reference assignment.
}
}

/// <summary>
/// This class is used to box any value type or reference type into an object.
/// This is used to avoid generic type cycling in structs.
/// This is only here to support visual studio. Other dotnet build tools do not require this.
/// More information can be found here:
/// https://github.com/dotnet/runtime/issues/6924
/// </summary>
public struct Box : IEquatable<Box>
{
private object _value;
public object Value
{
get => _value;
set => _value = value;
}

public override bool Equals(object? obj)
{
if (obj is null)
{
return false;
}
if (obj is Box other)
{
return ReferenceEquals(Value, other.Value);
}
return false;
}

bool IEquatable<Box>.Equals(Box other)
{
return this.Equals(other);
}

public override int GetHashCode()
{
return Value?.GetHashCode() ?? 0;
}

public static bool operator ==(Box left, Box right)
{
return left.Equals(right);
}

public static bool operator !=(Box left, Box right)
{
return !(left == right);
}
}
17 changes: 9 additions & 8 deletions src/libs/AutoSDK/Models/ModelData.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System.Collections.Immutable;
using AutoSDK.Extensions;
using AutoSDK.Helpers;
using System.Collections.Immutable;

namespace AutoSDK.Models;

public record struct ModelData(
SchemaContext SchemaContext,
string Id,
ImmutableArray<ModelData> Parents,
ImmutableArray<Box> Parents,
string Namespace,
Settings Settings,
ModelStyle Style,
Expand All @@ -25,7 +26,7 @@ public static ModelData FromSchemaContext(
SchemaContext context)
{
context = context ?? throw new ArgumentNullException(nameof(context));

var parents = new List<ModelData>();
var parent = context.Parent;
while (parent != null)
Expand All @@ -38,11 +39,11 @@ public static ModelData FromSchemaContext(
}

parents.Reverse();

return new ModelData(
SchemaContext: context,
Id: context.Id,
Parents: parents.ToImmutableArray(),
Parents: parents.Select(p => p.Box()).ToImmutableArray(),
Namespace: context.Settings.Namespace,
Style: context.Schema.IsEnum() ? ModelStyle.Enumeration : context.Settings.ModelStyle,
Settings: context.Settings,
Expand Down Expand Up @@ -82,13 +83,13 @@ public static ModelData FromSchemaContext(
// };

public string GlobalClassName => $"global::{Namespace}.{ClassName}";

public string ExternalClassName => Settings.NamingConvention switch
{
NamingConvention.ConcatNames => ClassName,
NamingConvention.InnerClasses => string.Join(".", Parents.Select(x => x.ClassName).Concat([ClassName])),
NamingConvention.InnerClasses => string.Join(".", Parents.Select(x => x.Unbox<ModelData>().ClassName).Concat([ClassName])),
_ => string.Empty,
};

public string FileNameWithoutExtension => $"{Namespace}.Models.{ExternalClassName}";
}
17 changes: 9 additions & 8 deletions src/libs/AutoSDK/Models/PropertyData.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AutoSDK.Extensions;
using AutoSDK.Helpers;
using AutoSDK.Naming.Properties;

namespace AutoSDK.Models;
Expand Down Expand Up @@ -39,22 +40,22 @@ public static PropertyData FromSchemaContext(SchemaContext context)
{
context = context ?? throw new ArgumentNullException(nameof(context));
var type = context.TypeData;

// OpenAPI doesn't allow metadata for references so sometimes allOf with single item is used to add metadata.
if (context.HasAllOfTypeForMetadata() &&
!type.SubTypes.IsEmpty)
{
type = type.SubTypes[0] with
type = type.SubTypes[0].Unbox<TypeData>() with
{
CSharpTypeRaw = type.SubTypes[0].CSharpTypeRaw,
CSharpTypeRaw = type.SubTypes[0].Unbox<TypeData>().CSharpTypeRaw,
CSharpTypeNullability = type.CSharpTypeNullability,
};
}

var requiredProperties = context.Parent != null
? new HashSet<string>(context.Parent.Schema.Required)
: [];

var propertyName = context.PropertyName ?? throw new InvalidOperationException("Property name or parameter name is required.");
var isRequired =
requiredProperties.Contains(propertyName) &&
Expand All @@ -64,7 +65,7 @@ public static PropertyData FromSchemaContext(SchemaContext context)
{
isRequired = false;
}

return new PropertyData(
Id: propertyName,
Name: CSharpPropertyNameGenerator.ComputePropertyName(context),
Expand All @@ -81,19 +82,19 @@ public static PropertyData FromSchemaContext(SchemaContext context)
DefaultValue: context.Schema is { ReadOnly: true } && !type.CSharpTypeNullability
? "default!"
: context.GetDefaultValue(),
Example: context.Schema.Example?.GetString() is {} example &&
Example: context.Schema.Example?.GetString() is { } example &&
!string.IsNullOrWhiteSpace(example)
? example.ClearForXml()
: null,
Summary: context.Schema.GetSummary(),
ConverterType: type.ConverterType,
DiscriminatorValue: string.Empty);
}

public string ParameterName => Name
.Replace(".", string.Empty)
.ToParameterName()

// https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/
.ReplaceIfEquals("abstract", "@abstract")
.ReplaceIfEquals("as", "@as")
Expand Down
Loading
Loading