@@ -46,6 +46,9 @@ export class IndentedWriter {
4646 private readonly _indentStack : string [ ] ;
4747 private _indentText : string ;
4848
49+ private _beforeStack : string [ ] ;
50+ private _isWritingBeforeStack : boolean ;
51+
4952 public constructor ( builder ?: IStringBuilder ) {
5053 this . _builder = builder === undefined ? new StringBuilder ( ) : builder ;
5154
@@ -55,6 +58,9 @@ export class IndentedWriter {
5558
5659 this . _indentStack = [ ] ;
5760 this . _indentText = '' ;
61+
62+ this . _beforeStack = [ ] ;
63+ this . _isWritingBeforeStack = false ;
5864 }
5965
6066 /**
@@ -149,6 +155,30 @@ export class IndentedWriter {
149155 return '' ;
150156 }
151157
158+ /**
159+ * Writes `before` and `after` messages if and only if `mayWrite` writes anything.
160+ *
161+ * If `mayWrite` writes "CONTENT", this method will write "<before>CONTENT<after>".
162+ * If `mayWrite` writes nothing, this method will write nothing.
163+ */
164+ public writeTentative ( before : string , after : string , mayWrite : ( ) => void ) : void {
165+ this . _beforeStack . push ( before ) ;
166+
167+ // If this function writes anything, then _all_ messages in the "before stack" will also be
168+ // written. This means that the stack will be empty (as when we write a message from the stack,
169+ // we remove it from the stack).
170+ mayWrite ( ) ;
171+
172+ // If the stack is not empty, it means that `mayWrite` didn't write anything. Pop the last-
173+ // added message from the stack, we'll never write it. Otherwise, if the stack is empty, then
174+ // write the "after" message.
175+ if ( this . _beforeStack . length > 0 ) {
176+ this . _beforeStack . pop ( ) ;
177+ } else {
178+ this . write ( after ) ;
179+ }
180+ }
181+
152182 /**
153183 * Writes some text to the internal string buffer, applying indentation according
154184 * to the current indentation level. If the string contains multiple newlines,
@@ -159,6 +189,10 @@ export class IndentedWriter {
159189 return ;
160190 }
161191
192+ if ( ! this . _isWritingBeforeStack ) {
193+ this . _writeBeforeStack ( ) ;
194+ }
195+
162196 // If there are no newline characters, then append the string verbatim
163197 if ( ! / [ \r \n ] / . test ( message ) ) {
164198 this . _writeLinePart ( message ) ;
@@ -186,7 +220,10 @@ export class IndentedWriter {
186220 public writeLine ( message : string = '' ) : void {
187221 if ( message . length > 0 ) {
188222 this . write ( message ) ;
223+ } else if ( ! this . _isWritingBeforeStack ) {
224+ this . _writeBeforeStack ( ) ;
189225 }
226+
190227 this . _writeNewLine ( ) ;
191228 }
192229
@@ -218,6 +255,21 @@ export class IndentedWriter {
218255 this . _builder . append ( s ) ;
219256 }
220257
258+ /**
259+ * Writes all messages in our before stack, processing them in FIFO order. This stack is
260+ * populated by the `writeTentative` method.
261+ */
262+ private _writeBeforeStack ( ) : void {
263+ this . _isWritingBeforeStack = true ;
264+
265+ for ( const message of this . _beforeStack ) {
266+ this . write ( message ) ;
267+ }
268+
269+ this . _isWritingBeforeStack = false ;
270+ this . _beforeStack = [ ] ;
271+ }
272+
221273 private _updateIndentText ( ) : void {
222274 this . _indentText = this . _indentStack . join ( '' ) ;
223275 }
0 commit comments