Browse Source

Fixed forum-10067: incorrect indentation for nested if-statements without braces.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@4933 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 16 years ago
parent
commit
98fe76ebe4
  1. 102
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/Indentation.cs

102
src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/Indentation.cs

@ -20,14 +20,63 @@ namespace CSharpBinding.FormattingStrategy
public sealed class IndentationReformatter public sealed class IndentationReformatter
{ {
/// <summary>
/// An indentation block. Tracks the state of the indentation.
/// </summary>
public struct Block public struct Block
{ {
/// <summary>
/// The indentation outside of the block.
/// </summary>
public string OuterIndent; public string OuterIndent;
/// <summary>
/// The indentation inside the block.
/// </summary>
public string InnerIndent; public string InnerIndent;
/// <summary>
/// The last word that was seen inside this block.
/// Because parenthesis open a sub-block and thus don't change their parent's LastWord,
/// this property can be used to identify the type of block statement (if, while, switch)
/// at the position of the '{'.
/// </summary>
public string LastWord; public string LastWord;
/// <summary>
/// The type of bracket that opened this block (, [ or {
/// </summary>
public char Bracket; public char Bracket;
/// <summary>
/// Gets whether there's currently a line continuation going on inside this block.
/// </summary>
public bool Continuation; public bool Continuation;
public bool OneLineBlock;
/// <summary>
/// Gets whether there's currently a 'one-line-block' going on. 'one-line-blocks' occur
/// with if statements that don't use '{}'. They are not represented by a Block instance on
/// the stack, but are instead handled similar to line continuations.
/// This property is an integer because there might be multiple nested one-line-blocks.
/// As soon as there is a finished statement, OneLineBlock is reset to 0.
/// </summary>
public int OneLineBlock;
/// <summary>
/// The previous value of one-line-block before it was reset.
/// Used to restore the indentation of 'else' to the correct level.
/// </summary>
public int PreviousOneLineBlock;
public void ResetOneLineBlock()
{
PreviousOneLineBlock = OneLineBlock;
OneLineBlock = 0;
}
/// <summary>
/// Gets the line number where this block started.
/// </summary>
public int StartLine; public int StartLine;
public void Indent(IndentationSettings set) public void Indent(IndentationSettings set)
@ -40,9 +89,15 @@ namespace CSharpBinding.FormattingStrategy
OuterIndent = InnerIndent; OuterIndent = InnerIndent;
InnerIndent += str; InnerIndent += str;
Continuation = false; Continuation = false;
OneLineBlock = false; ResetOneLineBlock();
LastWord = ""; LastWord = "";
} }
public override string ToString()
{
return string.Format("[Block StartLine={0}, LastWord='{1}', Continuation={2}, OneLineBlock={3}, PreviousOneLineBlock={4}]",
this.StartLine, this.LastWord, this.Continuation, this.OneLineBlock, this.PreviousOneLineBlock);
}
} }
StringBuilder wordBuilder; StringBuilder wordBuilder;
@ -78,7 +133,8 @@ namespace CSharpBinding.FormattingStrategy
block.Bracket = '{'; block.Bracket = '{';
block.Continuation = false; block.Continuation = false;
block.LastWord = ""; block.LastWord = "";
block.OneLineBlock = false; block.OneLineBlock = 0;
block.PreviousOneLineBlock = 0;
block.StartLine = 0; block.StartLine = 0;
inString = false; inString = false;
@ -104,8 +160,7 @@ namespace CSharpBinding.FormattingStrategy
if (blockComment || (inString && verbatim)) if (blockComment || (inString && verbatim))
return; return;
indent.Append(block.InnerIndent); indent.Append(block.InnerIndent);
if (block.OneLineBlock) indent.Append(Repeat(set.IndentString, block.OneLineBlock));
indent.Append(set.IndentString);
if (block.Continuation) if (block.Continuation)
indent.Append(set.IndentString); indent.Append(set.IndentString);
if (doc.Text != indent.ToString()) if (doc.Text != indent.ToString())
@ -212,7 +267,7 @@ namespace CSharpBinding.FormattingStrategy
#region Push/Pop the blocks #region Push/Pop the blocks
switch (c) { switch (c) {
case '{': case '{':
block.OneLineBlock = false; block.ResetOneLineBlock();
blocks.Push(block); blocks.Push(block);
block.StartLine = doc.LineNumber; block.StartLine = doc.LineNumber;
if (block.LastWord == "switch") { if (block.LastWord == "switch") {
@ -242,7 +297,7 @@ namespace CSharpBinding.FormattingStrategy
if (blocks.Count == 0) break; if (blocks.Count == 0) break;
block = blocks.Pop(); block = blocks.Pop();
block.Continuation = false; block.Continuation = false;
block.OneLineBlock = false; block.ResetOneLineBlock();
break; break;
case '(': case '(':
case '[': case '[':
@ -252,7 +307,7 @@ namespace CSharpBinding.FormattingStrategy
else else
block.StartLine = doc.LineNumber; block.StartLine = doc.LineNumber;
block.Indent(set, block.Indent(set,
(oldBlock.OneLineBlock ? set.IndentString : "") + Repeat(set.IndentString, oldBlock.OneLineBlock) +
(oldBlock.Continuation ? set.IndentString : "") + (oldBlock.Continuation ? set.IndentString : "") +
(i == line.Length - 1 ? set.IndentString : new String(' ', i + 1))); (i == line.Length - 1 ? set.IndentString : new String(' ', i + 1)));
block.Bracket = c; block.Bracket = c;
@ -273,12 +328,12 @@ namespace CSharpBinding.FormattingStrategy
case ';': case ';':
case ',': case ',':
block.Continuation = false; block.Continuation = false;
block.OneLineBlock = false; block.ResetOneLineBlock();
break; break;
case ':': case ':':
if (block.LastWord == "case" || line.StartsWith("case ") || line.StartsWith(block.LastWord + ":")) { if (block.LastWord == "case" || line.StartsWith("case ") || line.StartsWith(block.LastWord + ":")) {
block.Continuation = false; block.Continuation = false;
block.OneLineBlock = false; block.ResetOneLineBlock();
} }
break; break;
} }
@ -302,7 +357,7 @@ namespace CSharpBinding.FormattingStrategy
if (line[0] == '}') { if (line[0] == '}') {
indent.Append(oldBlock.OuterIndent); indent.Append(oldBlock.OuterIndent);
oldBlock.OneLineBlock = false; oldBlock.ResetOneLineBlock();
oldBlock.Continuation = false; oldBlock.Continuation = false;
} else { } else {
indent.Append(oldBlock.InnerIndent); indent.Append(oldBlock.InnerIndent);
@ -321,18 +376,19 @@ namespace CSharpBinding.FormattingStrategy
indent.Remove(indent.Length - set.IndentString.Length, set.IndentString.Length); indent.Remove(indent.Length - set.IndentString.Length, set.IndentString.Length);
} else if (lastRealChar == ')') { } else if (lastRealChar == ')') {
if (IsSingleStatementKeyword(block.LastWord)) { if (IsSingleStatementKeyword(block.LastWord)) {
block.OneLineBlock = true; block.OneLineBlock++;
} }
} else if (lastRealChar == 'e' && block.LastWord == "else") { } else if (lastRealChar == 'e' && block.LastWord == "else") {
block.OneLineBlock = true; block.OneLineBlock = Math.Max(1, block.PreviousOneLineBlock);
block.Continuation = false; block.Continuation = false;
oldBlock.OneLineBlock = block.OneLineBlock - 1;
} }
if (doc.ReadOnly) { if (doc.ReadOnly) {
// We can't change the current line, but we should accept the existing // We can't change the current line, but we should accept the existing
// indentation if possible (=if the current statement is not a multiline // indentation if possible (=if the current statement is not a multiline
// statement). // statement).
if (!oldBlock.Continuation && !oldBlock.OneLineBlock && if (!oldBlock.Continuation && oldBlock.OneLineBlock == 0 &&
oldBlock.StartLine == block.StartLine && oldBlock.StartLine == block.StartLine &&
block.StartLine < doc.LineNumber && lastRealChar != ':') block.StartLine < doc.LineNumber && lastRealChar != ':')
{ {
@ -357,8 +413,7 @@ namespace CSharpBinding.FormattingStrategy
if (line[0] != '{') { if (line[0] != '{') {
if (line[0] != ')' && oldBlock.Continuation && oldBlock.Bracket == '{') if (line[0] != ')' && oldBlock.Continuation && oldBlock.Bracket == '{')
indent.Append(set.IndentString); indent.Append(set.IndentString);
if (oldBlock.OneLineBlock) indent.Append(Repeat(set.IndentString, oldBlock.OneLineBlock));
indent.Append(set.IndentString);
} }
// this is only for blockcomment lines starting with *, // this is only for blockcomment lines starting with *,
@ -374,7 +429,20 @@ namespace CSharpBinding.FormattingStrategy
} }
} }
bool IsSingleStatementKeyword(string keyword) { static string Repeat(string text, int count)
{
if (count == 0)
return string.Empty;
if (count == 1)
return text;
StringBuilder b = new StringBuilder(text.Length * count);
for (int i = 0; i < count; i++)
b.Append(text);
return b.ToString();
}
bool IsSingleStatementKeyword(string keyword)
{
switch (keyword) { switch (keyword) {
case "if": case "if":
case "for": case "for":

Loading…
Cancel
Save