Skip to content

Commit 7f11f46

Browse files
YVbakkerCopilot
andauthored
Add json file support, (+ .yml extension) (#19)
* Implementation * Update src/OpenApiSourceGenerator/OpenApiSourceGenerator.cs Remove explicit call to AddJsonReader as this is natively supported Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
1 parent 7a77aab commit 7f11f46

File tree

7 files changed

+129
-26
lines changed

7 files changed

+129
-26
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Feature: File Format Support
2+
Verify that different file extensions (.yaml, .yml, .json) are correctly recognized and parsed
3+
4+
Scenario Outline: Parse OpenAPI file with <extension> extension
5+
When the code generator is executed with file extension <extension>
6+
Then code should be generated
7+
8+
Examples:
9+
| extension |
10+
| .yaml |
11+
| .yml |
12+
| .json |
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using System.Linq;
2+
using Microsoft.CodeAnalysis;
3+
using Microsoft.CodeAnalysis.CSharp;
4+
using Microsoft.CodeAnalysis.Text;
5+
using OpenApiSourceGenerator;
6+
using Reqnroll;
7+
using Shouldly;
8+
9+
namespace OpenApiSourceGenerator.Tests.Features.Steps;
10+
11+
[Binding]
12+
public sealed class FileFormatsStepDefinitions(ScenarioContext scenarioContext)
13+
{
14+
private const string MinimalYamlSpec = """
15+
openapi: 3.0.0
16+
info:
17+
title: API
18+
version: 1.0.0
19+
paths: {}
20+
components:
21+
schemas:
22+
Model:
23+
type: object
24+
properties:
25+
Name:
26+
type: string
27+
""";
28+
29+
private const string MinimalJsonSpec = """
30+
{
31+
"openapi": "3.0.0",
32+
"info": {"title": "API", "version": "1.0.0"},
33+
"paths": {},
34+
"components": {
35+
"schemas": {
36+
"Model": {
37+
"type": "object",
38+
"properties": {
39+
"Name": {"type": "string"}
40+
}
41+
}
42+
}
43+
}
44+
}
45+
""";
46+
47+
[When("the code generator is executed with file extension {word}")]
48+
public void WhenTheCodeGeneratorIsExecutedWithFileExtension(string extension)
49+
{
50+
var specification = extension == ".json" ? MinimalJsonSpec : MinimalYamlSpec;
51+
52+
var generator = new OpenApiSourceGenerator();
53+
54+
GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);
55+
56+
// Add the OpenAPI specification as an additional file with the correct extension
57+
driver = driver.AddAdditionalTexts(
58+
[new TestAdditionalFile($"test{extension}", specification)]
59+
);
60+
61+
// To run generators, we can use an empty compilation
62+
var compilation = CSharpCompilation.Create(nameof(FileFormatsStepDefinitions));
63+
64+
driver.RunGeneratorsAndUpdateCompilation(compilation, out var newCompilation, out var diagnostics);
65+
66+
scenarioContext["GeneratedCompilation"] = newCompilation;
67+
scenarioContext["Diagnostics"] = diagnostics;
68+
}
69+
70+
[Then("code should be generated")]
71+
public void ThenCodeShouldBeGenerated()
72+
{
73+
var newCompilation = (Compilation)scenarioContext["GeneratedCompilation"];
74+
75+
// Get all generated syntax trees (excluding the empty compilation)
76+
var generatedTrees = newCompilation.SyntaxTrees
77+
.Where(t => !string.IsNullOrEmpty(t.FilePath))
78+
.ToList();
79+
80+
// Verify that code was generated
81+
generatedTrees.ShouldNotBeEmpty("No code was generated");
82+
}
83+
}

