From 01c9fe3ecfbacdca62148278e63bb9ed99bc5a04 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 15:53:20 +0000
Subject: [PATCH 01/20] Add missing parameter to Kiota engine constructor
---
.../KiotaEngine.cs | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.cs b/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.cs
index d384f22..d513be6 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.cs
+++ b/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.cs
@@ -1,4 +1,4 @@
-using System.Text;
+using System.Diagnostics.CodeAnalysis;
namespace Riverside.CompilerPlatform.Features.Swagger;
@@ -128,6 +128,7 @@ public partial class KiotaEngine
/// The target programming language for code generation.
/// The name of the root class to be generated. Can be null to use a default class name.
/// The access modifier to apply to generated types. Can be null to use the default accessibility.
+ /// The namespace for the generated client class. Can be null to use the default namespace.
/// The log level to use for diagnostic output during generation. Can be null to use the default log level.
/// Indicates whether to use a backing store for generated models. If null, the default behavior is used.
/// Indicates whether to exclude backward compatible code from the output. If null, the default behavior is used.
@@ -141,7 +142,8 @@ public partial class KiotaEngine
/// An array of validation rules to disable during generation. Can be null to enable all rules.
/// Indicates whether to clear the internal cache before generation. If null, the default behavior is used.
/// Indicates whether to disable SSL validation for network operations. If null, the default behavior is used.
- public KiotaEngine(string? d, string? a, string? o, GenerationLanguage l, string? c, Accessibility? tam, ConsoleLogLevel? ll, bool? b, bool? ebc, bool? ad, string[]? s, string[]? ds, bool? co, string[]? m, string[]? i, string[]? e, ValidationRules[]? dvr, bool? cc, bool? dsv)
+ [SetsRequiredMembers]
+ public KiotaEngine(string? d, string? a, string? o, GenerationLanguage l, string? c, Accessibility? tam, string? n, ConsoleLogLevel? ll, bool? b, bool? ebc, bool? ad, string[]? s, string[]? ds, bool? co, string[]? m, string[]? i, string[]? e, ValidationRules[]? dvr, bool? cc, bool? dsv)
{
Path = d;
Manifest = a;
@@ -149,6 +151,7 @@ public KiotaEngine(string? d, string? a, string? o, GenerationLanguage l, string
Language = l;
ClassName = c;
TypeAccessModifier = tam;
+ NamespaceName = n;
LogLevel = ll;
BackingStore = b;
ExcludeBackwardCompatible = ebc;
From 4dbd47b5926fa10c1faa3ca24d6f47274f14a237 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 16:45:32 +0000
Subject: [PATCH 02/20] Add .NET tool helpers
---
.../Helpers/NETCoreToolHelpers.cs | 74 +++++++++++++++++++
.../Helpers/ProcessHelpers.cs | 13 +++-
2 files changed, 85 insertions(+), 2 deletions(-)
create mode 100644 src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/NETCoreToolHelpers.cs
diff --git a/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/NETCoreToolHelpers.cs b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/NETCoreToolHelpers.cs
new file mode 100644
index 0000000..ea1c479
--- /dev/null
+++ b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/NETCoreToolHelpers.cs
@@ -0,0 +1,74 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+
+namespace Riverside.CompilerPlatform.Helpers;
+
+///
+/// Provides helpers for installing and locating .NET tools installed to a specific tool-path directory.
+///
+public static class NETCoreToolHelpers
+{
+ ///
+ /// Returns the full path to the tool executable expected in .
+ /// Appends .exe on Windows; uses the bare name on all other platforms.
+ ///
+ /// The directory the tool was installed into via --tool-path.
+ /// The tool executable name (e.g. kiota).
+ /// The full path including the platform-appropriate extension.
+ public static string GetExecutablePath(string toolDirectory, string toolName)
+ => Path.Combine(
+ toolDirectory,
+ Environment.OSVersion.Platform == PlatformID.Win32NT ? toolName + ".exe" : toolName);
+
+ ///
+ /// Ensures the specified .NET tool is available in .
+ ///
+ ///
+ ///
+ /// - If the executable already exists and no specific is requested, the tool is reused immediately.
+ /// - Otherwise dotnet tool install is attempted. If it fails because the tool is already installed, dotnet tool update is tried instead.
+ /// - Installation succeeds when the executable is present after the above steps.
+ ///
+ ///
+ /// The NuGet package ID of the tool (e.g. Riverside.JsonBinder.Console).
+ /// The directory to install the tool into, passed to --tool-path.
+ ///
+ /// A specific version to pin. Pass to install or keep the latest.
+ ///
+ /// Maximum wait time per install or update process. Defaults to 5 minutes.
+ ///
+ /// A tuple where Success is when the executable is available, and Error carries the captured stderr when installation fails.
+ ///
+ public static async Task<(bool Success, string? Error)> EnsureToolAsync(
+ string toolName,
+ string toolDirectory,
+ string? version = null,
+ TimeSpan? timeout = null)
+ {
+ var exe = GetExecutablePath(toolDirectory, toolName);
+ var effectiveTimeout = timeout ?? TimeSpan.FromMinutes(5);
+
+ Directory.CreateDirectory(toolDirectory);
+
+ if (File.Exists(exe) && string.IsNullOrWhiteSpace(version))
+ return (true, null);
+
+ var toolPathArg = $"--tool-path \"{toolDirectory}\"";
+ var versionArg = string.IsNullOrWhiteSpace(version) ? string.Empty : $" --version {version}";
+
+ var installResult = await ProcessHelpers.RunNETCoreCliAsync(
+ $"tool install {toolName} {toolPathArg}{versionArg}", effectiveTimeout);
+
+ if (installResult.ExitCode == 0)
+ return (true, null);
+
+ // install exits non-zero when the tool is already present; attempt an update instead
+ var updateResult = await ProcessHelpers.RunNETCoreCliAsync(
+ $"tool update {toolName} {toolPathArg}{versionArg}", effectiveTimeout);
+
+ return File.Exists(exe)
+ ? (true, null)
+ : (false, updateResult.StandardError);
+ }
+}
diff --git a/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/ProcessHelpers.cs b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/ProcessHelpers.cs
index 4132700..9bb2dd5 100644
--- a/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/ProcessHelpers.cs
+++ b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/ProcessHelpers.cs
@@ -49,8 +49,7 @@ public class ProcessOutput(int code, string stdout, string stderr)
/// A tuple containing the process exit code, the captured standard output, and the captured standard error.
/// If the process times out, the exit code is -1 and the standard error includes a timeout message.
///
- public static async Task
- RunProcess(string fileName, string arguments, TimeSpan timeout)
+ public static async Task RunProcess(string fileName, string arguments, TimeSpan timeout)
{
var psi = new ProcessStartInfo
{
@@ -82,4 +81,14 @@ public static async Task
return new(proc.ExitCode, outputSb.ToString(), errorSb.ToString());
}
+
+ ///
+ /// Runs a dotnet command asynchronously with the specified arguments and timeout,
+ /// capturing its exit code, standard output, and standard error.
+ ///
+ /// The arguments to pass after dotnet (e.g. tool install Riverside.JsonBinder.Console ...).
+ /// The maximum duration to wait before forcibly terminating the process.
+ /// A containing the exit code and captured streams.
+ public static Task RunNETCoreCliAsync(string arguments, TimeSpan timeout)
+ => RunProcess("dotnet", arguments, timeout);
}
From d461701a4428ddf6c25c1be2d277b40a1cbe44df Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 18:02:55 +0000
Subject: [PATCH 03/20] Fix bad sanitisation
---
.../KiotaEngine.Methods.cs | 35 ++++++++++---------
.../Helpers/SanitizationHelpers.cs | 1 -
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.Methods.cs b/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.Methods.cs
index cf50361..6031450 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.Methods.cs
+++ b/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.Methods.cs
@@ -1,4 +1,5 @@
-using System.Text;
+using Riverside.CompilerPlatform.Helpers;
+using System.Text;
namespace Riverside.CompilerPlatform.Features.Swagger;
@@ -13,19 +14,19 @@ partial class KiotaEngine
///
public override string ToString()
{
- var command = new StringBuilder().Append("kiota generate");
+ var command = new StringBuilder().Append("generate");
if (!string.IsNullOrWhiteSpace(Path))
{
- command.Append($" --openapi {Path}");
+ command.Append($" --openapi {SanitizationHelpers.EscapeArg(Path!)}");
}
if (!string.IsNullOrWhiteSpace(Manifest))
{
- command.Append($" --manifest {Manifest}");
+ command.Append($" --manifest {SanitizationHelpers.EscapeArg(Manifest!)}");
}
if (!string.IsNullOrWhiteSpace(Output))
{
- command.Append($" --output {Output}");
+ command.Append($" --output {SanitizationHelpers.EscapeArg(Output!)}");
}
command.Append($" --language {Language}");
if (!string.IsNullOrWhiteSpace(ClassName))
@@ -56,68 +57,68 @@ public override string ToString()
{
command.Append($" --additional-data {AdditionalData}");
}
- if (Serializer is not null)
+ if (Serializer is not null && Serializer.Length > 0)
{
var serializers = new StringBuilder().Append(" --serializer ");
foreach (var serializer in Serializer)
{
serializers.Append(serializer + "|");
}
- serializers.Remove(serializers.Length, 1); // remove final '|' char
+ serializers.Remove(serializers.Length - 1, 1); // remove final '|' char
command.Append(serializers.ToString());
}
- if (Deserializer is not null)
+ if (Deserializer is not null && Deserializer.Length > 0)
{
var deserializers = new StringBuilder().Append(" --deserializer ");
foreach (var deserializer in Deserializer)
{
deserializers.Append(deserializer + "|");
}
- deserializers.Remove(deserializers.Length, 1); // remove final '|' char
+ deserializers.Remove(deserializers.Length - 1, 1); // remove final '|' char
command.Append(deserializers.ToString());
}
if (CleanOutput is not null)
{
command.Append($" --clean-output {CleanOutput}");
}
- if (StructuredMimeTypes is not null)
+ if (StructuredMimeTypes is not null && StructuredMimeTypes.Length > 0)
{
var structuredMimeTypes = new StringBuilder().Append(" --structured-mime-types ");
foreach (var structuredMimeType in StructuredMimeTypes)
{
structuredMimeTypes.Append(structuredMimeType + "|");
}
- structuredMimeTypes.Remove(structuredMimeTypes.Length, 1); // remove final '|' char
+ structuredMimeTypes.Remove(structuredMimeTypes.Length - 1, 1); // remove final '|' char
command.Append(structuredMimeTypes.ToString());
}
- if (IncludePath is not null)
+ if (IncludePath is not null && IncludePath.Length > 0)
{
var includePaths = new StringBuilder().Append(" --include-path ");
foreach (var includePath in IncludePath)
{
includePaths.Append(includePath + "|");
}
- includePaths.Remove(includePaths.Length, 1); // remove final '|' char
+ includePaths.Remove(includePaths.Length - 1, 1); // remove final '|' char
command.Append(includePaths.ToString());
}
- if (ExcludePath is not null)
+ if (ExcludePath is not null && ExcludePath.Length > 0)
{
var excludePaths = new StringBuilder().Append(" --exclude-path ");
foreach (var excludePath in ExcludePath)
{
excludePaths.Append(excludePath + "|");
}
- excludePaths.Remove(excludePaths.Length, 1); // remove final '|' char
+ excludePaths.Remove(excludePaths.Length - 1, 1); // remove final '|' char
command.Append(excludePaths.ToString());
}
- if (DisableValidationRules is not null)
+ if (DisableValidationRules is not null && DisableValidationRules.Length > 0)
{
var disableValidationRules = new StringBuilder().Append(" --disable-validation-rules ");
foreach (var disableValidationRule in DisableValidationRules)
{
disableValidationRules.Append(disableValidationRule + "|");
}
- disableValidationRules.Remove(disableValidationRules.Length, 1); // remove final '|' char
+ disableValidationRules.Remove(disableValidationRules.Length - 1, 1); // remove final '|' char
command.Append(disableValidationRules.ToString());
}
if (ClearCache is not null)
diff --git a/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/SanitizationHelpers.cs b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/SanitizationHelpers.cs
index 74aea88..70e1823 100644
--- a/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/SanitizationHelpers.cs
+++ b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/SanitizationHelpers.cs
@@ -36,7 +36,6 @@ public static string Sanitize(string s)
/// The argument to escape.
/// A string containing the escaped argument, suitable for use in a command-line context.
/// Thrown if is null.
- [NotMyCode] // from the internet
public static string EscapeArg(string arg)
{
if (arg == null)
From d571102a57bfb1a4830abd74bb48a2e98d007896 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 18:03:28 +0000
Subject: [PATCH 04/20] Use `[Diagnostic].Report()` method in
`IncrementalGenerator` API
---
.../IncrementalGenerator.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/roslyn/Riverside.CompilerPlatform.SourceGenerators/IncrementalGenerator.cs b/src/roslyn/Riverside.CompilerPlatform.SourceGenerators/IncrementalGenerator.cs
index 0a46157..8feb11b 100644
--- a/src/roslyn/Riverside.CompilerPlatform.SourceGenerators/IncrementalGenerator.cs
+++ b/src/roslyn/Riverside.CompilerPlatform.SourceGenerators/IncrementalGenerator.cs
@@ -1,4 +1,5 @@
-using System;
+using Riverside.CompilerPlatform.Extensions;
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -249,12 +250,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
if (!SuppressDiagnostics)
{
// Report exceptions that occur during generation
- sourceProductionContext.ReportDiagnostic(
CreateDiagnostic(
$"RS9999",
"Source Generation Error",
$"An error occurred during source generation: {ex.Message}",
- DiagnosticSeverity.Error));
+ DiagnosticSeverity.Error).Report(Context);
}
}
});
From b5a6121d9d3eb0dd63cd3aed8543bd29dc18481e Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 18:04:40 +0000
Subject: [PATCH 05/20] Add extensions to Roslyn primitive analyser config
options & dir helper
---
.../AnalyzerConfigOptionsExtensions.cs | 92 +++++++++++++++++++
.../Helpers/DirectoryHelpers.cs | 33 +++++++
2 files changed, 125 insertions(+)
create mode 100644 src/roslyn/Riverside.CompilerPlatform.Extensions/Extensions/AnalyzerConfigOptionsExtensions.cs
create mode 100644 src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/DirectoryHelpers.cs
diff --git a/src/roslyn/Riverside.CompilerPlatform.Extensions/Extensions/AnalyzerConfigOptionsExtensions.cs b/src/roslyn/Riverside.CompilerPlatform.Extensions/Extensions/AnalyzerConfigOptionsExtensions.cs
new file mode 100644
index 0000000..858f9d4
--- /dev/null
+++ b/src/roslyn/Riverside.CompilerPlatform.Extensions/Extensions/AnalyzerConfigOptionsExtensions.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Linq;
+
+namespace Riverside.CompilerPlatform.Extensions;
+
+///
+/// Provides extension methods for reading typed values from .
+///
+public static class AnalyzerConfigOptionsExtensions
+{
+ ///
+ /// Returns the string value for , or if the key is absent or whitespace.
+ ///
+ /// The analyser config options to read from.
+ /// The property key, typically prefixed with build_property..
+ /// The trimmed string value, or .
+ public static string? GetString(this AnalyzerConfigOptions options, string key)
+ {
+ options.TryGetValue(key, out var value);
+ return string.IsNullOrWhiteSpace(value) ? null : value;
+ }
+
+ ///
+ /// Returns a nullable for .
+ /// Returns when the key is absent, empty, or not a valid boolean string.
+ ///
+ /// The analyzer config options to read from.
+ /// The property key.
+ /// The parsed boolean, or .
+ public static bool? GetNullableBool(this AnalyzerConfigOptions options, string key)
+ {
+ var value = options.GetString(key);
+ return value is not null && bool.TryParse(value, out var result) ? result : null;
+ }
+
+ ///
+ /// Returns a nullable for , parsed case-insensitively.
+ /// Returns when the key is absent, empty, or does not map to a valid enum member.
+ ///
+ /// The enum type to parse into.
+ /// The analyser config options to read from.
+ /// The property key.
+ /// The parsed enum value, or .
+ public static TEnum? GetNullableEnum(this AnalyzerConfigOptions options, string key)
+ where TEnum : struct, Enum
+ {
+ var value = options.GetString(key);
+ return value is not null && Enum.TryParse(value, ignoreCase: true, out var result) ? result : null;
+ }
+
+ ///
+ /// Returns a [] by splitting 's value on the | character.
+ /// Empty or whitespace-only segments are discarded.
+ /// Returns when the key is absent, empty, or yields no usable segments.
+ ///
+ /// The analyser config options to read from.
+ /// The property key.
+ /// A non-empty trimmed array of segments, or .
+ public static string[]? GetPipeSeparatedArray(this AnalyzerConfigOptions options, string key)
+ {
+ var value = options.GetString(key);
+ if (value is null)
+ return null;
+ var parts = value.Split('|')
+ .Select(p => p.Trim())
+ .Where(p => p.Length > 0)
+ .ToArray();
+ return parts.Length > 0 ? parts : null;
+ }
+
+ ///
+ /// Returns a [] by splitting 's value on | and parsing each segment case-insensitively.
+ /// Segments that do not match a valid enum member are silently skipped.
+ ///
+ /// The enum type to parse each segment into.
+ /// The analyser config options to read from.
+ /// The property key.
+ /// A non-empty array of parsed enum values, or when the is absent, empty, or yields no valid members.
+ public static TEnum[]? GetPipeSeparatedEnumArray(this AnalyzerConfigOptions options, string key)
+ where TEnum : struct, Enum
+ {
+ var raw = options.GetPipeSeparatedArray(key);
+ if (raw is null)
+ return null;
+ var parsed = raw
+ .Select(s => (ok: Enum.TryParse(s, ignoreCase: true, out var v), val: v))
+ .Where(t => t.ok)
+ .Select(t => t.val)
+ .ToArray();
+ return parsed.Length > 0 ? parsed : null;
+ }
+}
diff --git a/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/DirectoryHelpers.cs b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/DirectoryHelpers.cs
new file mode 100644
index 0000000..691d6b4
--- /dev/null
+++ b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/DirectoryHelpers.cs
@@ -0,0 +1,33 @@
+using System;
+using System.IO;
+
+namespace Riverside.CompilerPlatform.Helpers;
+
+///
+/// Provides utility methods for common directory operations.
+///
+public static class DirectoryHelpers
+{
+ ///
+ /// Deletes and all of its contents recursively, suppressing any exception that occurs.
+ ///
+ /// The directory to delete.
+ public static void TryDelete(string path)
+ {
+ try { if (Directory.Exists(path)) Directory.Delete(path, recursive: true); }
+ catch { }
+ }
+
+ ///
+ /// Creates a uniquely named subdirectory under and returns its full path.
+ /// The subdirectory name is a compact with no formatting characters.
+ ///
+ /// The parent directory. Created if it does not already exist.
+ /// The full path of the newly created temporary directory.
+ public static string CreateTemporary(string basePath)
+ {
+ var path = Path.Combine(basePath, Guid.NewGuid().ToString("N"));
+ Directory.CreateDirectory(path);
+ return path;
+ }
+}
From 9aafe7e7d26382691e6ca0d2e8d566213f702c21 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 18:05:02 +0000
Subject: [PATCH 06/20] Fix source generator runtime exception
---
.../{api-1.json => Lapse.json} | 0
...ide.CompilerPlatform.Features.Tests.csproj | 19 ++++++++++---------
2 files changed, 10 insertions(+), 9 deletions(-)
rename tests/Riverside.CompilerPlatform.Features.Tests/{api-1.json => Lapse.json} (100%)
diff --git a/tests/Riverside.CompilerPlatform.Features.Tests/api-1.json b/tests/Riverside.CompilerPlatform.Features.Tests/Lapse.json
similarity index 100%
rename from tests/Riverside.CompilerPlatform.Features.Tests/api-1.json
rename to tests/Riverside.CompilerPlatform.Features.Tests/Lapse.json
diff --git a/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj b/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
index dba8912..54119ac 100644
--- a/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
+++ b/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
@@ -5,23 +5,24 @@
netstandard2.0
+
+
+
+
-
-
+
+
+
-
-
-
-
-
-
+
+
-
+
From 3411656e12c73c16bdf6f3b0ce24b8ea00f5c3c5 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 18:07:28 +0000
Subject: [PATCH 07/20] Add new Kiota options to Swagger source generator
editorconfig options
---
.../KiotaGenerator.cs | 25 ++++++++++++++++---
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs b/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs
index f4582d6..615d089 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs
+++ b/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs
@@ -1,4 +1,4 @@
-using Riverside.CompilerPlatform.SourceGenerators;
+using Riverside.CompilerPlatform.SourceGenerators;
using System.Threading;
using System;
using System.Linq;
@@ -16,10 +16,27 @@ namespace Riverside.CompilerPlatform.Features.Swagger;
[Generator]
public partial class KiotaGenerator : IncrementalGenerator
{
- private const string VersionProperty = "build_property.KiotaGenerator_Version";
- private const string OptionsProperty = "build_property.KiotaGenerator_Options";
+ private const string VersionProperty = "build_property.Kiota_Version";
private const string LanguageProperty = "build_property.KiotaGenerator_Language";
- private const string AdditionalPropertiesProperty = "build_property.KiotaGenerator_AdditionalProperties";
+ private const string ClassNameProperty = "build_property.KiotaGenerator_ClassName";
+ private const string NamespaceNameProperty = "build_property.KiotaGenerator_NamespaceName";
+ private const string TypeAccessModifierProperty = "build_property.KiotaGenerator_TypeAccessModifier";
+ private const string LogLevelProperty = "build_property.KiotaGenerator_LogLevel";
+ private const string BackingStoreProperty = "build_property.KiotaGenerator_BackingStore";
+ private const string ExcludeBackwardCompatibleProperty = "build_property.KiotaGenerator_ExcludeBackwardCompatible";
+ private const string AdditionalDataProperty = "build_property.KiotaGenerator_AdditionalData";
+ private const string SerializerProperty = "build_property.KiotaGenerator_Serializer";
+ private const string DeserializerProperty = "build_property.KiotaGenerator_Deserializer";
+ private const string CleanOutputProperty = "build_property.KiotaGenerator_CleanOutput";
+ private const string StructuredMimeTypesProperty = "build_property.KiotaGenerator_StructuredMimeTypes";
+ private const string IncludePathProperty = "build_property.KiotaGenerator_IncludePath";
+ private const string ExcludePathProperty = "build_property.KiotaGenerator_ExcludePath";
+ private const string DisableValidationRulesProperty = "build_property.KiotaGenerator_DisableValidationRules";
+ private const string ClearCacheProperty = "build_property.KiotaGenerator_ClearCache";
+ private const string DisableSSLValidationProperty = "build_property.KiotaGenerator_DisableSSLValidation";
+
+ private static readonly string ToolDirectory = Path.Combine(
+ Path.GetTempPath(), "Roslyn", "Advanced Compiler Services for .NET", "KiotaGenerator");
///
protected override void OnBeforeGeneration(GeneratorContext context, CancellationToken cancellationToken)
From 9ed0e7dde65ec21c8cd4d9c74e4f35ec577ca153 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 18:08:25 +0000
Subject: [PATCH 08/20] Introduce new Kiota generator API
---
.../KiotaGenerator.cs | 192 ++++++++++--------
1 file changed, 106 insertions(+), 86 deletions(-)
diff --git a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs b/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs
index 615d089..f681249 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs
+++ b/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs
@@ -1,12 +1,12 @@
-using Riverside.CompilerPlatform.SourceGenerators;
-using System.Threading;
+using Riverside.CompilerPlatform.SourceGenerators;
+using Riverside.CompilerPlatform.Extensions;
+using Riverside.CompilerPlatform.Helpers;
using System;
-using System.Linq;
using System.Collections.Immutable;
using System.IO;
+using System.Linq;
using System.Text;
-using Riverside.CompilerPlatform.Extensions;
-using Riverside.CompilerPlatform.Helpers;
+using System.Threading;
namespace Riverside.CompilerPlatform.Features.Swagger;
@@ -41,78 +41,123 @@ public partial class KiotaGenerator : IncrementalGenerator
///
protected override void OnBeforeGeneration(GeneratorContext context, CancellationToken cancellationToken)
{
- var optionsProvider = context.AnalyzerConfigOptions.GlobalOptions;
+ var options = context.AnalyzerConfigOptions.GlobalOptions;
- // OpenAPI specs
var specs = context.AdditionalTexts
.Where(at => at.Path.EndsWith(".yaml", StringComparison.OrdinalIgnoreCase)
|| at.Path.EndsWith(".yml", StringComparison.OrdinalIgnoreCase)
|| at.Path.EndsWith(".json", StringComparison.OrdinalIgnoreCase))
.ToImmutableArray();
- optionsProvider.TryGetValue(VersionProperty, out var version);
- optionsProvider.TryGetValue(OptionsProperty, out var cliOptions);
- optionsProvider.TryGetValue(LanguageProperty, out var language);
- optionsProvider.TryGetValue(AdditionalPropertiesProperty, out var additionalProps);
-
- version ??= string.Empty;
- language ??= "csharp";
+ if (specs.IsEmpty)
+ return;
+
+ var version = options.GetString(VersionProperty);
+
+ // Kiota engine args
+ var language = options.GetNullableEnum(LanguageProperty)
+ ?? KiotaEngine.GenerationLanguage.CSharp;
+ var className = options.GetString(ClassNameProperty);
+ var namespaceName = options.GetString(NamespaceNameProperty);
+ var typeAccessModifier = options.GetNullableEnum(TypeAccessModifierProperty);
+ var logLevel = options.GetNullableEnum(LogLevelProperty);
+ var backingStore = options.GetNullableBool(BackingStoreProperty);
+ var excludeBackwardCompatible = options.GetNullableBool(ExcludeBackwardCompatibleProperty);
+ var additionalData = options.GetNullableBool(AdditionalDataProperty);
+ var serializers = options.GetPipeSeparatedArray(SerializerProperty);
+ var deserializers = options.GetPipeSeparatedArray(DeserializerProperty);
+ var cleanOutput = options.GetNullableBool(CleanOutputProperty);
+ var structuredMimeTypes = options.GetPipeSeparatedArray(StructuredMimeTypesProperty);
+ var includePaths = options.GetPipeSeparatedArray(IncludePathProperty);
+ var excludePaths = options.GetPipeSeparatedArray(ExcludePathProperty);
+ var disableValidationRules = options.GetPipeSeparatedEnumArray(DisableValidationRulesProperty);
+ var clearCache = options.GetNullableBool(ClearCacheProperty);
+ var disableSSLValidation = options.GetNullableBool(DisableSSLValidationProperty);
+
+ string toolExecutable;
+ try
+ {
+ var (installed, installError) = NETCoreToolHelpers
+ .EnsureToolAsync("Microsoft.OpenApi.Kiota", ToolDirectory, version)
+ .GetAwaiter().GetResult();
- var jarPath = EnsureToolInstallation(version, context);
+ if (!installed)
+ {
+ CreateDiagnostic(
+ "KG0000",
+ "Kiota installation failed",
+ installError ?? "Failed to install or locate the Kiota tool.").Report(context);
+ return;
+ }
- if (string.IsNullOrWhiteSpace(jarPath))
+ toolExecutable = NETCoreToolHelpers.GetExecutablePath(ToolDirectory, "kiota");
+ }
+ catch (Exception ex)
{
- IncrementalGenerator.CreateDiagnostic(
- "RS0000",
- "JAR not downloaded",
- "An error occured whilst downloading the JAR executable to generate the OpenAPI spec")
- .Report(context);
+ CreateDiagnostic("KG0000", "Kiota installation failed", ex.Message).Report(context);
+ return;
}
foreach (var spec in specs)
{
- try
- {
- var specNamespace = SanitizationHelpers.Sanitize(Path.GetFileNameWithoutExtension(Path.GetFileName(spec.Path)));
+ cancellationToken.ThrowIfCancellationRequested();
- var specPath = spec.Path;
- if (!File.Exists(specPath))
- continue;
+ var specPath = spec.Path;
+ if (!File.Exists(specPath))
+ continue;
- var specFileName = Path.GetFileNameWithoutExtension(specPath);
+ var specFileName = Path.GetFileNameWithoutExtension(specPath);
+ var effectiveNamespace = namespaceName ?? SanitizationHelpers.Sanitize(specFileName);
- var tempOut = Path.Combine(Path.GetTempPath(), "Roslyn", "Advanced Compiler Services for .NET", Guid.NewGuid().ToString("N"));
- Directory.CreateDirectory(tempOut);
+ var tempOut = DirectoryHelpers.CreateTemporary(
+ Path.Combine(Path.GetTempPath(), "Roslyn", "Advanced Compiler Services for .NET"));
- if (!string.IsNullOrWhiteSpace(cliOptions))
- {
- argsBuilder.Append(" ");
- argsBuilder.Append(cliOptions);
- }
-
- if (!string.IsNullOrWhiteSpace(additionalProps))
- {
- argsBuilder.Append(" --additional-properties=");
- argsBuilder.Append(SanitizationHelpers.EscapeArg(additionalProps!));
- }
-
- var args = argsBuilder.ToString();
-
- var runResult = ProcessHelpers.RunProcess("java", args, TimeSpan.FromMinutes(2)).GetAwaiter().GetResult();
+ try
+ {
+ var engine = new KiotaEngine(
+ d: specPath,
+ a: null,
+ o: tempOut,
+ l: language,
+ c: className,
+ n: effectiveNamespace,
+ tam: typeAccessModifier,
+ ll: logLevel,
+ b: backingStore,
+ ebc: excludeBackwardCompatible,
+ ad: additionalData,
+ s: serializers,
+ ds: deserializers,
+ co: cleanOutput,
+ m: structuredMimeTypes,
+ i: includePaths,
+ e: excludePaths,
+ dvr: disableValidationRules,
+ cc: clearCache,
+ dsv: disableSSLValidation);
+
+ var runResult = ProcessHelpers
+ .RunProcess(toolExecutable, engine.ToString(), TimeSpan.FromMinutes(2))
+ .GetAwaiter().GetResult();
if (runResult.ExitCode != 0)
{
- CreateDiagnostic("RS0000", "OpenAPI generator failed", $"OpenAPI generator failed for spec '{spec.Path}' with exit code {runResult.ExitCode}: {runResult.StandardError.ReplaceLineEndings(" ")}").Report(context);
- TryDeleteDirectory(tempOut);
+ CreateDiagnostic(
+ "KG0001",
+ "Kiota generation failed",
+ $"Kiota failed for spec '{specPath}' with exit code {runResult.ExitCode}: {runResult.StandardError.ReplaceLineEndings(" ")}").Report(context);
+ DirectoryHelpers.TryDelete(tempOut);
continue;
}
- var srcDir = Path.Combine(tempOut, "src", specNamespace);
- var csFiles = Directory.EnumerateFiles(srcDir, "*.cs", SearchOption.AllDirectories).ToArray();
+ var csFiles = Directory.EnumerateFiles(tempOut, "*.cs", SearchOption.AllDirectories).ToArray();
if (csFiles.Length == 0)
{
- CreateDiagnostic("RS0000", "No C# files generated", $"OpenAPI generator produced no C# files for spec '{spec.Path}'").Report(context);
- TryDeleteDirectory(tempOut);
+ CreateDiagnostic(
+ "KG0002",
+ "No C# files generated",
+ $"Kiota produced no C# files for spec '{specPath}'").Report(context);
+ DirectoryHelpers.TryDelete(tempOut);
continue;
}
@@ -122,52 +167,27 @@ protected override void OnBeforeGeneration(GeneratorContext context, Cancellatio
{
var content = File.ReadAllText(cs, Encoding.UTF8);
var rel = Path.GetRelativePath(tempOut, cs)
- .Replace(Path.DirectorySeparatorChar, '_')
- .Replace(Path.AltDirectorySeparatorChar, '_');
-
- var hintName = $"{SanitizationHelpers.Sanitize(specFileName)}_{SanitizationHelpers.Sanitize(rel)}";
+ .Replace(Path.DirectorySeparatorChar, '.')
+ .Replace(Path.AltDirectorySeparatorChar, '.');
+ var hintName = $"{SanitizationHelpers.Sanitize(engine.NamespaceName!)}.{SanitizationHelpers.Sanitize(rel)}";
AddSource(hintName, content);
}
catch (Exception ex)
{
- CreateDiagnostic("RS0000", "Failed to add generated file", $"Failed to add generated file '{cs}': {ex.Message}").Report(context);
+ CreateDiagnostic(
+ "KG0003",
+ "Failed to add generated file",
+ $"Failed to add '{cs}': {ex.Message}").Report(context);
}
}
- TryDeleteDirectory(tempOut);
-
- AddSource($"{SanitizationHelpers.Sanitize(specFileName)}_AnyOf", AnyOf_Polyfill(specNamespace + ".Model"));
+ //DirectoryHelpers.TryDelete(tempOut);
}
catch (Exception ex)
{
- CreateDiagnostic("RS9999", "OpenAPI generator exception", ex.ToString());
+ CreateDiagnostic("KG9999", "Kiota generator exception", ex.ToString()).Report(context);
+ DirectoryHelpers.TryDelete(tempOut);
}
}
}
-
- private static string? EnsureToolInstallation(string version, GeneratorContext context)
- {
- try
- {
- var baseDir = Path.Combine(Path.GetTempPath(), "Roslyn", "Advanced Compiler Services for .NET", "KiotaGenerator");
- Directory.CreateDirectory(baseDir);
-
- var jarPath = Path.Combine(baseDir, $"openapi-generator-cli-{version}.jar");
- if (File.Exists(jarPath))
- return jarPath;
-
- return jarPath;
- }
- catch (Exception ex)
- {
- CreateDiagnostic("RS0000", $"Failed to download OpenAPI generator JAR", $"Could not download version {version}: {ex.Message}").Report(context);
- return null;
- }
- }
-
- private static void TryDeleteDirectory(string path)
- {
- try { if (Directory.Exists(path)) Directory.Delete(path, true); }
- catch { }
- }
}
From 9fe5d31492b3f50c4dd8f58214bbf8110262593c Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 18:09:49 +0000
Subject: [PATCH 09/20] Remove testing values & correctly reference "Microsoft
Kiota"
---
.../KiotaGenerator.cs | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs b/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs
index f681249..d6e2f80 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs
+++ b/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs
@@ -85,8 +85,8 @@ protected override void OnBeforeGeneration(GeneratorContext context, Cancellatio
{
CreateDiagnostic(
"KG0000",
- "Kiota installation failed",
- installError ?? "Failed to install or locate the Kiota tool.").Report(context);
+ "Microsoft Kiota installation failed",
+ installError ?? "Failed to install or locate the Microsoft Kiota tool.").Report(context);
return;
}
@@ -94,7 +94,7 @@ protected override void OnBeforeGeneration(GeneratorContext context, Cancellatio
}
catch (Exception ex)
{
- CreateDiagnostic("KG0000", "Kiota installation failed", ex.Message).Report(context);
+ CreateDiagnostic("KG0000", "Microsoft Kiota installation failed", ex.Message).Report(context);
return;
}
@@ -144,8 +144,8 @@ protected override void OnBeforeGeneration(GeneratorContext context, Cancellatio
{
CreateDiagnostic(
"KG0001",
- "Kiota generation failed",
- $"Kiota failed for spec '{specPath}' with exit code {runResult.ExitCode}: {runResult.StandardError.ReplaceLineEndings(" ")}").Report(context);
+ "OpenAPI generation failed",
+ $"Microsoft Kiota failed for spec '{specPath}' with exit code {runResult.ExitCode}: {runResult.StandardError.ReplaceLineEndings(" ")}").Report(context);
DirectoryHelpers.TryDelete(tempOut);
continue;
}
@@ -156,7 +156,7 @@ protected override void OnBeforeGeneration(GeneratorContext context, Cancellatio
CreateDiagnostic(
"KG0002",
"No C# files generated",
- $"Kiota produced no C# files for spec '{specPath}'").Report(context);
+ $"Microsoft Kiota produced no C# files for spec '{specPath}'").Report(context);
DirectoryHelpers.TryDelete(tempOut);
continue;
}
@@ -181,11 +181,11 @@ protected override void OnBeforeGeneration(GeneratorContext context, Cancellatio
}
}
- //DirectoryHelpers.TryDelete(tempOut);
+ DirectoryHelpers.TryDelete(tempOut);
}
catch (Exception ex)
{
- CreateDiagnostic("KG9999", "Kiota generator exception", ex.ToString()).Report(context);
+ CreateDiagnostic("KG9999", "OpenAPI generator exception", ex.ToString()).Report(context);
DirectoryHelpers.TryDelete(tempOut);
}
}
From ffd8050adf6a9504a5f36ab4b9467d72abb963f8 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 18:14:03 +0000
Subject: [PATCH 10/20] Completely rename "Swagger" project to "Kiota"
---
.github/workflows/ci.yml | 4 ++--
CompilerPlatform.slnx | 2 +-
.../KiotaEngine.Enums.cs | 2 +-
.../KiotaEngine.Methods.cs | 2 +-
.../KiotaEngine.cs | 2 +-
.../KiotaGenerator.cs | 2 +-
.../Riverside.CompilerPlatform.Features.Kiota.csproj} | 0
.../Riverside.CompilerPlatform.Features.Tests.csproj | 2 +-
8 files changed, 8 insertions(+), 8 deletions(-)
rename src/features/{Riverside.CompilerPlatform.Features.Swagger => Riverside.CompilerPlatform.Features.Kiota}/KiotaEngine.Enums.cs (91%)
rename src/features/{Riverside.CompilerPlatform.Features.Swagger => Riverside.CompilerPlatform.Features.Kiota}/KiotaEngine.Methods.cs (98%)
rename src/features/{Riverside.CompilerPlatform.Features.Swagger => Riverside.CompilerPlatform.Features.Kiota}/KiotaEngine.cs (99%)
rename src/features/{Riverside.CompilerPlatform.Features.Swagger => Riverside.CompilerPlatform.Features.Kiota}/KiotaGenerator.cs (99%)
rename src/features/{Riverside.CompilerPlatform.Features.Swagger/Riverside.CompilerPlatform.Features.Swagger.csproj => Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj} (100%)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7a51ba6..d2aed10 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -16,12 +16,12 @@ jobs:
fail-fast: false
matrix:
configuration: [CSharp, VisualBasic]
- project: [Analyzers, CodeFixers, Extensions, HighPerformance, SourceGenerators, DynamicCast, Swagger]
+ project: [Analyzers, CodeFixers, Extensions, HighPerformance, SourceGenerators, DynamicCast, Kiota]
exclude:
- configuration: VisualBasic
project: DynamicCast
- configuration: VisualBasic
- project: Swagger
+ project: Kiota
env:
PROJECT: ${{ matrix.project }}
diff --git a/CompilerPlatform.slnx b/CompilerPlatform.slnx
index 75a6797..cc4cc7d 100644
--- a/CompilerPlatform.slnx
+++ b/CompilerPlatform.slnx
@@ -9,7 +9,7 @@
-
+
diff --git a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.Enums.cs b/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaEngine.Enums.cs
similarity index 91%
rename from src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.Enums.cs
rename to src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaEngine.Enums.cs
index 46ee5ea..90663f7 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.Enums.cs
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaEngine.Enums.cs
@@ -1,4 +1,4 @@
-namespace Riverside.CompilerPlatform.Features.Swagger;
+namespace Riverside.CompilerPlatform.Features.Kiota;
partial class KiotaEngine
{
diff --git a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.Methods.cs b/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaEngine.Methods.cs
similarity index 98%
rename from src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.Methods.cs
rename to src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaEngine.Methods.cs
index 6031450..ac5ead9 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.Methods.cs
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaEngine.Methods.cs
@@ -1,7 +1,7 @@
using Riverside.CompilerPlatform.Helpers;
using System.Text;
-namespace Riverside.CompilerPlatform.Features.Swagger;
+namespace Riverside.CompilerPlatform.Features.Kiota;
partial class KiotaEngine
{
diff --git a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.cs b/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaEngine.cs
similarity index 99%
rename from src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.cs
rename to src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaEngine.cs
index d513be6..aff3c43 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaEngine.cs
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaEngine.cs
@@ -1,6 +1,6 @@
using System.Diagnostics.CodeAnalysis;
-namespace Riverside.CompilerPlatform.Features.Swagger;
+namespace Riverside.CompilerPlatform.Features.Kiota;
///
/// Represents the configuration and options for generating code using the Kiota engine.
diff --git a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs b/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaGenerator.cs
similarity index 99%
rename from src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs
rename to src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaGenerator.cs
index d6e2f80..f9b5924 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Swagger/KiotaGenerator.cs
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaGenerator.cs
@@ -8,7 +8,7 @@
using System.Text;
using System.Threading;
-namespace Riverside.CompilerPlatform.Features.Swagger;
+namespace Riverside.CompilerPlatform.Features.Kiota;
///
/// Generates source code from OpenAPI specification files as part of the build process.
diff --git a/src/features/Riverside.CompilerPlatform.Features.Swagger/Riverside.CompilerPlatform.Features.Swagger.csproj b/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
similarity index 100%
rename from src/features/Riverside.CompilerPlatform.Features.Swagger/Riverside.CompilerPlatform.Features.Swagger.csproj
rename to src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
diff --git a/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj b/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
index 54119ac..8a39d30 100644
--- a/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
+++ b/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
@@ -11,7 +11,7 @@
-
+
From cf7c8abf56c7721c26f4d9f198e6fa25a1ff1086 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 18:15:07 +0000
Subject: [PATCH 11/20] Remove unnecessary IDs from solution file
---
CompilerPlatform.slnx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/CompilerPlatform.slnx b/CompilerPlatform.slnx
index cc4cc7d..de535ba 100644
--- a/CompilerPlatform.slnx
+++ b/CompilerPlatform.slnx
@@ -9,7 +9,7 @@
-
+
@@ -26,7 +26,7 @@
-
+
From 97f8b63284e007533a8cc2a32a0fd9f01729e299 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 18:25:58 +0000
Subject: [PATCH 12/20] Remove accidental spaces indentation usage
I am a bad person!!
---
.../Helpers/DirectoryHelpers.cs | 42 +++++++++----------
1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/DirectoryHelpers.cs b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/DirectoryHelpers.cs
index 691d6b4..99a0167 100644
--- a/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/DirectoryHelpers.cs
+++ b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/DirectoryHelpers.cs
@@ -8,26 +8,26 @@ namespace Riverside.CompilerPlatform.Helpers;
///
public static class DirectoryHelpers
{
- ///
- /// Deletes and all of its contents recursively, suppressing any exception that occurs.
- ///
- /// The directory to delete.
- public static void TryDelete(string path)
- {
- try { if (Directory.Exists(path)) Directory.Delete(path, recursive: true); }
- catch { }
- }
+ ///
+ /// Deletes and all of its contents recursively, suppressing any exception that occurs.
+ ///
+ /// The directory to delete.
+ public static void TryDelete(string path)
+ {
+ try { if (Directory.Exists(path)) Directory.Delete(path, recursive: true); }
+ catch { }
+ }
- ///
- /// Creates a uniquely named subdirectory under and returns its full path.
- /// The subdirectory name is a compact with no formatting characters.
- ///
- /// The parent directory. Created if it does not already exist.
- /// The full path of the newly created temporary directory.
- public static string CreateTemporary(string basePath)
- {
- var path = Path.Combine(basePath, Guid.NewGuid().ToString("N"));
- Directory.CreateDirectory(path);
- return path;
- }
+ ///
+ /// Creates a uniquely named subdirectory under and returns its full path.
+ /// The subdirectory name is a compact with no formatting characters.
+ ///
+ /// The parent directory. Created if it does not already exist.
+ /// The full path of the newly created temporary directory.
+ public static string CreateTemporary(string basePath)
+ {
+ var path = Path.Combine(basePath, Guid.NewGuid().ToString("N"));
+ Directory.CreateDirectory(path);
+ return path;
+ }
}
From 4e0f8e179912c4600dd8a9b854c7e3f27f269013 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 18:37:17 +0000
Subject: [PATCH 13/20] Add `Kiota.props`
---
.../Kiota.props | 67 +++++++++++++++++++
...ide.CompilerPlatform.Features.Kiota.csproj | 5 ++
2 files changed, 72 insertions(+)
create mode 100644 src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props
diff --git a/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props b/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props
new file mode 100644
index 0000000..75bb4e3
--- /dev/null
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props
@@ -0,0 +1,67 @@
+
+
+
+ 7.3
+ 1.21.2
+ 1.21.2
+
+
+
+
+
+
+
+
+
+
+
+ <_Kiota_TargetFramework Include="$(TargetFramework)" Condition="'$(TargetFramework)' != ''" />
+ <_Kiota_TargetFramework Include="$(TargetFrameworks)" Condition="'$(TargetFrameworks)' != ''" />
+ <_Kiota_InvalidFramework Include="@(_Kiota_TargetFramework)"
+ Condition="!$([System.Text.RegularExpressions.Regex]::IsMatch('%(Identity)', '^netstandard2\.(0|1)$|^net462$|^net([8-9]|[1-9][0-9])(?:\.[0-9]+)?(?:[-.].*)?$'))" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj b/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
index f8ca381..dd149f1 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
@@ -10,6 +10,11 @@
+
+
+
+
+
all
From 8f765948cbac175ca0711446a7814aa30dd295ae Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 18:52:06 +0000
Subject: [PATCH 14/20] Clean up
---
Directory.Build.props | 3 +++
.../KiotaGenerator.cs | 4 ++--
.../Helpers/SanitizationHelpers.cs | 3 +--
.../IncrementalGenerator.cs | 10 +++++-----
4 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index a540c34..1f9add8 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,6 +1,8 @@
+
+
$(MSBuildThisFileDirectory)
$(RootDirectory)src
@@ -30,4 +32,5 @@
+
\ No newline at end of file
diff --git a/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaGenerator.cs b/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaGenerator.cs
index f9b5924..09c21a0 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaGenerator.cs
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaGenerator.cs
@@ -1,6 +1,6 @@
-using Riverside.CompilerPlatform.SourceGenerators;
-using Riverside.CompilerPlatform.Extensions;
+using Riverside.CompilerPlatform.Extensions;
using Riverside.CompilerPlatform.Helpers;
+using Riverside.CompilerPlatform.SourceGenerators;
using System;
using System.Collections.Immutable;
using System.IO;
diff --git a/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/SanitizationHelpers.cs b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/SanitizationHelpers.cs
index 70e1823..a258a42 100644
--- a/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/SanitizationHelpers.cs
+++ b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/SanitizationHelpers.cs
@@ -1,5 +1,4 @@
-using Riverside.Extensions.Accountability;
-using System;
+using System;
using System.IO;
using System.Linq;
using System.Text;
diff --git a/src/roslyn/Riverside.CompilerPlatform.SourceGenerators/IncrementalGenerator.cs b/src/roslyn/Riverside.CompilerPlatform.SourceGenerators/IncrementalGenerator.cs
index 8feb11b..8d9f615 100644
--- a/src/roslyn/Riverside.CompilerPlatform.SourceGenerators/IncrementalGenerator.cs
+++ b/src/roslyn/Riverside.CompilerPlatform.SourceGenerators/IncrementalGenerator.cs
@@ -250,11 +250,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
if (!SuppressDiagnostics)
{
// Report exceptions that occur during generation
- CreateDiagnostic(
- $"RS9999",
- "Source Generation Error",
- $"An error occurred during source generation: {ex.Message}",
- DiagnosticSeverity.Error).Report(Context);
+ CreateDiagnostic(
+ $"RS9999",
+ "Source Generation Error",
+ $"An error occurred during source generation: {ex.Message}",
+ DiagnosticSeverity.Error).Report(Context);
}
}
});
From 505dc8478e2d83a6ce6c80d34f659734e51dfac9 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 21:35:34 +0000
Subject: [PATCH 15/20] Initial progress on Kiota generator publishing
---
.../Kiota.props | 4 ++++
...ide.CompilerPlatform.Features.Kiota.csproj | 20 +++++++++++++++++--
.../{Lapse.json => Lapse12345.json} | 0
...ide.CompilerPlatform.Features.Tests.csproj | 8 +++++---
4 files changed, 27 insertions(+), 5 deletions(-)
rename tests/Riverside.CompilerPlatform.Features.Tests/{Lapse.json => Lapse12345.json} (100%)
diff --git a/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props b/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props
index 75bb4e3..ba4080b 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props
@@ -20,6 +20,10 @@
+
+
+
+
<_Kiota_TargetFramework Include="$(TargetFramework)" Condition="'$(TargetFramework)' != ''" />
<_Kiota_TargetFramework Include="$(TargetFrameworks)" Condition="'$(TargetFrameworks)' != ''" />
diff --git a/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj b/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
index dd149f1..cdd8711 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
@@ -3,11 +3,14 @@
netstandard2.0
CSharp
+ true
+ false
+ $(NoWarn);NU5128
-
-
+
+
@@ -22,4 +25,17 @@
+
+
+
+
+
+
+
+
diff --git a/tests/Riverside.CompilerPlatform.Features.Tests/Lapse.json b/tests/Riverside.CompilerPlatform.Features.Tests/Lapse12345.json
similarity index 100%
rename from tests/Riverside.CompilerPlatform.Features.Tests/Lapse.json
rename to tests/Riverside.CompilerPlatform.Features.Tests/Lapse12345.json
diff --git a/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj b/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
index 8a39d30..4d472a1 100644
--- a/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
+++ b/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
@@ -3,6 +3,7 @@
VisualBasic;CSharp
netstandard2.0
+ 14.0
@@ -10,19 +11,20 @@
-
+
+
-
+
From 03be3b40b1b6df2cd6cc9800ffb262fb0b9ec524 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 21:51:38 +0000
Subject: [PATCH 16/20] Remove unnecessary code
---
.../Riverside.CompilerPlatform.Features.Kiota/Kiota.props | 4 ----
.../Riverside.CompilerPlatform.Features.Kiota.csproj | 1 -
2 files changed, 5 deletions(-)
diff --git a/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props b/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props
index ba4080b..75bb4e3 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props
@@ -20,10 +20,6 @@
-
-
-
-
<_Kiota_TargetFramework Include="$(TargetFramework)" Condition="'$(TargetFramework)' != ''" />
<_Kiota_TargetFramework Include="$(TargetFrameworks)" Condition="'$(TargetFrameworks)' != ''" />
diff --git a/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj b/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
index cdd8711..582a3a2 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
@@ -3,7 +3,6 @@
netstandard2.0
CSharp
- true
false
$(NoWarn);NU5128
From ff7d05c8e5ad0f9777705f41acd2d11d05594e51 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 22:11:26 +0000
Subject: [PATCH 17/20] Fix ambiguity between package ID and command name in
`NETCoreToolHelper`
---
.../KiotaGenerator.cs | 2 +-
.../Helpers/NETCoreToolHelpers.cs | 18 ++++++++++++------
2 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaGenerator.cs b/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaGenerator.cs
index 09c21a0..177f3a9 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaGenerator.cs
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/KiotaGenerator.cs
@@ -78,7 +78,7 @@ protected override void OnBeforeGeneration(GeneratorContext context, Cancellatio
try
{
var (installed, installError) = NETCoreToolHelpers
- .EnsureToolAsync("Microsoft.OpenApi.Kiota", ToolDirectory, version)
+ .EnsureToolAsync("Microsoft.OpenApi.Kiota", ToolDirectory, version, commandName: "kiota")
.GetAwaiter().GetResult();
if (!installed)
diff --git a/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/NETCoreToolHelpers.cs b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/NETCoreToolHelpers.cs
index ea1c479..a80df77 100644
--- a/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/NETCoreToolHelpers.cs
+++ b/src/roslyn/Riverside.CompilerPlatform.Extensions/Helpers/NETCoreToolHelpers.cs
@@ -31,22 +31,28 @@ public static string GetExecutablePath(string toolDirectory, string toolName)
/// - Installation succeeds when the executable is present after the above steps.
///
///
- /// The NuGet package ID of the tool (e.g. Riverside.JsonBinder.Console).
+ /// The NuGet package ID of the tool (e.g. Riverside.JsonBinder.Console).
/// The directory to install the tool into, passed to --tool-path.
///
/// A specific version to pin. Pass to install or keep the latest.
///
/// Maximum wait time per install or update process. Defaults to 5 minutes.
+ ///
+ /// The executable/command name to look for in (e.g. jsonbinder).
+ /// If , is used as the command name.
+ ///
///
/// A tuple where Success is when the executable is available, and Error carries the captured stderr when installation fails.
///
public static async Task<(bool Success, string? Error)> EnsureToolAsync(
- string toolName,
+ string packageId,
string toolDirectory,
string? version = null,
- TimeSpan? timeout = null)
+ TimeSpan? timeout = null,
+ string? commandName = null)
{
- var exe = GetExecutablePath(toolDirectory, toolName);
+ var exeName = string.IsNullOrWhiteSpace(commandName) ? packageId : commandName;
+ var exe = GetExecutablePath(toolDirectory, exeName!);
var effectiveTimeout = timeout ?? TimeSpan.FromMinutes(5);
Directory.CreateDirectory(toolDirectory);
@@ -58,14 +64,14 @@ public static string GetExecutablePath(string toolDirectory, string toolName)
var versionArg = string.IsNullOrWhiteSpace(version) ? string.Empty : $" --version {version}";
var installResult = await ProcessHelpers.RunNETCoreCliAsync(
- $"tool install {toolName} {toolPathArg}{versionArg}", effectiveTimeout);
+ $"tool install {packageId} {toolPathArg}{versionArg}", effectiveTimeout);
if (installResult.ExitCode == 0)
return (true, null);
// install exits non-zero when the tool is already present; attempt an update instead
var updateResult = await ProcessHelpers.RunNETCoreCliAsync(
- $"tool update {toolName} {toolPathArg}{versionArg}", effectiveTimeout);
+ $"tool update {packageId} {toolPathArg}{versionArg}", effectiveTimeout);
return File.Exists(exe)
? (true, null)
From d06fca04b9699e968dd0cd89d2474b440078f059 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 22:13:07 +0000
Subject: [PATCH 18/20] Reference only Kiota project in tests
---
.../Riverside.CompilerPlatform.Features.Tests.csproj | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj b/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
index 4d472a1..b673344 100644
--- a/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
+++ b/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
@@ -1,4 +1,4 @@
-
+
VisualBasic;CSharp
@@ -18,9 +18,7 @@
-
-
-
+
From 664068d45588c357df37f7c71b783334c5bc8810 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 22:17:48 +0000
Subject: [PATCH 19/20] Remove implicit reference to `Microsoft.Kiota` packages
---
.../Riverside.CompilerPlatform.Features.Kiota/Kiota.props | 4 ++--
.../Riverside.CompilerPlatform.Features.Kiota.csproj | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props b/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props
index 75bb4e3..aa54407 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/Kiota.props
@@ -6,7 +6,7 @@
1.21.2
-
+
diff --git a/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj b/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
index 582a3a2..b3b6e17 100644
--- a/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
+++ b/src/features/Riverside.CompilerPlatform.Features.Kiota/Riverside.CompilerPlatform.Features.Kiota.csproj
@@ -22,6 +22,8 @@
all
runtime; build; native; contentfiles; analyzers
+
+
From 9b72aafd4543991f269df4e55c84c8186393b962 Mon Sep 17 00:00:00 2001
From: Lamparter <71598437+Lamparter@users.noreply.github.com>
Date: Sat, 14 Mar 2026 22:20:55 +0000
Subject: [PATCH 20/20] Disassemble Kiota testing framework
---
.../{Lapse12345.json => Lapse.json} | 0
.../Riverside.CompilerPlatform.Features.Tests.csproj | 12 +++++++-----
2 files changed, 7 insertions(+), 5 deletions(-)
rename tests/Riverside.CompilerPlatform.Features.Tests/{Lapse12345.json => Lapse.json} (100%)
diff --git a/tests/Riverside.CompilerPlatform.Features.Tests/Lapse12345.json b/tests/Riverside.CompilerPlatform.Features.Tests/Lapse.json
similarity index 100%
rename from tests/Riverside.CompilerPlatform.Features.Tests/Lapse12345.json
rename to tests/Riverside.CompilerPlatform.Features.Tests/Lapse.json
diff --git a/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj b/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
index b673344..b186e42 100644
--- a/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
+++ b/tests/Riverside.CompilerPlatform.Features.Tests/Riverside.CompilerPlatform.Features.Tests.csproj
@@ -1,4 +1,4 @@
-
+
VisualBasic;CSharp
@@ -11,18 +11,20 @@
-
+
-
+
+
+
-
+