From b8d0a9096e48bc846d52f187b2a5b63b323fb5db Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Thu, 4 Jul 2024 08:42:09 -0700 Subject: [PATCH 1/2] Support events. --- Directory.Packages.props | 4 ++-- FacilityMarkdown.sln | 1 + conformance/ConformanceApi.fsd | 9 ++++++++ conformance/http/ConformanceApi.md | 4 ++++ conformance/http/ConformanceApi/fibonacci.md | 20 ++++++++++++++++ conformance/no-http/ConformanceApi.md | 4 ++++ .../no-http/ConformanceApi/fibonacci.md | 11 +++++++++ dotnet-tools.json | 5 ++-- .../MarkdownGenerator.cs | 11 +++++++++ .../MarkdownGeneratorGlobals.cs | 10 +++++++- .../template.scriban-txt | 23 ++++++++++++++++--- src/fsdgenmd/FsdGenMarkdownApp.cs | 3 +++ .../MarkdownGeneratorTests.cs | 8 ++++--- 13 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 conformance/http/ConformanceApi/fibonacci.md create mode 100644 conformance/no-http/ConformanceApi/fibonacci.md diff --git a/Directory.Packages.props b/Directory.Packages.props index f667941..c0e598b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,8 +4,8 @@ - - + + diff --git a/FacilityMarkdown.sln b/FacilityMarkdown.sln index 4a7a15b..546496d 100644 --- a/FacilityMarkdown.sln +++ b/FacilityMarkdown.sln @@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .github\workflows\build.yaml = .github\workflows\build.yaml Directory.Build.props = Directory.Build.props Directory.Packages.props = Directory.Packages.props + dotnet-tools.json = dotnet-tools.json global.json = global.json LICENSE = LICENSE nuget.config = nuget.config diff --git a/conformance/ConformanceApi.fsd b/conformance/ConformanceApi.fsd index ff35857..85a03e2 100644 --- a/conformance/ConformanceApi.fsd +++ b/conformance/ConformanceApi.fsd @@ -253,6 +253,15 @@ service ConformanceApi [http(from: body, type: "application/x-output")] content: bytes; } + [http(method: GET)] + event fibonacci + { + count: int32!; + }: + { + value: int32!; + } + data Any { string: string; diff --git a/conformance/http/ConformanceApi.md b/conformance/http/ConformanceApi.md index b28641c..f873997 100644 --- a/conformance/http/ConformanceApi.md +++ b/conformance/http/ConformanceApi.md @@ -20,6 +20,10 @@ API for a Facility test server. | [mirrorText](ConformanceApi/mirrorText.md) | `POST /mirrorText` | | | [bodyTypes](ConformanceApi/bodyTypes.md) | `POST /bodyTypes` | | +| event | path | description | +| --- | --- | --- | +| [fibonacci](ConformanceApi/fibonacci.md) | ` /fibonacci` | | + | data | description | | --- | --- | | [Widget](ConformanceApi/Widget.md) | A widget. | diff --git a/conformance/http/ConformanceApi/fibonacci.md b/conformance/http/ConformanceApi/fibonacci.md new file mode 100644 index 0000000..12ddcc3 --- /dev/null +++ b/conformance/http/ConformanceApi/fibonacci.md @@ -0,0 +1,20 @@ +# fibonacci (event) + +``` +GET /fibonacci + ?count={count} +--- 200 OK (server-sent events) +{ + "value": (integer) +} +``` + +| request | type | description | +| --- | --- | --- | +| count | int32 | | + +| response | type | description | +| --- | --- | --- | +| value | int32 | | + + diff --git a/conformance/no-http/ConformanceApi.md b/conformance/no-http/ConformanceApi.md index 92f74b4..8b96f13 100644 --- a/conformance/no-http/ConformanceApi.md +++ b/conformance/no-http/ConformanceApi.md @@ -20,6 +20,10 @@ API for a Facility test server. | [mirrorText](ConformanceApi/mirrorText.md) | | | [bodyTypes](ConformanceApi/bodyTypes.md) | | +| event | description | +| --- | --- | +| [fibonacci](ConformanceApi/fibonacci.md) | | + | data | description | | --- | --- | | [Widget](ConformanceApi/Widget.md) | A widget. | diff --git a/conformance/no-http/ConformanceApi/fibonacci.md b/conformance/no-http/ConformanceApi/fibonacci.md new file mode 100644 index 0000000..992a2bd --- /dev/null +++ b/conformance/no-http/ConformanceApi/fibonacci.md @@ -0,0 +1,11 @@ +# fibonacci (event) + +| request | type | description | +| --- | --- | --- | +| count | int32 | | + +| response | type | description | +| --- | --- | --- | +| value | int32 | | + + diff --git a/dotnet-tools.json b/dotnet-tools.json index 9562684..194ceef 100644 --- a/dotnet-tools.json +++ b/dotnet-tools.json @@ -3,10 +3,11 @@ "isRoot": true, "tools": { "facilityconformance": { - "version": "2.21.0", + "version": "2.29.0", "commands": [ "FacilityConformance" - ] + ], + "rollForward": false } } } \ No newline at end of file diff --git a/src/Facility.CodeGen.Markdown/MarkdownGenerator.cs b/src/Facility.CodeGen.Markdown/MarkdownGenerator.cs index 3c752f2..e30eaf7 100644 --- a/src/Facility.CodeGen.Markdown/MarkdownGenerator.cs +++ b/src/Facility.CodeGen.Markdown/MarkdownGenerator.cs @@ -1,6 +1,7 @@ using CodeGenCore; using Facility.Definition; using Facility.Definition.CodeGen; +using Facility.Definition.Fsd; using Facility.Definition.Http; namespace Facility.CodeGen.Markdown; @@ -13,8 +14,18 @@ public sealed class MarkdownGenerator : CodeGenerator /// /// Generates Markdown. /// + /// The parser. /// The settings. /// The number of updated files. + public static int GenerateMarkdown(ServiceParser parser, MarkdownGeneratorSettings settings) => + FileGenerator.GenerateFiles(parser, new MarkdownGenerator { GeneratorName = nameof(MarkdownGenerator) }, settings); + + /// + /// Generates Markdown. + /// + /// The settings. + /// The number of updated files. + [Obsolete("Use the overload that takes a parser.")] public static int GenerateMarkdown(MarkdownGeneratorSettings settings) => FileGenerator.GenerateFiles(new MarkdownGenerator { GeneratorName = nameof(MarkdownGenerator) }, settings); diff --git a/src/Facility.CodeGen.Markdown/MarkdownGeneratorGlobals.cs b/src/Facility.CodeGen.Markdown/MarkdownGeneratorGlobals.cs index f9d4561..5c96b9c 100644 --- a/src/Facility.CodeGen.Markdown/MarkdownGeneratorGlobals.cs +++ b/src/Facility.CodeGen.Markdown/MarkdownGeneratorGlobals.cs @@ -22,7 +22,15 @@ public MarkdownGeneratorGlobals(MarkdownGenerator generator, ServiceInfo service public string CodeGenCommentText { get; } public HttpElementInfo? GetHttp(ServiceElementInfo methodInfo) => - HttpService?.Methods.FirstOrDefault(x => x.ServiceMethod == methodInfo); + HttpService?.AllMethods.FirstOrDefault(x => x.ServiceMethod == methodInfo); + + public bool IsEvent(object methodInfo) => + methodInfo switch + { + ServiceMethodInfo serviceMethodInfo => serviceMethodInfo.Kind == ServiceMethodKind.Event, + HttpMethodInfo httpMethodInfo => httpMethodInfo.ServiceMethod.Kind == ServiceMethodKind.Event, + _ => false, + }; public ServiceTypeInfo? GetFieldType(ServiceFieldInfo field) => Service.GetFieldType(field); diff --git a/src/Facility.CodeGen.Markdown/template.scriban-txt b/src/Facility.CodeGen.Markdown/template.scriban-txt index d47c9df..3457e04 100644 --- a/src/Facility.CodeGen.Markdown/template.scriban-txt +++ b/src/Facility.CodeGen.Markdown/template.scriban-txt @@ -45,6 +45,23 @@ URL: [`{{ HttpService.Url }}`]({{ HttpService.Url }}) {{ end ~}} {{ end # else ~}} {{ end # if !Service.Methods.empty? ~}} +{{ if !Service.Events.empty? ~}} +{{ if HttpService ~}} + +| event | path | description | +| --- | --- | --- | +{{ for event in HttpService.Events | WhereNotObsolete ~}} +| [{{ event.ServiceMethod.Name }}]({{ Service.Name }}/{{ event.ServiceMethod.Name }}.md) | `{{ event.Event }} {{ event.Path }}` | {{ event.ServiceMethod.Summary }} | +{{ end ~}} +{{ else # if HttpService ~}} + +| event | description | +| --- | --- | +{{ for event in Service.Events | WhereNotObsolete ~}} +| [{{ event.Name }}]({{ Service.Name }}/{{ event.Name }}.md) | {{ event.Summary }} | +{{ end ~}} +{{ end # else ~}} +{{ end # if !Service.Events.empty? ~}} {{ if !Service.Dtos.empty? ~}} | data | description | @@ -73,11 +90,11 @@ URL: [`{{ HttpService.Url }}`]({{ HttpService.Url }}) {{ WriteCodeGenComment ~}} {{### Methods ### ~}} -{{ for method in Service.Methods | WhereNotObsolete ~}} +{{ for method in Service.AllMethods | WhereNotObsolete ~}} ==> {{ Service.Name }}/{{ method.Name }}.md -# {{ method.Name }} +# {{ method.Name }}{{ if method | IsEvent; ' (event)'; end }} {{ WriteSummary method ~}} {{ http = method | GetHttp ~}} {{ if http ~}} @@ -106,7 +123,7 @@ URL: [`{{ HttpService.Url }}`]({{ HttpService.Url }}) {{ end ~}} {{ end # if !http.ResponseHeaderFields.empty? ~}} {{ for response in http.ValidResponses ~}} ---- {{ response.StatusCode + 0 }} {{ response.StatusCode | StatusCodePhrase }} +--- {{ response.StatusCode + 0 }} {{ response.StatusCode | StatusCodePhrase }}{{ if method | IsEvent; ' (server-sent events)'; end }} {{ if response.BodyField ~}} ({{ if (response.BodyField.ServiceField | GetFieldType).Kind == 'Boolean'; 'if '; end }}{{ response.BodyField.ServiceField.Name }}) {{ else if !response.NormalFields.empty? ~}} diff --git a/src/fsdgenmd/FsdGenMarkdownApp.cs b/src/fsdgenmd/FsdGenMarkdownApp.cs index 613ccf5..57435b3 100644 --- a/src/fsdgenmd/FsdGenMarkdownApp.cs +++ b/src/fsdgenmd/FsdGenMarkdownApp.cs @@ -2,6 +2,7 @@ using Facility.CodeGen.Console; using Facility.CodeGen.Markdown; using Facility.Definition.CodeGen; +using Facility.Definition.Fsd; namespace fsdgenmd; @@ -22,6 +23,8 @@ public sealed class FsdGenMarkdownApp : CodeGeneratorApp " Override the default template.", ]; + protected override ServiceParser CreateParser() => new FsdParser(new FsdParserSettings { SupportsEvents = true }); + protected override CodeGenerator CreateGenerator() => new MarkdownGenerator(); protected override FileGeneratorSettings CreateSettings(ArgsReader args) => diff --git a/tests/Facility.CodeGen.Markdown.UnitTests/MarkdownGeneratorTests.cs b/tests/Facility.CodeGen.Markdown.UnitTests/MarkdownGeneratorTests.cs index 7abb862..b9a97ba 100644 --- a/tests/Facility.CodeGen.Markdown.UnitTests/MarkdownGeneratorTests.cs +++ b/tests/Facility.CodeGen.Markdown.UnitTests/MarkdownGeneratorTests.cs @@ -12,7 +12,7 @@ public void GenerateExampleApiSuccess() { ServiceInfo service; const string fileName = "Facility.CodeGen.Markdown.UnitTests.ConformanceApi.fsd"; - var parser = new FsdParser(); + var parser = CreateParser(); var stream = GetType().GetTypeInfo().Assembly.GetManifestResourceStream(fileName); Assert.That(stream, Is.Not.Null); using (var reader = new StreamReader(stream!)) @@ -31,7 +31,7 @@ public void DtoWithExternDataType() const string definition = @"service TestApi { extern data Thing; data Test { /// This is a description. thing: Thing; } }"; - var parser = new FsdParser(); + var parser = CreateParser(); var service = parser.ParseDefinition(new ServiceDefinitionText("TestApi.fsd", definition)); var generator = new MarkdownGenerator { GeneratorName = nameof(MarkdownGeneratorTests) }; @@ -48,7 +48,7 @@ public void DtoWithExternEnumType() const string definition = @"service TestApi { extern enum Kind; data Test { /// This is a description. kind: Kind; } }"; - var parser = new FsdParser(); + var parser = CreateParser(); var service = parser.ParseDefinition(new ServiceDefinitionText("TestApi.fsd", definition)); var generator = new MarkdownGenerator { GeneratorName = nameof(MarkdownGeneratorTests) }; @@ -58,4 +58,6 @@ public void DtoWithExternEnumType() Assert.That(file.Text, Does.Contain("\"kind\": (Kind)")); Assert.That(file.Text, Does.Contain("| kind | Kind | This is a description. |")); } + + private static FsdParser CreateParser() => new FsdParser(new FsdParserSettings { SupportsEvents = true }); } From ccf311b2f2cfac6c09bbb0a18f543622adfae4cc Mon Sep 17 00:00:00 2001 From: Ed Ball Date: Thu, 4 Jul 2024 08:45:25 -0700 Subject: [PATCH 2/2] Publish 2.10.0. --- Directory.Build.props | 4 ++-- ReleaseNotes.md | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 66853b1..7f00a89 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,8 @@ - 2.9.0 - 2.8.0 + 2.10.0 + 2.9.0 12.0 enable enable diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 0295a8a..218f2c1 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,5 +1,9 @@ # Release Notes +## 2.10.0 + +* Support events. + ## 2.9.0 * Add .NET 8 targets. Update dependencies.