src/OpenApiSourceGenerator.Tests/Features/Steps/OpenApiStepDefinitions.cs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -101,22 +101,3 @@ public void ThenTheFollowingCodeShouldBeGenerated(string className, string expec
101101
generatedRoot.IsEquivalentTo(expectedRoot).ShouldBeTrue();
102102
}
103103
}
104-
105-
// Helper class to create additional files for testing
106-
internal class TestAdditionalFile : AdditionalText
107-
{
108-
private readonly string _text;
109-
110-
public TestAdditionalFile(string path, string text)
111-
{
112-
Path = path;
113-
_text = text;
114-
}
115-
116-
public override string Path { get; }
117-
118-
public override SourceText GetText(System.Threading.CancellationToken cancellationToken = default)
119-
{
120-
return SourceText.From(_text);
121-
}
122-
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.Threading;
2+
using Microsoft.CodeAnalysis;
3+
using Microsoft.CodeAnalysis.Text;
4+
5+
namespace OpenApiSourceGenerator.Tests.Features.Steps;
6+
7+
/// <summary>
8+
/// Helper class to create additional files for testing source generators
9+
/// </summary>
10+
internal class TestAdditionalFile(string path, string text) : AdditionalText
11+
{
12+
private readonly string _text = text;
13+
14+
public override string Path { get; } = path;
15+
16+
public override SourceText GetText(CancellationToken cancellationToken = default)
17+
{
18+
return SourceText.From(_text);
19+
}
20+
}

src/OpenApiSourceGenerator.Tests/OpenApiSourceGenerator.Tests.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="5.0.0" />
1010
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
1111
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
12-
<PackageReference Include="Microsoft.OpenApi" Version="3.0.1" />
13-
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="3.0.1" />
12+
<PackageReference Include="Microsoft.OpenApi" Version="3.0.2" />
13+
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="3.0.2" />
1414
<PackageReference Include="Reqnroll.TUnit" Version="3.2.1" />
1515
<PackageReference Include="Shouldly" Version="4.3.0" />
1616
<PackageReference Include="TUnit" Version="1.5.60" />

src/OpenApiSourceGenerator/OpenApiSourceGenerator.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,26 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
4040
_openApiReaderSettings.AddYamlReader();
4141

4242
var provider = context.AdditionalTextsProvider
43-
.Where(file => file.Path.EndsWith(".yaml", StringComparison.OrdinalIgnoreCase))
43+
.Where(file => file.Path.EndsWith(".yaml", StringComparison.OrdinalIgnoreCase) ||
44+
file.Path.EndsWith(".yml", StringComparison.OrdinalIgnoreCase) ||
45+
file.Path.EndsWith(".json", StringComparison.OrdinalIgnoreCase))
4446
.Collect();
4547

4648
context.RegisterSourceOutput(provider, GenerateCode);
4749
}
4850

4951
private void GenerateCode(SourceProductionContext context, ImmutableArray<AdditionalText> files)
5052
{
51-
foreach (var text in files.Select(file => file.GetText()).Where(text => text is not null))
53+
foreach (var file in files)
5254
{
53-
var (openApiDocument, _) = OpenApiDocument.Parse(text!.ToString(), "yaml", _openApiReaderSettings);
55+
var text = file.GetText();
56+
if (text is null)
57+
{
58+
continue;
59+
}
60+
61+
var format = file.Path.EndsWith(".json", StringComparison.OrdinalIgnoreCase) ? "json" : "yaml";
62+
var (openApiDocument, _) = OpenApiDocument.Parse(text.ToString(), format, _openApiReaderSettings);
5463

5564
if (openApiDocument is null)
5665
{

src/OpenApiSourceGenerator/OpenApiSourceGenerator.csproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@
4949
</PackageReference>
5050
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0"
5151
PrivateAssets="all" />
52-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="5.0.0"
53-
PrivateAssets="all" />
5452
<PackageReference Include="Microsoft.OpenApi" Version="3.0.2" PrivateAssets="all"
5553
GeneratePathProperty="true" />
5654
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="3.0.2" PrivateAssets="all" GeneratePathProperty="true" />

0 commit comments

Comments
 (0)