Skip to content

Commit 25ab434

Browse files
committed
Bug: lineBreak inside Interpolated-Placeholder was deleting the whole line (before placeholder) due to a bug in TrimCurrentLineEnd; CodegenCS.Core bumped to 3.3.1
1 parent aef7e1b commit 25ab434

File tree

3 files changed

+55
-31
lines changed

3 files changed

+55
-31
lines changed

src/Core/CodegenCS/CodegenCS.Core.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<Description>Class Library and Toolkit for Code Generation using plain C#</Description>
99
<Copyright>Rick Drizin</Copyright>
1010
<Company>Rick Drizin</Company>
11-
<Version>3.3.0</Version>
11+
<Version>3.3.1</Version>
1212
<DocumentationFile>CodegenCS.xml</DocumentationFile>
1313
<PackageTags>code generation;code generator;templating;codegencs</PackageTags>
1414
<PublishRepositoryUrl>true</PublishRepositoryUrl>

src/Core/CodegenCS/CodegenTextWriter.ScopeContext.cs

+26-12
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ protected internal static ScopeContext CreateRootContext(CodegenTextWriter write
5353
protected internal string IndentString { get; protected set; }
5454

5555
/// <summary>
56-
/// Indent was written to current line
56+
/// Indent State regarding the current line (if <see cref="IndentString"/> was already written to current line)
5757
/// </summary>
58-
protected internal bool IndentWritten { get; set; } = false;
58+
protected internal IndentStateEnum IndentState { get; set; } = IndentStateEnum.None;
5959

6060
protected internal int StartingPos { get; protected set; }
6161

@@ -67,11 +67,6 @@ protected internal static ScopeContext CreateRootContext(CodegenTextWriter write
6767
/// </summary>
6868
protected internal string ImplicitIndentBeforeFirstPlaceHolder { get; set; } = null;
6969

70-
/// <summary>
71-
/// When we're in the middle of a line and start an inline block (which could be multiline string), the first line don't need to be indented - only the next ones
72-
/// </summary>
73-
internal bool DontIndentFirstLine = false;
74-
7570
protected internal int IndentLevel { get; set; }
7671

7772
#endregion
@@ -84,17 +79,36 @@ protected internal static ScopeContext CreateRootContext(CodegenTextWriter write
8479
/// </summary>
8580
protected internal void InnerIndentCurrentLine()
8681
{
87-
if (IndentWritten)
82+
if (IndentState != IndentStateEnum.None)
8883
return;
8984
if (string.IsNullOrEmpty(this.IndentString))
9085
return;
91-
// if DontIndentFirstLine is set it's because we're starting an inner block right "at cursor position"- no need to indent again - we're already positioned!
92-
if (DontIndentFirstLine && WhitespaceLines == 0 && NonWhitespaceLines == 0)
93-
return;
9486
ParentTextWriter.InnerWriteRaw(this.IndentString);
95-
IndentWritten = true;
87+
IndentState = IndentStateEnum.None;
88+
}
89+
#endregion
90+
91+
#region IndentStateEnum
92+
protected internal enum IndentStateEnum
93+
{
94+
/// <summary>
95+
/// Indent wasn't written to current line
96+
/// </summary>
97+
None,
98+
99+
/// <summary>
100+
/// Indent was implicitly captured from the current line (no need to write it while in this same line)
101+
/// </summary>
102+
ImplicitlyCaptured,
103+
104+
105+
/// <summary>
106+
/// Indent was written
107+
/// </summary>
108+
Written
96109
}
97110
#endregion
111+
98112
}
99113
}
100114
}

src/Core/CodegenCS/CodegenTextWriter.cs

+28-18
Original file line numberDiff line numberDiff line change
@@ -679,23 +679,32 @@ protected virtual void TrimCurrentLineEnd(bool onlyIfLineIsAllWhitespace = true)
679679
int len = _currentLine.Length;
680680
char c;
681681

682-
// Remove everything until we find last linebreak
683-
while (remove < len && ((c = _currentLine[len - remove - 1]) == '\r' || c == '\n' || c == '\t' || c == ' '))
682+
// Trim all trailing whitespace from _currentLine
683+
while (remove < len && ((c = _currentLine[len - remove - 1]) == '\r' || c == '\n' || c == '\t' || c == ' ')) //TODO: support for onlyIfLineIsAllWhitspace=false
684684
remove++;
685-
686685
if (remove != 0)
687686
_currentLine.Remove(_currentLine.Length - remove, remove);
688687

