Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1723,8 +1723,9 @@ Cannot be combined with `@nexus.source`.
Adds an experimental API warning to the generated declaration's documentation.
The directive takes no arguments. Mark declarations individually; marking an
interface does not implicitly mark its types. For variants, the warning belongs
to the variant declaration, not its individual cases, in Python, TypeScript, Go,
and .NET.
to the variant declaration, not its individual cases, in Python, TypeScript, and
Go. In .NET, the warning appears on both the variant's base record and each
nested case record.

```wit
/// @nexus.experimental
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using Temporalio.Converters;

namespace Nexgen.NotificationService
{
Expand All @@ -22,12 +21,14 @@ private OnCompleteRequestResult() { }
/// <summary>
/// The source operation completed successfully with this output.
/// </summary>
/// <remarks>WARNING: This API is experimental and may change in the future.</remarks>
[GeneratedCode("nexgen", null)]
public sealed record Success(TOutput Value) : OnCompleteRequestResult<TOutput>;

/// <summary>
/// The source operation failed, including timeout, cancellation, and application errors.
/// </summary>
/// <remarks>WARNING: This API is experimental and may change in the future.</remarks>
[GeneratedCode("nexgen", null)]
public sealed record Failure(System.Exception Value) : OnCompleteRequestResult<TOutput>;
}
Expand Down
1 change: 0 additions & 1 deletion advanced/samples/dotnet/wit/proto-generic/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using Temporalio.Converters;
using Nexgen.Support;

namespace Nexgen.ProtoGeneric
Expand Down
1 change: 0 additions & 1 deletion advanced/samples/dotnet/wit/proto-oneof/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using Temporalio.Converters;
using Nexgen.Support;

namespace Nexgen.ProtoOneof
Expand Down
1 change: 0 additions & 1 deletion advanced/samples/dotnet/wit/start-workflow/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using Temporalio.Converters;
using Nexgen.Support;

namespace Nexgen.StartWorkflowService
Expand Down
1 change: 0 additions & 1 deletion advanced/samples/dotnet/wit/stream-service/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using Temporalio.Converters;
using Nexgen.Support;

namespace Nexgen.StreamService
Expand Down
1 change: 0 additions & 1 deletion advanced/samples/dotnet/wit/type-roundtrip/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using Temporalio.Converters;
using Nexgen.Support;

namespace Nexgen.TypeRoundtripService
Expand Down
1 change: 0 additions & 1 deletion advanced/samples/dotnet/wit/workflow-service/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using Temporalio.Converters;
using Nexgen.Support;

namespace Temporalio.Workflows
Expand Down
1 change: 1 addition & 0 deletions changelog/fixed/warning-wearing-waffle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The .NET generator now includes experimental API remarks on nested cases of experimental variants and omits the unused `Temporalio.Converters` import from model files.
9 changes: 1 addition & 8 deletions src/generator/dotnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,6 @@ impl<'a> ApiPlanner<'a> {
"System.CodeDom.Compiler",
"System.Collections.Generic",
];
if models.iter().any(|model| {
self.external_models
.model_transfer_converter_attribute(model, self.api_plan)
.is_some()
}) {
imports.push("Temporalio.Converters");
}
if self.external_model_fragments.has_models() {
imports.push("System.Text.Json");
imports.push("System.Text.Json.Serialization");
Expand Down Expand Up @@ -590,7 +583,7 @@ impl<'a> ApiPlanner<'a> {
output.push_str("() { }\n\n");
for (index, case) in variant.cases.iter().enumerate() {
let case_name = csharp_type_name(&case.name);
render_xml_summary(output, " ", case.doc.value(), false);
render_xml_summary(output, " ", case.doc.value(), variant.experimental);
output.push_str(" ");
output.push_str(GENERATED_CODE_ATTRIBUTE);
output.push('\n');
Expand Down
40 changes: 33 additions & 7 deletions tests/generate_dotnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ interface api {
}

#[test]
fn dotnet_experimental_variant_warning_applies_only_to_base_records() {
fn dotnet_experimental_variant_warning_applies_to_base_and_case_records() {
let temp_dir = unique_output_path("dotnet-experimental-variants");
fs::create_dir_all(&temp_dir).unwrap();
let wit_path = temp_dir.join("variants.wit");
Expand Down Expand Up @@ -238,12 +238,19 @@ interface api {
assert!(rendered.contains(&format!(
"{WARNING}\n[GeneratedCode(\"nexgen\", null)]\npublic abstract record Undocumented"
)));
assert!(rendered.contains(&format!(
" /// <summary>\n /// Documented case.\n /// </summary>\n {WARNING}\n [GeneratedCode(\"nexgen\", null)]\n public sealed record First("
)));
assert!(rendered.contains(&format!(
" {WARNING}\n [GeneratedCode(\"nexgen\", null)]\n public sealed record Second : Undocumented;"
)));
assert!(
rendered.contains("\n[GeneratedCode(\"nexgen\", null)]\npublic abstract record Stable")
);
assert!(rendered.contains(
" /// <summary>\n /// Documented case.\n /// </summary>\n [GeneratedCode(\"nexgen\", null)]\n public sealed record First("
"\n [GeneratedCode(\"nexgen\", null)]\n public sealed record Third : Stable;"
));
assert!(rendered.contains("public sealed record Second : Undocumented;"));
assert!(rendered.contains("public abstract record Stable"));
assert_eq!(rendered.matches(WARNING).count(), 2);
assert_eq!(rendered.matches(WARNING).count(), 4);
fs::remove_dir_all(temp_dir).unwrap();
}

Expand Down Expand Up @@ -645,6 +652,24 @@ interface workflow-service {
fs::remove_dir_all(temp_dir).unwrap();
}

#[test]
fn dotnet_imports_converters_only_where_unqualified_types_need_them() {
let root = project_root();
for example in ["notification-service", "proto-oneof", "workflow-service"] {
let files = generate_dotnet_files(
&example_input_paths(&root, example),
&[descriptor_path(&root)],
);
let models = &files[&PathBuf::from("Models.cs")];
assert!(models.contains("Temporalio.Converters.TemporalTransferTypeConverter"));
assert!(!models.contains("using Temporalio.Converters;"));
if let Some(services) = files.get(&PathBuf::from("Services.cs")) {
assert!(services.contains("ISerializationContext"));
assert!(services.contains("using Temporalio.Converters;"));
}
}
}

#[test]
fn dotnet_notification_models_convert_generic_oneofs_without_service() {
let root = project_root();
Expand All @@ -658,15 +683,16 @@ fn dotnet_notification_models_convert_generic_oneofs_without_service() {

assert!(!files.contains_key(&PathBuf::from("Services.cs")));
assert!(!files.contains_key(&PathBuf::from("Operations.cs")));
assert!(!models.contains("using Temporalio.Converters;"));
assert!(models.contains("namespace Nexgen.NotificationService\n{"));
assert!(models.contains(
" /// <summary>\n /// The successful output or failure of the source operation.\n /// </summary>\n /// <remarks>WARNING: This API is experimental and may change in the future.</remarks>\n [GeneratedCode(\"nexgen\", null)]\n public abstract record OnCompleteRequestResult<TOutput>"
));
assert!(models.contains(
" /// <summary>\n /// The source operation completed successfully with this output.\n /// </summary>\n [GeneratedCode(\"nexgen\", null)]\n public sealed record Success(TOutput Value)"
" /// <summary>\n /// The source operation completed successfully with this output.\n /// </summary>\n /// <remarks>WARNING: This API is experimental and may change in the future.</remarks>\n [GeneratedCode(\"nexgen\", null)]\n public sealed record Success(TOutput Value)"
));
assert!(models.contains(
" /// <summary>\n /// The source operation failed, including timeout, cancellation, and application errors.\n /// </summary>\n [GeneratedCode(\"nexgen\", null)]\n public sealed record Failure(System.Exception Value)"
" /// <summary>\n /// The source operation failed, including timeout, cancellation, and application errors.\n /// </summary>\n /// <remarks>WARNING: This API is experimental and may change in the future.</remarks>\n [GeneratedCode(\"nexgen\", null)]\n public sealed record Failure(System.Exception Value)"
));
assert!(
models.contains(" /// A notification that reports that a source operation completed.")
Expand Down
Loading