Browse Source

indentation is now respecting ILCs

4.0
Siegfried Pammer 15 years ago
parent
commit
55de9e4431
  1. 136
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBNetFormattingStrategy.cs
  2. 114
      src/AddIns/BackendBindings/VBNetBinding/Test/FormattingStrategy/IndentationTests.cs

136
src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBNetFormattingStrategy.cs

@ -408,7 +408,6 @@ namespace ICSharpCode.VBNetBinding @@ -408,7 +408,6 @@ namespace ICSharpCode.VBNetBinding
while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF) {
if (prevToken == null)
prevToken = currentToken;
if (IsBlockStart(lexer, currentToken, prevToken)) {
if ((tokens.Count > 0 && tokens.Peek().Kind != Tokens.Interface) || IsDeclaration(currentToken.Kind))
tokens.Push(currentToken);
@ -514,10 +513,9 @@ namespace ICSharpCode.VBNetBinding @@ -514,10 +513,9 @@ namespace ICSharpCode.VBNetBinding
ILexer lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, new StringReader(editor.Document.Text));
Stack<string> indentation = new Stack<string>();
indentation.Push(string.Empty);
int oldLine = 1;
List<int> eols = new List<int>();
bool inInterface = false;
bool isMustOverride = false;
@ -527,6 +525,8 @@ namespace ICSharpCode.VBNetBinding @@ -527,6 +525,8 @@ namespace ICSharpCode.VBNetBinding
Token currentToken = null;
Token prevToken = null;
int blockStart = 1;
while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF) {
if (prevToken == null)
prevToken = currentToken;
@ -540,11 +540,16 @@ namespace ICSharpCode.VBNetBinding @@ -540,11 +540,16 @@ namespace ICSharpCode.VBNetBinding
if (currentToken.Kind == Tokens.Declare)
isDeclare = true;
if (currentToken.Kind == Tokens.EOL)
if (currentToken.Kind == Tokens.EOL) {
isDelegate = isDeclare = isMustOverride = false;
eols.Add(currentToken.Location.Line);
}
if (IsBlockEnd(currentToken, prevToken)) {
ApplyToRange(editor, indentation, oldLine, currentToken.Location.Line, begin, end);
// indent the lines inside the block
// this is an End-statement
// hence we indent from blockStart to the previous line
ApplyToRange(editor, indentation, eols, blockStart, currentToken.Location.Line - 1, begin, end);
if (currentToken.Kind == Tokens.Interface)
inInterface = false;
@ -556,12 +561,17 @@ namespace ICSharpCode.VBNetBinding @@ -556,12 +561,17 @@ namespace ICSharpCode.VBNetBinding
Unindent(indentation);
}
oldLine = currentToken.Location.Line;
// block start is this line (for the lines between two blocks)
blockStart = currentToken.Location.Line;
}
if (IsBlockStart(lexer, currentToken, prevToken)) {
int line = GetLastVisualLine(currentToken.Location.Line, editor);
ApplyToRange(editor, indentation, oldLine, line, begin, end);
// indent the lines between the last and this block
// this is a Begin-statement
// hence we indent from blockStart to the this line
int lastVisualLine = FindNextEol(lexer);
eols.Add(lastVisualLine);
ApplyToRange(editor, indentation, eols, blockStart, lastVisualLine, begin, end);
if (!inInterface && !isMustOverride && !isDeclare && !isDelegate) {
Indent(editor, indentation);
@ -573,31 +583,78 @@ namespace ICSharpCode.VBNetBinding @@ -573,31 +583,78 @@ namespace ICSharpCode.VBNetBinding
if (currentToken.Kind == Tokens.Interface)
inInterface = true;
oldLine = line + 1;
// block start is the following line (for the lines inside a block)
blockStart = lastVisualLine + 1;
}
prevToken = currentToken;
}
// do last indent step
int newLine = prevToken.Location.Line;
if (oldLine > newLine)
newLine = oldLine;
ApplyToRange(editor, indentation, oldLine, newLine, begin, end);
ApplyToRange(editor, indentation, eols, blockStart, editor.Document.TotalNumberOfLines, begin, end);
return (indentation.PeekOrDefault() ?? string.Empty).Length;
}
static int GetLastVisualLine(int line, ITextEditor area)
static int FindNextEol(ILexer lexer)
{
string text = area.Document.GetLine(line).Text.TrimComments();
while (text.EndsWith("_", StringComparison.Ordinal)) {
line++;
text = area.Document.GetLine(line).Text.TrimComments();
lexer.StartPeek();
Token t = lexer.Peek();
while (t.Kind != Tokens.EOL)
t = lexer.Peek();
return t.Location.Line;
}
static void ApplyToRange(ITextEditor editor, Stack<string> indentation, List<int> eols, int blockStart, int blockEnd, int selectionStart, int selectionEnd) {
LoggingService.InfoFormatted("indenting line {0} to {1} with {2}", blockStart, blockEnd, (indentation.PeekOrDefault() ?? "").Length);
int nextEol = -1;
bool wasMultiLine = false;
for (int i = blockStart; i <= blockEnd; i++) {
IDocumentLine curLine = editor.Document.GetLine(i);
string lineText = curLine.Text.TrimStart();
string noComments = lineText.TrimComments().TrimEnd();
// adjust indentation if the current line is not selected
// lines between the selection will be aligned to the selected level
if (i < selectionStart || i > selectionEnd) {
indentation.PopOrDefault();
indentation.Push(DocumentUtilitites.GetWhitespaceAfter(editor.Document, curLine.Offset));
}
// look for next eol if line is not empty
// (the lexer does not produce eols for empty lines)
if (!string.IsNullOrEmpty(noComments) && i >= nextEol) {
int search = eols.BinarySearch(i);
if (search < 0)
search = ~search;
nextEol = search < eols.Count ? eols[search] : i;
}
// remove indentation in last line of multiline array(, collection, object) initializers
if (i == nextEol && wasMultiLine && noComments == "}") {
wasMultiLine = false;
Unindent(indentation);
}
// apply the indentation
editor.Document.SmartReplaceLine(curLine, (indentation.PeekOrDefault() ?? "") + lineText);
// indent line if it is ended by (implicit) line continuation
if (i < nextEol && !wasMultiLine) {
wasMultiLine = true;
Indent(editor, indentation);
}
// unindent if this is the last line of a multiline statement
if (i == nextEol && wasMultiLine) {
wasMultiLine = false;
Unindent(indentation);
}
}
return line;
}
static void Unindent(Stack<string> indentation)
@ -718,41 +775,6 @@ namespace ICSharpCode.VBNetBinding @@ -718,41 +775,6 @@ namespace ICSharpCode.VBNetBinding
return false;
}
static void ApplyToRange(ITextEditor editor, Stack<string> indentation, int begin, int end, int selBegin, int selEnd)
{
bool multiLine = false;
for (int i = begin; i <= end; i++) {
IDocumentLine curLine = editor.Document.GetLine(i);
string lineText = curLine.Text.TrimStart(' ', '\t', '\r', '\n');
string noComments = lineText.TrimComments().TrimEnd(' ', '\t', '\r', '\n');
if (i < selBegin || i > selEnd) {
indentation.PopOrDefault();
indentation.Push(DocumentUtilitites.GetWhitespaceAfter(editor.Document, curLine.Offset));
}
// change indentation before (indent this line)
if (multiLine && noComments.EndsWith("}", StringComparison.OrdinalIgnoreCase)) {
Unindent(indentation);
multiLine = false;
}
editor.Document.SmartReplaceLine(curLine, (indentation.PeekOrDefault() ?? string.Empty) + lineText);
// change indentation afterwards (indent next line)
if (!multiLine && noComments.EndsWith("_", StringComparison.OrdinalIgnoreCase)) {
Indent(editor, indentation);
multiLine = true;
}
if (multiLine && !noComments.EndsWith("_", StringComparison.OrdinalIgnoreCase)) {
multiLine = false;
Unindent(indentation);
}
}
}
/// <summary>
/// Gets the next member after the specified caret position.
/// </summary>