689-
// If the whole "real content" of the line was removed (or if the line didn't had any real content), then we should also remove the automatic added indent
690-
if (remove == len && _scopeContexts.Peek().IndentWritten)
688+
// If the whole "real content" of the line was removed (or if the line didn't had any real content), then we should also remove the automatic added indent(s) (if any)
689+
if (remove == len) //TODO: should also loop to remove PARENT scopes if they match contents
691690
{
692-
string indentString = _scopeContexts.Peek().IndentString;
693-
bool match = true;
694-
for (int i = 0; match && i < indentString.Length; i++)
695-
if (sb[sb.Length - remove - i - 1] != indentString[indentString.Length - i - 1])
696-
match = false;
697-
if (match)
698-
remove += indentString.Length;
691+
// Loop through all parent scopes, and while the indent of each scope matches what was written to the line we "revert" that indent written by each scope
692+
ScopeContext scope;
693+
for (int j = 0; j < _scopeContexts.Count && (scope = _scopeContexts.ElementAt(j)) != null && scope.IndentState == ScopeContext.IndentStateEnum.Written; j++)
694+
{
695+
string indentString = scope.IndentString;
696+
697+
bool match = true;
698+
for (int i = 0; match && i < indentString.Length; i++)
699+
if (sb[sb.Length - remove - i - 1] != indentString[indentString.Length - i - 1])
700+
match = false;
701+
702+
if (match)
703+
{
704+
remove += indentString.Length;
705+
scope.IndentState = ScopeContext.IndentStateEnum.None;
706+
}
707+
}
699708
}
700709

701710
if (remove != 0)
@@ -712,10 +721,9 @@ protected virtual void TrimEnd()
712721
int len = sb.Length;
713722
char c;
714723

715-
// Remove everything until we find last linebreak
724+
// Trim all trailing whitespace from _innerWriter
716725
while (remove < len && ((c = sb[len - remove - 1]) == '\r' || c == '\n' || c == '\t' || c == ' '))
717726
remove++;
718-
719727
if (remove == 0)
720728
return;
721729
sb.Remove(sb.Length - remove, remove);
@@ -745,7 +753,10 @@ protected virtual void InnerWriteNewLine(string newLine = null)
745753
foreach (var scope in _scopeContexts)
746754
scope.WhitespaceLines++;
747755
foreach (var scope in _scopeContexts)
748-
scope.IndentWritten = false;
756+
{
757+
if (scope.IndentState == ScopeContext.IndentStateEnum.ImplicitlyCaptured)
758+
scope.IndentState = ScopeContext.IndentStateEnum.None; // subsequent lines should get indent added
759+
}
749760
_currentLine.Clear();
750761
_scopeContexts.Peek().ImplicitIndentBeforeFirstPlaceHolder = null;
751762
_nextWriteRequiresLineBreak = false;
@@ -832,8 +843,8 @@ protected virtual void InnerInlineAction(Action action)
832843

833844
if (implicitIndent != null)
834845
{
835-
// implicit indent was captured and we're starting a new scope - but the first line should not have indent written (it was already explicitly written)
836-
_scopeContexts.Push(new ScopeContext(this, implicitIndent) { IndentWritten = true });
846+
// implicit indent was captured and we're starting a new scope - but the first line should not have indent written (it was already explicitly written) - only the subsequent lines
847+
_scopeContexts.Push(new ScopeContext(this, implicitIndent) { IndentState = ScopeContext.IndentStateEnum.ImplicitlyCaptured });
837848
_currentLine.Clear(); // implicitIndent will be added to all subsequent lines written by action
838849
}
839850

@@ -1717,7 +1728,6 @@ public virtual void ClearLastLine(bool onlyIfAllWhitespace = false)
17171728

17181729
sb.Remove(sb.Length - remove, remove);
17191730

1720-
17211731
_currentLine.Clear();
17221732
}
17231733
#endregion

0 commit comments

Comments
 (0)