Skip to content

Commit 9ed0e7d

Browse files
committed
Introduce new Kiota generator API
1 parent 3411656 commit 9ed0e7d

1 file changed

Lines changed: 106 additions & 86 deletions

File tree

Lines changed: 106 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
using Riverside.CompilerPlatform.SourceGenerators;
2-
using System.Threading;
1+
using Riverside.CompilerPlatform.SourceGenerators;
2+
using Riverside.CompilerPlatform.Extensions;
3+
using Riverside.CompilerPlatform.Helpers;
34
using System;
4-
using System.Linq;
55
using System.Collections.Immutable;
66
using System.IO;
7+
using System.Linq;
78
using System.Text;
8-
using Riverside.CompilerPlatform.Extensions;
9-
using Riverside.CompilerPlatform.Helpers;
9+
using System.Threading;
1010

1111
namespace Riverside.CompilerPlatform.Features.Swagger;
1212

@@ -41,78 +41,123 @@ public partial class KiotaGenerator : IncrementalGenerator
4141
/// <inheritdoc/>
4242
protected override void OnBeforeGeneration(GeneratorContext context, CancellationToken cancellationToken)
4343
{
44-
var optionsProvider = context.AnalyzerConfigOptions.GlobalOptions;
44+
var options = context.AnalyzerConfigOptions.GlobalOptions;
4545

46-
// OpenAPI specs
4746
var specs = context.AdditionalTexts
4847
.Where(at => at.Path.EndsWith(".yaml", StringComparison.OrdinalIgnoreCase)
4948
|| at.Path.EndsWith(".yml", StringComparison.OrdinalIgnoreCase)
5049
|| at.Path.EndsWith(".json", StringComparison.OrdinalIgnoreCase))
5150
.ToImmutableArray();
5251

53-
optionsProvider.TryGetValue(VersionProperty, out var version);
54-
optionsProvider.TryGetValue(OptionsProperty, out var cliOptions);
55-
optionsProvider.TryGetValue(LanguageProperty, out var language);
56-
optionsProvider.TryGetValue(AdditionalPropertiesProperty, out var additionalProps);
57-
58-
version ??= string.Empty;
59-
language ??= "csharp";
52+
if (specs.IsEmpty)
53+
return;
54+
55+
var version = options.GetString(VersionProperty);
56+
57+
// Kiota engine args
58+
var language = options.GetNullableEnum<KiotaEngine.GenerationLanguage>(LanguageProperty)
59+
?? KiotaEngine.GenerationLanguage.CSharp;
60+
var className = options.GetString(ClassNameProperty);
61+
var namespaceName = options.GetString(NamespaceNameProperty);
62+
var typeAccessModifier = options.GetNullableEnum<KiotaEngine.Accessibility>(TypeAccessModifierProperty);
63+
var logLevel = options.GetNullableEnum<KiotaEngine.ConsoleLogLevel>(LogLevelProperty);
64+
var backingStore = options.GetNullableBool(BackingStoreProperty);
65+
var excludeBackwardCompatible = options.GetNullableBool(ExcludeBackwardCompatibleProperty);
66+
var additionalData = options.GetNullableBool(AdditionalDataProperty);
67+
var serializers = options.GetPipeSeparatedArray(SerializerProperty);
68+
var deserializers = options.GetPipeSeparatedArray(DeserializerProperty);
69+
var cleanOutput = options.GetNullableBool(CleanOutputProperty);
70+
var structuredMimeTypes = options.GetPipeSeparatedArray(StructuredMimeTypesProperty);
71+
var includePaths = options.GetPipeSeparatedArray(IncludePathProperty);
72+
var excludePaths = options.GetPipeSeparatedArray(ExcludePathProperty);
73+
var disableValidationRules = options.GetPipeSeparatedEnumArray<KiotaEngine.ValidationRules>(DisableValidationRulesProperty);
74+
var clearCache = options.GetNullableBool(ClearCacheProperty);
75+
var disableSSLValidation = options.GetNullableBool(DisableSSLValidationProperty);
76+
77+
string toolExecutable;
78+
try
79+
{
80+
var (installed, installError) = NETCoreToolHelpers
81+
.EnsureToolAsync("Microsoft.OpenApi.Kiota", ToolDirectory, version)
82+
.GetAwaiter().GetResult();
6083

61-
var jarPath = EnsureToolInstallation(version, context);
84+
if (!installed)
85+
{
86+
CreateDiagnostic(
87+
"KG0000",
88+
"Kiota installation failed",
89+
installError ?? "Failed to install or locate the Kiota tool.").Report(context);
90+
return;
91+
}
6292

63-
if (string.IsNullOrWhiteSpace(jarPath))
93+
toolExecutable = NETCoreToolHelpers.GetExecutablePath(ToolDirectory, "kiota");
94+
}
95+
catch (Exception ex)
6496
{
65-
IncrementalGenerator.CreateDiagnostic(
66-
"RS0000",
67-
"JAR not downloaded",
68-
"An error occured whilst downloading the JAR executable to generate the OpenAPI spec")
69-
.Report(context);
97+
CreateDiagnostic("KG0000", "Kiota installation failed", ex.Message).Report(context);
98+
return;
7099
}
71100

72101
foreach (var spec in specs)
73102
{
74-
try
75-
{
76-
var specNamespace = SanitizationHelpers.Sanitize(Path.GetFileNameWithoutExtension(Path.GetFileName(spec.Path)));
103+
cancellationToken.ThrowIfCancellationRequested();
77104

78-
var specPath = spec.Path;
79-
if (!File.Exists(specPath))
80-
continue;
105+
var specPath = spec.Path;
106+
if (!File.Exists(specPath))
107+
continue;
81108

82-
var specFileName = Path.GetFileNameWithoutExtension(specPath);
109+
var specFileName = Path.GetFileNameWithoutExtension(specPath);
110+
var effectiveNamespace = namespaceName ?? SanitizationHelpers.Sanitize(specFileName);
83111

84-
var tempOut = Path.Combine(Path.GetTempPath(), "Roslyn", "Advanced Compiler Services for .NET", Guid.NewGuid().ToString("N"));
85-
Directory.CreateDirectory(tempOut);
112+
var tempOut = DirectoryHelpers.CreateTemporary(
113+
Path.Combine(Path.GetTempPath(), "Roslyn", "Advanced Compiler Services for .NET"));
86114

87-
if (!string.IsNullOrWhiteSpace(cliOptions))
88-
{
89-
argsBuilder.Append(" ");
90-
argsBuilder.Append(cliOptions);
91-
}
92-
93-
if (!string.IsNullOrWhiteSpace(additionalProps))
94-
{
95-
argsBuilder.Append(" --additional-properties=");
96-
argsBuilder.Append(SanitizationHelpers.EscapeArg(additionalProps!));
97-
}
98-
99-
var args = argsBuilder.ToString();
100-
101-
var runResult = ProcessHelpers.RunProcess("java", args, TimeSpan.FromMinutes(2)).GetAwaiter().GetResult();
115+
try
116+
{
117+
var engine = new KiotaEngine(
118+
d: specPath,
119+
a: null,
120+
o: tempOut,
121+
l: language,
122+
c: className,
123+
n: effectiveNamespace,
124+
tam: typeAccessModifier,
125+
ll: logLevel,
126+
b: backingStore,
127+
ebc: excludeBackwardCompatible,
128+
ad: additionalData,
129+
s: serializers,
130+
ds: deserializers,
131+
co: cleanOutput,
132+
m: structuredMimeTypes,
133+
i: includePaths,
134+
e: excludePaths,
135+
dvr: disableValidationRules,
136+
cc: clearCache,
137+
dsv: disableSSLValidation);
138+
139+
var runResult = ProcessHelpers
140+
.RunProcess(toolExecutable, engine.ToString(), TimeSpan.FromMinutes(2))
141+
.GetAwaiter().GetResult();
102142

103143
if (runResult.ExitCode != 0)
104144
{
105-
CreateDiagnostic("RS0000", "OpenAPI generator failed", $"OpenAPI generator failed for spec '{spec.Path}' with exit code {runResult.ExitCode}: {runResult.StandardError.ReplaceLineEndings(" ")}").Report(context);
106-
TryDeleteDirectory(tempOut);
145+
CreateDiagnostic(
146+
"KG0001",
147+
"Kiota generation failed",
148+
$"Kiota failed for spec '{specPath}' with exit code {runResult.ExitCode}: {runResult.StandardError.ReplaceLineEndings(" ")}").Report(context);
149+
DirectoryHelpers.TryDelete(tempOut);
107150
continue;
108151
}
109152

110-
var srcDir = Path.Combine(tempOut, "src", specNamespace);
111-
var csFiles = Directory.EnumerateFiles(srcDir, "*.cs", SearchOption.AllDirectories).ToArray();
153+
var csFiles = Directory.EnumerateFiles(tempOut, "*.cs", SearchOption.AllDirectories).ToArray();
112154
if (csFiles.Length == 0)
113155
{
114-
CreateDiagnostic("RS0000", "No C# files generated", $"OpenAPI generator produced no C# files for spec '{spec.Path}'").Report(context);
115-
TryDeleteDirectory(tempOut);
156+
CreateDiagnostic(
157+
"KG0002",
158+
"No C# files generated",
159+
$"Kiota produced no C# files for spec '{specPath}'").Report(context);
160+
DirectoryHelpers.TryDelete(tempOut);
116161
continue;
117162
}
118163

@@ -122,52 +167,27 @@ protected override void OnBeforeGeneration(GeneratorContext context, Cancellatio
122167
{
123168
var content = File.ReadAllText(cs, Encoding.UTF8);
124169
var rel = Path.GetRelativePath(tempOut, cs)
125-
.Replace(Path.DirectorySeparatorChar, '_')
126-
.Replace(Path.AltDirectorySeparatorChar, '_');
127-
128-
var hintName = $"{SanitizationHelpers.Sanitize(specFileName)}_{SanitizationHelpers.Sanitize(rel)}";
170+
.Replace(Path.DirectorySeparatorChar, '.')
171+
.Replace(Path.AltDirectorySeparatorChar, '.');
172+
var hintName = $"{SanitizationHelpers.Sanitize(engine.NamespaceName!)}.{SanitizationHelpers.Sanitize(rel)}";
129173
AddSource(hintName, content);
130174
}
131175
catch (Exception ex)
132176
{
133-
CreateDiagnostic("RS0000", "Failed to add generated file", $"Failed to add generated file '{cs}': {ex.Message}").Report(context);
177+
CreateDiagnostic(
178+
"KG0003",
179+
"Failed to add generated file",
180+
$"Failed to add '{cs}': {ex.Message}").Report(context);
134181
}
135182
}
136183

137-
TryDeleteDirectory(tempOut);
138-
139-
AddSource($"{SanitizationHelpers.Sanitize(specFileName)}_AnyOf", AnyOf_Polyfill(specNamespace + ".Model"));
184+
//DirectoryHelpers.TryDelete(tempOut);
140185
}
141186
catch (Exception ex)
142187
{
143-
CreateDiagnostic("RS9999", "OpenAPI generator exception", ex.ToString());
188+
CreateDiagnostic("KG9999", "Kiota generator exception", ex.ToString()).Report(context);
189+
DirectoryHelpers.TryDelete(tempOut);
144190
}
145191
}
146192
}
147-
148-
private static string? EnsureToolInstallation(string version, GeneratorContext context)
149-
{
150-
try
151-
{
152-
var baseDir = Path.Combine(Path.GetTempPath(), "Roslyn", "Advanced Compiler Services for .NET", "KiotaGenerator");
153-
Directory.CreateDirectory(baseDir);
154-
155-
var jarPath = Path.Combine(baseDir, $"openapi-generator-cli-{version}.jar");
156-
if (File.Exists(jarPath))
157-
return jarPath;
158-
159-
return jarPath;
160-
}
161-
catch (Exception ex)
162-
{
163-
CreateDiagnostic("RS0000", $"Failed to download OpenAPI generator JAR", $"Could not download version {version}: {ex.Message}").Report(context);
164-
return null;
165-
}
166-
}
167-
168-
private static void TryDeleteDirectory(string path)
169-
{
170-
try { if (Directory.Exists(path)) Directory.Delete(path, true); }
171-
catch { }
172-
}
173193
}

0 commit comments

Comments
 (0)