Skip to content

Commit 06faf09

Browse files
committed
feat: Initial work on generators.
1 parent 5fccf44 commit 06faf09

33 files changed

+1472
-80
lines changed

Anthropic.sln

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FixOpenApiSpec", "src\helpe
3131
EndProject
3232
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrimmingHelper", "src\helpers\TrimmingHelper\TrimmingHelper.csproj", "{873883B4-3C46-417F-9C30-ADE8391B1B24}"
3333
EndProject
34+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Anthropic.Generators", "src\libs\Anthropic.Generators\Anthropic.Generators.csproj", "{35422342-E805-4CE0-A073-E9BA501D310C}"
35+
EndProject
36+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Anthropic.Generators.Core", "src\libs\Anthropic.Generators.Core\Anthropic.Generators.Core.csproj", "{F6543F42-163A-4530-B30C-FFBFB610812A}"
37+
EndProject
38+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Anthropic.SnapshotTests", "src\tests\Anthropic.SnapshotTests\Anthropic.SnapshotTests.csproj", "{BDD832C8-2EA8-4F19-9A67-E34CA75EF585}"
39+
EndProject
3440
Global
3541
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3642
Debug|Any CPU = Debug|Any CPU
@@ -53,6 +59,18 @@ Global
5359
{873883B4-3C46-417F-9C30-ADE8391B1B24}.Debug|Any CPU.Build.0 = Debug|Any CPU
5460
{873883B4-3C46-417F-9C30-ADE8391B1B24}.Release|Any CPU.ActiveCfg = Release|Any CPU
5561
{873883B4-3C46-417F-9C30-ADE8391B1B24}.Release|Any CPU.Build.0 = Release|Any CPU
62+
{35422342-E805-4CE0-A073-E9BA501D310C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
63+
{35422342-E805-4CE0-A073-E9BA501D310C}.Debug|Any CPU.Build.0 = Debug|Any CPU
64+
{35422342-E805-4CE0-A073-E9BA501D310C}.Release|Any CPU.ActiveCfg = Release|Any CPU
65+
{35422342-E805-4CE0-A073-E9BA501D310C}.Release|Any CPU.Build.0 = Release|Any CPU
66+
{F6543F42-163A-4530-B30C-FFBFB610812A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
67+
{F6543F42-163A-4530-B30C-FFBFB610812A}.Debug|Any CPU.Build.0 = Debug|Any CPU
68+
{F6543F42-163A-4530-B30C-FFBFB610812A}.Release|Any CPU.ActiveCfg = Release|Any CPU
69+
{F6543F42-163A-4530-B30C-FFBFB610812A}.Release|Any CPU.Build.0 = Release|Any CPU
70+
{BDD832C8-2EA8-4F19-9A67-E34CA75EF585}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
71+
{BDD832C8-2EA8-4F19-9A67-E34CA75EF585}.Debug|Any CPU.Build.0 = Debug|Any CPU
72+
{BDD832C8-2EA8-4F19-9A67-E34CA75EF585}.Release|Any CPU.ActiveCfg = Release|Any CPU
73+
{BDD832C8-2EA8-4F19-9A67-E34CA75EF585}.Release|Any CPU.Build.0 = Release|Any CPU
5674
EndGlobalSection
5775
GlobalSection(SolutionProperties) = preSolution
5876
HideSolutionNode = FALSE
@@ -62,6 +80,9 @@ Global
6280
{2C15EAC0-08E6-447A-84E2-1398DDE358AC} = {AAA11B78-2764-4520-A97E-46AA7089A588}
6381
{65F8337C-FFAB-4A00-BFFE-E2E168B98488} = {5ECA2F6E-0559-459F-9D45-92B7677AD490}
6482
{873883B4-3C46-417F-9C30-ADE8391B1B24} = {5ECA2F6E-0559-459F-9D45-92B7677AD490}
83+
{35422342-E805-4CE0-A073-E9BA501D310C} = {61E7E11E-4558-434C-ACE8-06316A3097B3}
84+
{F6543F42-163A-4530-B30C-FFBFB610812A} = {61E7E11E-4558-434C-ACE8-06316A3097B3}
85+
{BDD832C8-2EA8-4F19-9A67-E34CA75EF585} = {AAA11B78-2764-4520-A97E-46AA7089A588}
6586
EndGlobalSection
6687
GlobalSection(ExtensibilityGlobals) = postSolution
6788
SolutionGuid = {CED9A020-DBA5-4BE6-8096-75E528648EC1}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net4.6.2;netstandard2.0;net6.0;net8.0</TargetFrameworks>
5+
<IsPackable>false</IsPackable>
6+
<GenerateDocumentationFile>false</GenerateDocumentationFile>
7+
<NoWarn>$(NoWarn);CA1308</NoWarn>
8+
</PropertyGroup>
9+
10+
<ItemGroup Label="Global Usings">
11+
<Using Include="System.Net.Http" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<PackageReference Include="PolySharp" Version="1.14.1">
16+
<PrivateAssets>all</PrivateAssets>
17+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
18+
</PackageReference>
19+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.1" PrivateAssets="all" />
20+
</ItemGroup>
21+
22+
</Project>
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
using System.ComponentModel;
2+
using H.Generators;
3+
using Microsoft.CodeAnalysis;
4+
5+
namespace Anthropic.Generators.Core.Conversion;
6+
7+
public static class ToModels
8+
{
9+
public static InterfaceData PrepareData(
10+
this INamedTypeSymbol interfaceSymbol)
11+
{
12+
interfaceSymbol = interfaceSymbol ?? throw new ArgumentNullException(nameof(interfaceSymbol));
13+
14+
var methods = interfaceSymbol
15+
.GetMembers()
16+
.OfType<IMethodSymbol>()
17+
.Where(static x => x.MethodKind == MethodKind.Ordinary)
18+
.Select(static x => new MethodData(
19+
Name: x.Name,
20+
Description: GetDescription(x),
21+
IsAsync: x.IsAsync || x.ReturnType.Name == "Task",
22+
IsVoid: x.ReturnsVoid,
23+
Parameters: new OpenApiSchema(
24+
Name: x.Name,
25+
Description: GetDescription(x),
26+
Type: "object",
27+
SchemaType: "object",
28+
Properties:
29+
x.Parameters
30+
.Where(static x => x.Type.MetadataName != "CancellationToken")
31+
.Select(static x => ToParameterData(
32+
typeSymbol: x.Type,
33+
name: x.Name,
34+
description: GetDescription(x),
35+
isRequired: !x.IsOptional))
36+
.ToArray(),
37+
EnumValues: Array.Empty<string>(),
38+
IsNullable: false,
39+
IsRequired: true,
40+
Format: null,
41+
ArrayItem: Array.Empty<OpenApiSchema>(),
42+
DefaultValue: string.Empty)))
43+
.ToArray();
44+
45+
return new InterfaceData(
46+
Namespace: interfaceSymbol.ContainingNamespace.ToDisplayString(),
47+
Name: interfaceSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
48+
Methods: methods);
49+
}
50+
51+
private static OpenApiSchema ToParameterData(ITypeSymbol typeSymbol, string? name = null, string? description = null, bool isRequired = true)
52+
{
53+
string schemaType;
54+
string? format = null;
55+
var properties = Array.Empty<OpenApiSchema>();
56+
OpenApiSchema? arrayItem = null;
57+
switch (typeSymbol.TypeKind)
58+
{
59+
case TypeKind.Enum:
60+
schemaType = "string";
61+
break;
62+
63+
case TypeKind.Structure:
64+
switch (typeSymbol.SpecialType)
65+
{
66+
case SpecialType.System_Int32:
67+
schemaType = "integer";
68+
format = "int32";
69+
break;
70+
71+
case SpecialType.System_Int64:
72+
schemaType = "integer";
73+
format = "int64";
74+
break;
75+
76+
case SpecialType.System_Single:
77+
schemaType = "number";
78+
format = "double";
79+
break;
80+
81+
case SpecialType.System_Double:
82+
schemaType = "number";
83+
format = "float";
84+
break;
85+
86+
case SpecialType.System_DateTime:
87+
schemaType = "string";
88+
format = "date-time";
89+
break;
90+
91+
case SpecialType.System_Boolean:
92+
schemaType = "boolean";
93+
break;
94+
95+
case SpecialType.None:
96+
switch (typeSymbol.Name)
97+
{
98+
case "DateOnly":
99+
schemaType = "string";
100+
format = "date";
101+
break;
102+
103+
default:
104+
throw new NotImplementedException($"{typeSymbol.Name} is not implemented.");
105+
}
106+
break;
107+
108+
default:
109+
throw new NotImplementedException($"{typeSymbol.SpecialType} is not implemented.");
110+
}
111+
break;
112+
113+
case TypeKind.Class:
114+
switch (typeSymbol.SpecialType)
115+
{
116+
case SpecialType.System_String:
117+
schemaType = "string";
118+
break;
119+
120+
121+
case SpecialType.None:
122+
schemaType = "object";
123+
properties = typeSymbol.GetMembers()
124+
.OfType<IPropertySymbol>()
125+
.Select(static y => ToParameterData(
126+
typeSymbol: y.Type,
127+
name: y.Name,
128+
description: GetDescription(y),
129+
isRequired: true))
130+
.ToArray();
131+
break;
132+
133+
default:
134+
throw new NotImplementedException($"{typeSymbol.SpecialType} is not implemented.");
135+
}
136+
break;
137+
138+
case TypeKind.Interface when typeSymbol.MetadataName == "IReadOnlyCollection`1":
139+
schemaType = "array";
140+
arrayItem = (typeSymbol as INamedTypeSymbol)?.TypeArguments
141+
.Select(static y => ToParameterData(y))
142+
.FirstOrDefault();
143+
break;
144+
145+
case TypeKind.Array:
146+
schemaType = "array";
147+
arrayItem = ToParameterData((typeSymbol as IArrayTypeSymbol)?.ElementType!);
148+
break;
149+
150+
default:
151+
throw new NotImplementedException($"{typeSymbol.TypeKind} is not implemented.");
152+
}
153+
154+
return new OpenApiSchema(
155+
Name: !string.IsNullOrWhiteSpace(name)
156+
? name!
157+
: typeSymbol.Name,
158+
Description: !string.IsNullOrWhiteSpace(description)
159+
? description!
160+
: GetDescription(typeSymbol),
161+
Type: typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
162+
DefaultValue: GetDefaultValue(typeSymbol),
163+
SchemaType: schemaType,
164+
Format: format,
165+
Properties: properties,
166+
ArrayItem: arrayItem != null ? [arrayItem.Value] : Array.Empty<OpenApiSchema>(),
167+
EnumValues: typeSymbol.TypeKind == TypeKind.Enum
168+
? typeSymbol
169+
.GetMembers()
170+
.OfType<IFieldSymbol>()
171+
.Select(static x => x.Name.ToLowerInvariant())
172+
.ToArray()
173+
: [],
174+
IsNullable: IsNullable(typeSymbol),
175+
IsRequired: isRequired);
176+
}
177+
178+
private static bool IsNullable(ITypeSymbol typeSymbol)
179+
{
180+
if (typeSymbol.TypeKind == TypeKind.Enum)
181+
{
182+
return false;
183+
}
184+
if (typeSymbol.TypeKind == TypeKind.Structure)
185+
{
186+
return false;
187+
}
188+
189+
return typeSymbol.SpecialType switch
190+
{
191+
SpecialType.System_String => false,
192+
_ => true,
193+
};
194+
}
195+
196+
private static string GetDefaultValue(ITypeSymbol typeSymbol)
197+
{
198+
switch (typeSymbol.SpecialType)
199+
{
200+
case SpecialType.System_String:
201+
return "string.Empty";
202+
203+
default:
204+
return string.Empty;
205+
}
206+
}
207+
208+
private static string GetDescription(ISymbol symbol)
209+
{
210+
return symbol.GetAttributes()
211+
.FirstOrDefault(static x => x.AttributeClass?.Name == nameof(DescriptionAttribute))?
212+
.ConstructorArguments.First().Value?.ToString() ?? string.Empty;
213+
}
214+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace H.Generators;
2+
3+
public readonly record struct InterfaceData(
4+
string Namespace,
5+
string Name,
6+
IReadOnlyCollection<MethodData> Methods);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using Anthropic.Generators.Core;
2+
3+
namespace H.Generators;
4+
5+
public readonly record struct MethodData(
6+
string Name,
7+
string Description,
8+
bool IsAsync,
9+
bool IsVoid,
10+
OpenApiSchema Parameters);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace Anthropic.Generators.Core;
2+
3+
public readonly record struct OpenApiSchema(
4+
string Name,
5+
string Description,
6+
string Type,
7+
string SchemaType,
8+
string? Format,
9+
IReadOnlyCollection<string> EnumValues,
10+
IReadOnlyCollection<OpenApiSchema> Properties,
11+
IReadOnlyCollection<OpenApiSchema> ArrayItem,
12+
bool IsRequired,
13+
bool IsNullable,
14+
string DefaultValue);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
<IsPackable>false</IsPackable>
6+
<GenerateDocumentationFile>false</GenerateDocumentationFile>
7+
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
8+
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
9+
<NoWarn>$(NoWarn);CA1014;CA1031;CA1308</NoWarn>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="IsExternalInit" Version="1.0.3">
14+
<PrivateAssets>all</PrivateAssets>
15+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
16+
</PackageReference>
17+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.1" PrivateAssets="all" />
18+
<PackageReference Include="H.Generators.Extensions" Version="1.22.0" PrivateAssets="all" />
19+
</ItemGroup>
20+
21+
<ItemGroup>
22+
<ProjectReference Include="..\Anthropic.Generators.Core\Anthropic.Generators.Core.csproj"
23+
PrivateAssets="all" />
24+
</ItemGroup>
25+
26+
</Project>

0 commit comments

Comments
 (0)