Skip to content

Commit

Permalink
Ensure code writer always has a StringBuilder
Browse files Browse the repository at this point in the history
There was an edge case where contents written to nested sections of
captured sections would be swallowed due to how code writer lazily
created StringBuilders. This change ensures that the root writer and
every interceptable writer always define a StringBuilder to ensure no
text is omitted.
  • Loading branch information
mtdowling authored and Michael Dowling committed Mar 11, 2022
1 parent 1332628 commit bbee4b7
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1766,7 +1766,6 @@ private final class State {
private CopyOnWriteRef<CodeWriterFormatterContainer> formatters;
private CopyOnWriteRef<CodeInterceptorContainer<T>> interceptors;

/** This StringBuilder, if null, will only be created lazily when needed. */
private StringBuilder builder;

/**
Expand All @@ -1777,6 +1776,7 @@ private final class State {
private boolean isInline;

State() {
builder = new StringBuilder();
isRoot = true;
CodeWriterFormatterContainer formatterContainer = new CodeWriterFormatterContainer();
DEFAULT_FORMATTERS.forEach(formatterContainer::putFormatter);
Expand Down Expand Up @@ -1810,13 +1810,10 @@ private void copyStateFrom(State copy) {

@Override
public String toString() {
return builder == null ? "" : builder.toString();
return getBuilder().toString();
}

StringBuilder getBuilder() {
if (builder == null) {
builder = new StringBuilder();
}
return builder;
}

Expand Down Expand Up @@ -1921,7 +1918,7 @@ private void makeInterceptableCodeSection(CodeSection section) {
// level is reset back to the root, and the newline prefix is removed.
// Indentation and prefixes are added automatically if/when the
// captured text is written into the parent state.
currentState.builder = null;
currentState.builder = new StringBuilder();
currentState.newlinePrefix = "";
dedent(-1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1030,4 +1030,22 @@ public void ensuresNewlineIsPresent() {

assertThat(writer.toString(), equalTo("Foo\nBar\nBaz\nBam\n"));
}

// Dynamically creating builders for a section doesn't work when pushing
// sections into captured sections that haven't written anything yet.
// It ends up swallowing the text written to sub-sections because the
// top-level section's builder wasn't written yet. This test makes sure
// that doesn't happen.
@Test
public void alwaysWritesToParentBuilders() {
SimpleCodeWriter writer = new SimpleCodeWriter();

writer.pushState("Hi");
writer.pushState();
writer.write("Hello");
writer.popState();
writer.popState();

assertThat(writer.toString(), equalTo("Hello\n"));
}
}

0 comments on commit bbee4b7

Please sign in to comment.