Skip to content

Accept any TextWriter, not just StringWriter #82

Description

@matt-edmondson

Problem

CodeBlocker's only constructor takes a StringWriter:

public class CodeBlocker(StringWriter stringWriter) : IDisposable

IndentedTextWriter itself accepts any TextWriter, so the restriction is self-imposed. It rules out generating straight to a StreamWriter (a file), to a TextWriter supplied by a build task, or to a test double — which matters for a generator emitting many files, where buffering every one in memory as a string is wasteful.

The restriction exists because ToString() reads back from the captured StringWriter:

public override string ToString() => stringWriter.ToString();

Proposal

  • Add a CodeBlocker(TextWriter writer) constructor (plus the indentString overload) and keep the StringWriter ones as the convenient path.
  • Keep Create() / Create(string) returning a StringWriter-backed instance, so ToString() continues to work for the common case and the existing API is unaffected.
  • Make ToString() honest for the general case: return the buffered text when the underlying writer is a StringWriter, otherwise either fall back to base.ToString() or throw InvalidOperationException with a message pointing at Create(). Pick one and document it — silently returning a type name would be worse than either.
  • Preserve the existing disposal contract: CodeBlocker disposes the writer only when it created it (shouldDisposeStringWriter), never a caller-supplied one.

Acceptance criteria

  • A CodeBlocker can be constructed over an arbitrary TextWriter and writes indented output to it.
  • A caller-supplied writer is not disposed by CodeBlocker.Dispose(); a Create()-owned one still is.
  • ToString() behaviour on a non-StringWriter instance is specified and covered by a test.
  • Existing StringWriter API and behaviour unchanged.

Context

Part of ktsu-dev/Semantics#181 — generalizing the code-generation stack so more projects can use it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions