From 1bd43a12b334788156b7e0e65e127f5ddaf043a4 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 5 Nov 2026 16:27:27 +0000 Subject: [PATCH] Skip blank entries in WriteUsings instead of writing `using ;` [patch] WriteUsings wrote every entry verbatim, so an empty or whitespace entry produced `using ;` (CS1001). A generator that builds optional usings as `condition ? "Ns" : ""` hit this directly, as did SourceFileTemplate.Usings, which goes through the same path. Null, empty and whitespace entries are now skipped, and a list made only of them writes nothing, not even the trailing blank line. Fixes #189 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017vfJW5wqHMdBMn6Wino1eH --- .../CodeBlockerExtensionsTests.cs | 24 +++++++++++++++++++ CodeBlocker.Test/TemplateTests.cs | 14 +++++++++++ CodeBlocker/CodeBlockerExtensions.cs | 11 +++++++-- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/CodeBlocker.Test/CodeBlockerExtensionsTests.cs b/CodeBlocker.Test/CodeBlockerExtensionsTests.cs index b6bfae1..25ffe88 100644 --- a/CodeBlocker.Test/CodeBlockerExtensionsTests.cs +++ b/CodeBlocker.Test/CodeBlockerExtensionsTests.cs @@ -162,6 +162,30 @@ public void NoUsingsWritesNothingIncludingTheBlankLine() Assert.AreEqual(string.Empty, emptySequence.ToString()); } + [TestMethod] + public void BlankUsingEntriesAreSkipped() + { + // A generator that builds optional usings as `condition ? "Ns" : ""` must not get `using ;`. + using CodeBlocker codeBlocker = Create(); + + codeBlocker.WriteUsings("System", "", " ", null!, "System.Linq"); + + Assert.AreEqual("using System;\nusing System.Linq;\n\n", codeBlocker.ToString()); + } + + [TestMethod] + public void OnlyBlankUsingEntriesWriteNothingIncludingTheBlankLine() + { + using CodeBlocker arrayOverload = Create(); + using CodeBlocker sequenceOverload = Create(); + + arrayOverload.WriteUsings("", " ", "\t"); + sequenceOverload.WriteUsings(new List { "", " " }); + + Assert.AreEqual(string.Empty, arrayOverload.ToString()); + Assert.AreEqual(string.Empty, sequenceOverload.ToString()); + } + [TestMethod] public void APreambleComposesWithConsistentSpacing() { diff --git a/CodeBlocker.Test/TemplateTests.cs b/CodeBlocker.Test/TemplateTests.cs index 3fd8237..72d4d8b 100644 --- a/CodeBlocker.Test/TemplateTests.cs +++ b/CodeBlocker.Test/TemplateTests.cs @@ -1536,6 +1536,20 @@ private class Inner public void AnEmptySourceFileWritesNothing() => Assert.AreEqual(string.Empty, Render(codeBlocker => codeBlocker.AddSourceFile(new SourceFileTemplate()))); + [TestMethod] + public void ASourceFileSkipsBlankUsings() + { + SourceFileTemplate file = new() + { + Namespace = "Contoso", + Usings = { "System", "", "System.Linq" }, + }; + + Assert.AreEqual( + "namespace Contoso;\n\nusing System;\nusing System.Linq;\n\n", + Render(codeBlocker => codeBlocker.AddSourceFile(file))); + } + [TestMethod] public void ASourceFileWithAnInvalidClassWritesNothing() { diff --git a/CodeBlocker/CodeBlockerExtensions.cs b/CodeBlocker/CodeBlockerExtensions.cs index 00365ef..b1fae56 100644 --- a/CodeBlocker/CodeBlockerExtensions.cs +++ b/CodeBlocker/CodeBlockerExtensions.cs @@ -95,13 +95,15 @@ public static CodeBlocker WriteFileScopedNamespace(this CodeBlocker codeBlocker, /// /// Writes one using directive per entry followed by a blank line, or nothing at all when - /// the sequence is empty. + /// the sequence has no namespaces in it. /// /// The to write to. /// /// The namespaces to import, without the using keyword or the trailing semicolon. An /// entry may carry a modifier or alias — static System.Math, Alias = System.Text — - /// because it is written verbatim after the keyword. + /// because it is written verbatim after the keyword. Entries that are , + /// empty or whitespace are skipped, so a generator can pass condition ? "Some.Namespace" : "" + /// without producing using ;. /// /// The same , for chaining. /// @@ -115,6 +117,11 @@ public static CodeBlocker WriteUsings(this CodeBlocker codeBlocker, IEnumerable< bool wroteAny = false; foreach (string usingDirective in usings) { + if (string.IsNullOrWhiteSpace(usingDirective)) + { + continue; + } + codeBlocker.WriteLine($"using {usingDirective};"); wroteAny = true; }