114
src/AddIns/BackendBindings/VBNetBinding/Test/FormattingStrategy/IndentationTests.cs

@ -9,7 +9,7 @@ using NUnit.Framework; @@ -9,7 +9,7 @@ using NUnit.Framework;
namespace ICSharpCode.VBNetBinding.Tests
{
[TestFixture, Ignore]
[TestFixture]
public class IndentationTests
{
[Test]
@ -63,22 +63,93 @@ End Interface"; @@ -63,22 +63,93 @@ End Interface";
}
[Test]
public void ArrayInitializerTest()
public void SD1775_Fix()
{
string expected = @"Public Class Test
Private Sub Tester()
test(asdf, _
asdf, _
asdf, _
asdf)
Dim test As Integer() = { _
2,2,3,34,4,5 _
}
B = New Burger With {Cheese = True, _
Lettuce = True, _
Tomato = True, _
CookLevel = MeatCookLevel.WellDone}
End Sub
End Class";
string code = @"Public Class Test
Private Sub Tester()
B = New Burger With {Cheese = True, _
Lettuce = True, _
Tomato = True, _
CookLevel = MeatCookLevel.WellDone}
End Sub
End Class";
RunFormatTest(code, expected);
}
[Test]
public void Simple()
{
string expected = @"'
' Created by SharpDevelop.
' User: Siegfried
' Date: 25.02.2011
' Time: 14:41
'
' To change this template use Tools | Options | Coding | Edit Standard Headers.
'
Imports Microsoft.VisualBasic.ApplicationServices
Namespace My
' This file controls the behaviour of the application.
Partial Class MyApplication
Public Sub New()
MyBase.New(AuthenticationMode.Windows)
Me.IsSingleInstance = False
Me.EnableVisualStyles = True
Me.SaveMySettingsOnExit = True
Me.ShutDownStyle = ShutdownMode.AfterMainFormCloses
End Sub
Protected Overrides Sub OnCreateMainForm()
Me.MainForm = My.Forms.MainForm
End Sub
End Class
End Namespace";
string code = @"'
' Created by SharpDevelop.
' User: Siegfried
' Date: 25.02.2011
' Time: 14:41
'
' To change this template use Tools | Options | Coding | Edit Standard Headers.
'
Imports Microsoft.VisualBasic.ApplicationServices
Namespace My
' This file controls the behaviour of the application.
Partial Class MyApplication
Public Sub New()
MyBase.New(AuthenticationMode.Windows)
Me.IsSingleInstance = False
Me.EnableVisualStyles = True
Me.SaveMySettingsOnExit = True
Me.ShutDownStyle = ShutdownMode.AfterMainFormCloses
End Sub
Protected Overrides Sub OnCreateMainForm()
Me.MainForm = My.Forms.MainForm
End Sub
End Class
End Namespace";
RunFormatTest(code, expected);
}
[Test]
public void ArrayInitializerTest()
{
string expected = @"Public Class Test
Private Sub Tester()
test(asdf, _
asdf, _
@ -86,11 +157,24 @@ End Class"; @@ -86,11 +157,24 @@ End Class";
asdf)
Dim test As Integer() = { _
2,2,3,34,4,5 _
2,2,3,34,4,5 _
}
End Sub
End Class";
string code = @"Public Class Test
Private Sub Tester()
test(asdf, _
asdf, _
asdf, _
asdf)
Dim test As Integer() = { _
2,2,3,34,4,5 _
}
End Sub
End Class";
RunFormatTest(code, expected);
}
@ -177,7 +261,7 @@ End Class"; @@ -177,7 +261,7 @@ End Class";
[Test]
public void SelectCaseTest()
{
string expected = @"Public Class Test
string expected = @"Public Class Test
Private Sub Tester()
Select Case a
Case 0
@ -215,7 +299,7 @@ End Class"; @@ -215,7 +299,7 @@ End Class";
[Test]
public void SelectCaseTest2()
{
string expected = @"Public Class Test
string expected = @"Public Class Test
Private Sub Tester()
Select Case a
Case 0
@ -247,7 +331,7 @@ End Class"; @@ -247,7 +331,7 @@ End Class";
[Test]
public void WithTest()
{
string expected = @"Public Class Test
string expected = @"Public Class Test
Private Sub Tester()
With a
If True Then
@ -281,7 +365,7 @@ End Class"; @@ -281,7 +365,7 @@ End Class";
[Test]
public void WithTest2()
{
string expected = @"Public Class Test
string expected = @"Public Class Test
Private Sub Tester()
With a
If True Then

Loading…
Cancel
Save