diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Writers/CodeWriter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Writers/CodeWriter.cs index f57b5435a4d..24156f94b49 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Writers/CodeWriter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Writers/CodeWriter.cs @@ -658,8 +658,11 @@ private void AppendType(CSharpType type, bool isDeclaration, bool writeTypeNameO UseNamespace(type.Namespace); AppendRaw("global::"); - AppendRaw(type.Namespace); - AppendRaw("."); + if (!string.IsNullOrEmpty(type.Namespace)) + { + AppendRaw(type.Namespace); + AppendRaw("."); + } if (type.DeclaringType is not null) AppendRaw($"{type.DeclaringType.Name}."); AppendRaw(type.Name); diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Writers/CodeWriterTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Writers/CodeWriterTests.cs index 6fec1f24139..cfa5e02c23e 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Writers/CodeWriterTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Writers/CodeWriterTests.cs @@ -727,5 +727,54 @@ public void CodeWriter_WriteMethod_AbstractMethodWithoutBody() var result = codeWriter.ToString(false); Assert.AreEqual(expected, result); } + + // Regression test for https://github.com/microsoft/typespec/issues/9880 + // When a CSharpType has an empty namespace (can happen when Roslyn cannot resolve the type), + // the CodeWriter should not output "global::." (global prefix followed by empty namespace and dot). + [Test] + public void TypeWithEmptyNamespaceDoesNotOutputGlobalDot() + { + // Create a CSharpType with an empty namespace (simulating an unresolved error type) + var typeWithEmptyNamespace = new CSharpType( + "UnresolvedType", + "", // empty namespace + isValueType: false, + isNullable: false, + declaringType: null, + args: [], + isPublic: true, + isStruct: false); + + using var writer = new CodeWriter(); + writer.Append($"{typeWithEmptyNamespace}"); + var result = writer.ToString(false); + + // Should contain "global::UnresolvedType" (without extra dot after global::) + Assert.That(result, Does.Contain("global::UnresolvedType"), + "Type with empty namespace should be prefixed with 'global::' directly followed by the type name"); + } + + // Verifies that types with proper namespaces still work correctly + [Test] + public void TypeWithNamespaceOutputsCorrectly() + { + var typeWithNamespace = new CSharpType( + "ResolvedType", + "Sample.Models", + isValueType: false, + isNullable: false, + declaringType: null, + args: [], + isPublic: true, + isStruct: false); + + using var writer = new CodeWriter(); + writer.Append($"{typeWithNamespace}"); + var result = writer.ToString(false); + + // Should contain the full qualified name + Assert.That(result, Does.Contain("global::Sample.Models.ResolvedType"), + "Type with namespace should include the full namespace in output"); + } } }