From a1a649e84e0ebfd6a12d6ddb6be1fd3e13dcf15d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 4 Sep 2011 12:02:04 +0200 Subject: [PATCH] Remove ITextEditorAdapter and use IDocument instead. --- .../Formatter/AstFormattingVisitor.cs | 197 +++++++------ .../Formatter/ITextEditorAdapter.cs | 83 ------ .../ICSharpCode.NRefactory.CSharp.csproj | 1 - .../Refactoring/NodeOutputAction.cs | 27 +- .../FormattingTests/TestFormattingBugs.cs | 8 +- .../FormattingTests/TestSpacingVisitor.cs | 160 +++++------ .../FormattingTests/TextEditorTestAdapter.cs | 262 ++---------------- .../Editor/IDocumentLine.cs | 10 + ICSharpCode.NRefactory/Editor/ISegment.cs | 2 +- .../Editor/ReadOnlyDocument.cs | 18 ++ 10 files changed, 256 insertions(+), 512 deletions(-) delete mode 100644 ICSharpCode.NRefactory.CSharp/Formatter/ITextEditorAdapter.cs diff --git a/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs b/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs index 99b8f67a3e..e69cbe4abf 100644 --- a/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs @@ -27,6 +27,7 @@ using System; using System.Text; using System.Collections.Generic; using System.Linq; +using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.CSharp.Refactoring; @@ -35,7 +36,7 @@ namespace ICSharpCode.NRefactory.CSharp public class AstFormattingVisitor : DepthFirstAstVisitor { CSharpFormattingOptions policy; - ITextEditorAdapter data; + IDocument document; IActionFactory factory; List changes = new List (); Indent curIndent = new Indent (); @@ -67,16 +68,20 @@ namespace ICSharpCode.NRefactory.CSharp get; set; } + + public string EolMarker { get; set; } - public AstFormattingVisitor (CSharpFormattingOptions policy, ITextEditorAdapter data, IActionFactory factory) + public AstFormattingVisitor (CSharpFormattingOptions policy, IDocument document, IActionFactory factory, + bool tabsToSpaces = false, int indentationSize = 4) { if (factory == null) throw new ArgumentNullException ("factory"); this.policy = policy; - this.data = data; - this.curIndent.TabsToSpaces = this.data.TabsToSpaces; - this.curIndent.TabSize = this.data.TabSize; + this.document = document; + this.curIndent.TabsToSpaces = tabsToSpaces; + this.curIndent.TabSize = indentationSize; this.factory = factory; + this.EolMarker = Environment.NewLine; CorrectBlankLines = true; } @@ -94,21 +99,23 @@ namespace ICSharpCode.NRefactory.CSharp int line = loc.Line; do { line++; - } while (line < data.LineCount && data.GetEditableLength (line) == data.GetIndentation (line).Length); - var start = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column); + } while (line < document.LineCount && IsSpacing(document.GetLineByNumber(line))); + var start = document.GetOffset (node.EndLocation); int foundBlankLines = line - loc.Line - 1; StringBuilder sb = new StringBuilder (); for (int i = 0; i < blankLines - foundBlankLines; i++) - sb.Append (data.EolMarker); + sb.Append (this.EolMarker); int ws = start; - while (ws < data.Length && IsSpacing (data.GetCharAt (ws))) + while (ws < document.TextLength && IsSpacing (document.GetCharAt (ws))) ws++; int removedChars = ws - start; - if (foundBlankLines > blankLines) - removedChars += data.GetLineEndOffset (loc.Line + foundBlankLines - blankLines) - data.GetLineEndOffset (loc.Line); + if (foundBlankLines > blankLines) { + removedChars += document.GetLineByNumber (loc.Line + foundBlankLines - blankLines).EndOffset + - document.GetLineByNumber (loc.Line).EndOffset; + } AddChange (start, removedChars, sb.ToString ()); } @@ -120,12 +127,12 @@ namespace ICSharpCode.NRefactory.CSharp int line = loc.Line; do { line--; - } while (line > 0 && data.GetEditableLength (line) == data.GetIndentation (line).Length); - int end = data.GetLineOffset (loc.Line); - int start = line >= 1 ? data.GetLineEndOffset (line) : 0; + } while (line > 0 && IsSpacing(document.GetLineByNumber(line))); + int end = document.GetOffset (loc.Line, 1); + int start = document.GetOffset (line + 1, 1); StringBuilder sb = new StringBuilder (); for (int i = 0; i < blankLines; i++) - sb.Append (data.EolMarker); + sb.Append (this.EolMarker); AddChange (start, end - start, sb.ToString ()); } @@ -216,6 +223,16 @@ namespace ICSharpCode.NRefactory.CSharp { return ch == ' ' || ch == '\t'; } + + bool IsSpacing (ISegment segment) + { + int endOffset = segment.EndOffset; + for (int i = segment.Offset; i < endOffset; i++) { + if (!IsSpacing(document.GetCharAt(i))) + return false; + } + return true; + } int SearchLastNonWsChar (int startOffset, int endOffset) { @@ -226,18 +243,18 @@ namespace ICSharpCode.NRefactory.CSharp int result = -1; bool inComment = false; - for (int i = startOffset; i < endOffset && i < data.Length; i++) { - char ch = data.GetCharAt (i); + for (int i = startOffset; i < endOffset && i < document.TextLength; i++) { + char ch = document.GetCharAt (i); if (IsSpacing (ch)) continue; - if (ch == '/' && i + 1 < data.Length && data.GetCharAt (i + 1) == '/') + if (ch == '/' && i + 1 < document.TextLength && document.GetCharAt (i + 1) == '/') return result; - if (ch == '/' && i + 1 < data.Length && data.GetCharAt (i + 1) == '*') { + if (ch == '/' && i + 1 < document.TextLength && document.GetCharAt (i + 1) == '*') { inComment = true; i++; continue; } - if (inComment && ch == '*' && i + 1 < data.Length && data.GetCharAt (i + 1) == '/') { + if (inComment && ch == '*' && i + 1 < document.TextLength && document.GetCharAt (i + 1) == '/') { inComment = false; i++; continue; @@ -271,11 +288,11 @@ namespace ICSharpCode.NRefactory.CSharp if (n == null) return; TextLocation location = n.EndLocation; - int offset = data.LocationToOffset (location.Line, location.Column); - if (location.Column > data.GetEditableLength (location.Line)) + int offset = document.GetOffset (location); + if (location.Column > document.GetLineByNumber (location.Line).Length) return; int i = offset; - while (i < data.Length && IsSpacing (data.GetCharAt (i))) { + while (i < document.TextLength && IsSpacing (document.GetCharAt (i))) { i++; } ForceSpace (offset - 1, i, forceSpaces); @@ -303,12 +320,12 @@ namespace ICSharpCode.NRefactory.CSharp return 0; TextLocation location = n.StartLocation; // respect manual line breaks. - if (location.Column <= 1 || data.GetIndentation (location.Line).Length == location.Column - 1) + if (location.Column <= 1 || GetIndentation (location.Line).Length == location.Column - 1) return 0; - int offset = data.LocationToOffset (location.Line, location.Column); + int offset = document.GetOffset (location); int i = offset - 1; - while (i >= 0 && IsSpacing (data.GetCharAt (i))) { + while (i >= 0 && IsSpacing (document.GetCharAt (i))) { i--; } ForceSpace (i, offset, forceSpaces); @@ -337,14 +354,14 @@ namespace ICSharpCode.NRefactory.CSharp case PropertyFormatting.ForceOneLine: isSimple = IsSimpleAccessor (propertyDeclaration.Getter) && IsSimpleAccessor (propertyDeclaration.Setter); if (isSimple) { - int offset = this.data.LocationToOffset (propertyDeclaration.LBraceToken.StartLocation.Line, propertyDeclaration.LBraceToken.StartLocation.Column); + int offset = this.document.GetOffset (propertyDeclaration.LBraceToken.StartLocation); int start = SearchWhitespaceStart (offset); int end = SearchWhitespaceEnd (offset); AddChange (start, offset - start, " "); AddChange (offset + 1, end - offset - 2, " "); - offset = this.data.LocationToOffset (propertyDeclaration.RBraceToken.StartLocation.Line, propertyDeclaration.RBraceToken.StartLocation.Column); + offset = this.document.GetOffset (propertyDeclaration.RBraceToken.StartLocation); start = SearchWhitespaceStart (offset); AddChange (start, offset - start, " "); oneLine = true; @@ -360,15 +377,15 @@ namespace ICSharpCode.NRefactory.CSharp if (!propertyDeclaration.Getter.IsNull) { if (!oneLine) { if (!IsLineIsEmptyUpToEol (propertyDeclaration.Getter.StartLocation)) { - int offset = this.data.LocationToOffset (propertyDeclaration.Getter.StartLocation.Line, propertyDeclaration.Getter.StartLocation.Column); + int offset = this.document.GetOffset (propertyDeclaration.Getter.StartLocation); int start = SearchWhitespaceStart (offset); string indentString = this.curIndent.IndentString; - AddChange (start, offset - start, this.data.EolMarker + indentString); + AddChange (start, offset - start, this.EolMarker + indentString); } else { FixIndentation (propertyDeclaration.Getter.StartLocation); } } else { - int offset = this.data.LocationToOffset (propertyDeclaration.Getter.StartLocation.Line, propertyDeclaration.Getter.StartLocation.Column); + int offset = this.document.GetOffset (propertyDeclaration.Getter.StartLocation); int start = SearchWhitespaceStart (offset); AddChange (start, offset - start, " "); @@ -388,15 +405,15 @@ namespace ICSharpCode.NRefactory.CSharp if (!propertyDeclaration.Setter.IsNull) { if (!oneLine) { if (!IsLineIsEmptyUpToEol (propertyDeclaration.Setter.StartLocation)) { - int offset = this.data.LocationToOffset (propertyDeclaration.Setter.StartLocation.Line, propertyDeclaration.Setter.StartLocation.Column); + int offset = this.document.GetOffset (propertyDeclaration.Setter.StartLocation); int start = SearchWhitespaceStart (offset); string indentString = this.curIndent.IndentString; - AddChange (start, offset - start, this.data.EolMarker + indentString); + AddChange (start, offset - start, this.EolMarker + indentString); } else { FixIndentation (propertyDeclaration.Setter.StartLocation); } } else { - int offset = this.data.LocationToOffset (propertyDeclaration.Setter.StartLocation.Line, propertyDeclaration.Setter.StartLocation.Column); + int offset = this.document.GetOffset (propertyDeclaration.Setter.StartLocation); int start = SearchWhitespaceStart (offset); AddChange (start, offset - start, " "); @@ -677,7 +694,7 @@ namespace ICSharpCode.NRefactory.CSharp FixIndentationForceNewLine (destructorDeclaration.StartLocation); CSharpTokenNode lParen = destructorDeclaration.LParToken; - int offset = this.data.LocationToOffset (lParen.StartLocation.Line, lParen.StartLocation.Column); + int offset = this.document.GetOffset (lParen.StartLocation); ForceSpaceBefore (offset, policy.SpaceBeforeConstructorDeclarationParentheses); object result = null; @@ -786,9 +803,9 @@ namespace ICSharpCode.NRefactory.CSharp case BraceForcement.AddBraces: if (!isBlock) { AstNode n = node.Parent.GetCSharpNodeBefore (node); - int start = data.LocationToOffset (n.EndLocation.Line, n.EndLocation.Column); + int start = document.GetOffset (n.EndLocation); var next = n.GetNextNode (); - int offset = data.LocationToOffset (next.StartLocation.Line, next.StartLocation.Column); + int offset = document.GetOffset (next.StartLocation); string startBrace = ""; switch (braceStyle) { case BraceStyle.EndOfLineWithoutSpace: @@ -798,15 +815,15 @@ namespace ICSharpCode.NRefactory.CSharp startBrace = " {"; break; case BraceStyle.NextLine: - startBrace = data.EolMarker + curIndent.IndentString + "{"; + startBrace = this.EolMarker + curIndent.IndentString + "{"; break; case BraceStyle.NextLineShifted2: case BraceStyle.NextLineShifted: - startBrace = data.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "{"; + startBrace = this.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "{"; break; } - if (IsLineIsEmptyUpToEol (data.LocationToOffset (node.StartLocation.Line, node.StartLocation.Column))) - startBrace += data.EolMarker + data.GetIndentation (node.StartLocation.Line); + if (IsLineIsEmptyUpToEol (document.GetOffset (node.StartLocation))) + startBrace += this.EolMarker + GetIndentation (node.StartLocation.Line); AddChange (start, offset - start, startBrace); } break; @@ -814,10 +831,10 @@ namespace ICSharpCode.NRefactory.CSharp if (isBlock) { BlockStatement block = node as BlockStatement; if (block.Statements.Count () == 1) { - int offset1 = data.LocationToOffset (node.StartLocation.Line, node.StartLocation.Column); + int offset1 = document.GetOffset (node.StartLocation); int start = SearchWhitespaceStart (offset1); - int offset2 = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column); + int offset2 = document.GetOffset (node.EndLocation); int end = SearchWhitespaceStart (offset2 - 1); AddChange (start, offset1 - start + 1, null); @@ -853,8 +870,8 @@ namespace ICSharpCode.NRefactory.CSharp break; case BraceForcement.AddBraces: if (!isBlock) { - int offset = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column); - if (!char.IsWhiteSpace (data.GetCharAt (offset))) + int offset = document.GetOffset (node.EndLocation); + if (!char.IsWhiteSpace (document.GetCharAt (offset))) offset++; string startBrace = ""; switch (braceStyle) { @@ -862,17 +879,17 @@ namespace ICSharpCode.NRefactory.CSharp startBrace = null; break; case BraceStyle.EndOfLineWithoutSpace: - startBrace = data.EolMarker + curIndent.IndentString + "}"; + startBrace = this.EolMarker + curIndent.IndentString + "}"; break; case BraceStyle.EndOfLine: - startBrace = data.EolMarker + curIndent.IndentString + "}"; + startBrace = this.EolMarker + curIndent.IndentString + "}"; break; case BraceStyle.NextLine: - startBrace = data.EolMarker + curIndent.IndentString + "}"; + startBrace = this.EolMarker + curIndent.IndentString + "}"; break; case BraceStyle.NextLineShifted2: case BraceStyle.NextLineShifted: - startBrace = data.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "}"; + startBrace = this.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "}"; break; } if (startBrace != null) @@ -889,10 +906,10 @@ namespace ICSharpCode.NRefactory.CSharp return; // LineSegment lbraceLineSegment = data.Document.GetLine (lbrace.StartLocation.Line); - int lbraceOffset = data.LocationToOffset (lbrace.StartLocation.Line, lbrace.StartLocation.Column); + int lbraceOffset = document.GetOffset (lbrace.StartLocation); // LineSegment rbraceLineSegment = data.Document.GetLine (rbrace.StartLocation.Line); - int rbraceOffset = data.LocationToOffset (rbrace.StartLocation.Line, rbrace.StartLocation.Column); + int rbraceOffset = document.GetOffset (rbrace.StartLocation); int whitespaceStart = SearchWhitespaceStart (lbraceOffset); int whitespaceEnd = SearchWhitespaceLineStart (rbraceOffset); string startIndent = ""; @@ -903,7 +920,7 @@ namespace ICSharpCode.NRefactory.CSharp break; case BraceStyle.EndOfLineWithoutSpace: startIndent = ""; - endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : data.EolMarker + curIndent.IndentString; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : this.EolMarker + curIndent.IndentString; break; case BraceStyle.EndOfLine: var prevNode = lbrace.GetPrevNode (); @@ -914,22 +931,22 @@ namespace ICSharpCode.NRefactory.CSharp while (prevNode is Comment) { prevNode = prevNode.GetPrevNode (); } - whitespaceStart = data.LocationToOffset (prevNode.EndLocation.Line, prevNode.EndLocation.Column); + whitespaceStart = document.GetOffset (prevNode.EndLocation); lbraceOffset = whitespaceStart; startIndent = " {"; } else { startIndent = " "; } - endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : data.EolMarker + curIndent.IndentString; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : this.EolMarker + curIndent.IndentString; break; case BraceStyle.NextLine: - startIndent = data.EolMarker + curIndent.IndentString; - endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : data.EolMarker + curIndent.IndentString; + startIndent = this.EolMarker + curIndent.IndentString; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : this.EolMarker + curIndent.IndentString; break; case BraceStyle.NextLineShifted2: case BraceStyle.NextLineShifted: - startIndent = data.EolMarker + curIndent.IndentString + curIndent.SingleIndent; - endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString + curIndent.SingleIndent : data.EolMarker + curIndent.IndentString + curIndent.SingleIndent; + startIndent = this.EolMarker + curIndent.IndentString + curIndent.SingleIndent; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString + curIndent.SingleIndent : this.EolMarker + curIndent.IndentString + curIndent.SingleIndent; break; } @@ -944,7 +961,7 @@ namespace ICSharpCode.NRefactory.CSharp if (changes.Any (c => c.Offset == offset && c.RemovedChars == removedChars && c.InsertedText == insertedText)) return; - string currentText = data.GetTextAt (offset, removedChars); + string currentText = document.GetText (offset, removedChars); if (currentText == insertedText) return; if (currentText.Any (c => !(char.IsWhiteSpace (c) || c == '\r' || c == '\t' || c == '{' || c == '}'))) @@ -973,13 +990,13 @@ namespace ICSharpCode.NRefactory.CSharp public bool IsLineIsEmptyUpToEol (TextLocation startLocation) { - return IsLineIsEmptyUpToEol (data.LocationToOffset (startLocation.Line, startLocation.Column) - 1); + return IsLineIsEmptyUpToEol (document.GetOffset (startLocation) - 1); } bool IsLineIsEmptyUpToEol (int startOffset) { for (int offset = startOffset - 1; offset >= 0; offset--) { - char ch = data.GetCharAt (offset); + char ch = document.GetCharAt (offset); if (ch != ' ' && ch != '\t') return ch == '\n' || ch == '\r'; } @@ -991,7 +1008,7 @@ namespace ICSharpCode.NRefactory.CSharp if (startOffset < 0) throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); for (int offset = startOffset - 1; offset >= 0; offset--) { - char ch = data.GetCharAt (offset); + char ch = document.GetCharAt (offset); if (!Char.IsWhiteSpace (ch)) { return offset + 1; } @@ -1001,15 +1018,15 @@ namespace ICSharpCode.NRefactory.CSharp int SearchWhitespaceEnd (int startOffset) { - if (startOffset > data.Length) + if (startOffset > document.TextLength) throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); - for (int offset = startOffset + 1; offset < data.Length; offset++) { - char ch = data.GetCharAt (offset); + for (int offset = startOffset + 1; offset < document.TextLength; offset++) { + char ch = document.GetCharAt (offset); if (!Char.IsWhiteSpace (ch)) { return offset + 1; } } - return data.Length - 1; + return document.TextLength - 1; } int SearchWhitespaceLineStart (int startOffset) @@ -1017,7 +1034,7 @@ namespace ICSharpCode.NRefactory.CSharp if (startOffset < 0) throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); for (int offset = startOffset - 1; offset >= 0; offset--) { - char ch = data.GetCharAt (offset); + char ch = document.GetCharAt (offset); if (ch != ' ' && ch != '\t') { return offset + 1; } @@ -1466,7 +1483,7 @@ namespace ICSharpCode.NRefactory.CSharp { bool insertedSpace = false; do { - char ch = data.GetCharAt (offset); + char ch = document.GetCharAt (offset); //Console.WriteLine (ch); if (!IsSpacing (ch) && (insertedSpace || !forceSpace)) break; @@ -1524,9 +1541,9 @@ namespace ICSharpCode.NRefactory.CSharp { if (semicolon.IsNull) return; - int endOffset = data.LocationToOffset (semicolon.StartLocation.Line, semicolon.StartLocation.Column); + int endOffset = document.GetOffset (semicolon.StartLocation); int offset = endOffset; - while (offset - 1 > 0 && char.IsWhiteSpace (data.GetCharAt (offset - 1))) { + while (offset - 1 > 0 && char.IsWhiteSpace (document.GetCharAt (offset - 1))) { offset--; } if (offset < endOffset) { @@ -1538,10 +1555,10 @@ namespace ICSharpCode.NRefactory.CSharp { if (keywordNode == null) return; - int offset = data.LocationToOffset (keywordNode.StartLocation.Line, keywordNode.StartLocation.Column); + int offset = document.GetOffset (keywordNode.StartLocation); int whitespaceStart = SearchWhitespaceStart (offset); - string indentString = newLine ? data.EolMarker + this.curIndent.IndentString : " "; + string indentString = newLine ? this.EolMarker + this.curIndent.IndentString : " "; AddChange (whitespaceStart, offset - whitespaceStart, indentString); } @@ -1549,7 +1566,7 @@ namespace ICSharpCode.NRefactory.CSharp void FixStatementIndentation (TextLocation location) { - int offset = data.LocationToOffset (location.Line, location.Column); + int offset = document.GetOffset (location); if (offset <= 0) { Console.WriteLine ("possible wrong offset"); Console.WriteLine (Environment.StackTrace); @@ -1557,7 +1574,7 @@ namespace ICSharpCode.NRefactory.CSharp } bool isEmpty = IsLineIsEmptyUpToEol (offset); int lineStart = SearchWhitespaceLineStart (offset); - string indentString = nextStatementIndent == null ? (isEmpty ? "" : data.EolMarker) + this.curIndent.IndentString : nextStatementIndent; + string indentString = nextStatementIndent == null ? (isEmpty ? "" : this.EolMarker) + this.curIndent.IndentString : nextStatementIndent; nextStatementIndent = null; AddChange (lineStart, offset - lineStart, indentString); } @@ -1569,40 +1586,54 @@ namespace ICSharpCode.NRefactory.CSharp void FixIndentation (TextLocation location, int relOffset) { - if (location.Line < 1 || location.Line > data.LineCount) { + if (location.Line < 1 || location.Line > document.LineCount) { Console.WriteLine ("Invalid location " + location); Console.WriteLine (Environment.StackTrace); return; } - string lineIndent = data.GetIndentation (location.Line); + string lineIndent = GetIndentation (location.Line); string indentString = this.curIndent.IndentString; if (indentString != lineIndent && location.Column - 1 + relOffset == lineIndent.Length) { - AddChange (data.GetLineOffset (location.Line), lineIndent.Length, indentString); + AddChange (document.GetOffset (location.Line, 1), lineIndent.Length, indentString); } } void FixIndentationForceNewLine (TextLocation location) { - string lineIndent = data.GetIndentation (location.Line); + string lineIndent = GetIndentation (location.Line); string indentString = this.curIndent.IndentString; if (location.Column - 1 == lineIndent.Length) { - AddChange (data.GetLineOffset (location.Line), lineIndent.Length, indentString); + AddChange (document.GetOffset (location.Line, 1), lineIndent.Length, indentString); } else { - int offset = data.LocationToOffset (location.Line, location.Column); + int offset = document.GetOffset (location); int start = SearchWhitespaceLineStart (offset); if (start > 0) { - char ch = data.GetCharAt (start - 1); + char ch = document.GetCharAt (start - 1); if (ch == '\n') { start--; - if (start > 1 && data.GetCharAt (start - 1) == '\r') + if (start > 1 && document.GetCharAt (start - 1) == '\r') start--; } else if (ch == '\r') { start--; } - AddChange (start, offset - start, data.EolMarker + indentString); + AddChange (start, offset - start, this.EolMarker + indentString); } } } + + string GetIndentation(int lineNumber) + { + IDocumentLine line = document.GetLineByNumber(lineNumber); + StringBuilder b = new StringBuilder(); + int endOffset = line.EndOffset; + for (int i = line.Offset; i < endOffset; i++) { + char c = document.GetCharAt(i); + if (!IsSpacing(c)) + break; + b.Append(c); + } + return b.ToString(); + } } } diff --git a/ICSharpCode.NRefactory.CSharp/Formatter/ITextEditorAdapter.cs b/ICSharpCode.NRefactory.CSharp/Formatter/ITextEditorAdapter.cs deleted file mode 100644 index 4568f8736e..0000000000 --- a/ICSharpCode.NRefactory.CSharp/Formatter/ITextEditorAdapter.cs +++ /dev/null @@ -1,83 +0,0 @@ -// -// ITextEditorAdapter.cs -// -// Author: -// Mike Krüger -// -// Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Collections.Generic; - -namespace ICSharpCode.NRefactory -{ - public interface ITextEditorAdapter - { - bool TabsToSpaces { get; } - - int TabSize { get; } - - string EolMarker { get; } - - string Text { get; } - - int Length { get; } - - int LocationToOffset (int line, int col); - char GetCharAt (int offset); - string GetTextAt (int offset, int length); - - int LineCount { get; } - - int GetEditableLength (int lineNumber); - string GetIndentation (int lineNumber); - int GetLineOffset (int lineNumber); - int GetLineLength (int lineNumber); - int GetLineEndOffset (int lineNumber); - - void Replace (int offset, int count, string text); - } - - /* - public static class ITextEditorAdapterHelperMethods - { - public static void AcceptChanges (this ITextEditorAdapter adapter, List changes) - { - for (int i = 0; i < changes.Count; i++) { - changes [i].PerformChange (adapter); - var replaceChange = changes [i]; - for (int j = i + 1; j < changes.Count; j++) { - var change = changes [j]; - if (replaceChange.Offset >= 0 && change.Offset >= 0) { - if (replaceChange.Offset < change.Offset) { - change.Offset -= replaceChange.RemovedChars; - if (!string.IsNullOrEmpty (replaceChange.InsertedText)) - change.Offset += replaceChange.InsertedText.Length; - } else if (replaceChange.Offset < change.Offset + change.RemovedChars) { - change.RemovedChars -= replaceChange.RemovedChars; - change.Offset = replaceChange.Offset + (!string.IsNullOrEmpty (replaceChange.InsertedText) ? replaceChange.InsertedText.Length : 0); - } - } - } - } - } - }*/ -} - diff --git a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj index b5b2450cb3..7be6865e41 100644 --- a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj +++ b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj @@ -164,7 +164,6 @@ - diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/NodeOutputAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/NodeOutputAction.cs index 47d5e7ba70..fd0e81a4fc 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/NodeOutputAction.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/NodeOutputAction.cs @@ -1,4 +1,4 @@ -// +// // NodeOutputChange.cs // // Author: @@ -26,6 +26,7 @@ using System; using System.Collections.Generic; +using ICSharpCode.NRefactory.Editor; namespace ICSharpCode.NRefactory.CSharp.Refactoring { @@ -109,28 +110,4 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring this.NodeOutput = output; } } - - - /// - /// An (Offset,Length)-pair. - /// - public interface ISegment - { - /// - /// Gets the start offset of the segment. - /// - int Offset { get; } - - /// - /// Gets the length of the segment. - /// - /// Must not be negative. - int Length { get; } - - /// - /// Gets the end offset of the segment. - /// - /// EndOffset = Offset + Length; - int EndOffset { get; } - } } diff --git a/ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs b/ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs index 8e667542e7..0b2184ccfc 100644 --- a/ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs +++ b/ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs @@ -1,4 +1,4 @@ -// +// // TestFormattingBugs.cs // // Author: @@ -131,9 +131,9 @@ using (IDisposable b = null) { " + input + @" } }"); - int start = result.GetLineOffset (5); - int end = result.GetLineOffset (result.LineCount - 1); - string text = result.GetTextAt (start, end - start).Trim (); + int start = result.GetOffset (5, 1); + int end = result.GetOffset (result.LineCount - 1, 1); + string text = result.GetText (start, end - start).Trim (); expectedOutput = expectedOutput.Replace ("\n", "\n\t\t"); Assert.AreEqual (expectedOutput, text); } diff --git a/ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs b/ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs index 87d61ee511..3f0c236024 100644 --- a/ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs +++ b/ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs @@ -1,4 +1,4 @@ -// +// // TestFormattingVisitor.cs // // Author: @@ -142,7 +142,7 @@ namespace ICSharpCode.NRefactory.FormattingTests int i2 = result.Text.IndexOf ("right") + "right".Length; if (i1 < 0 || i2 < 0) Assert.Fail ("text invalid:" + result.Text); - Assert.AreEqual ("left " + op + " right", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual ("left " + op + " right", result.GetText (i1, i2 - i1)); } [Test()] @@ -234,7 +234,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("condition"); int i2 = result.Text.IndexOf ("falseexpr") + "falseexpr".Length; - Assert.AreEqual (@"condition ? trueexpr : falseexpr", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"condition ? trueexpr : falseexpr", result.GetText (i1, i2 - i1)); policy.SpaceBeforeConditionalOperatorCondition = false; @@ -250,7 +250,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); i1 = result.Text.IndexOf ("true"); i2 = result.Text.IndexOf ("falseexpr") + "falseexpr".Length; - Assert.AreEqual (@"true?trueexpr:falseexpr", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"true?trueexpr:falseexpr", result.GetText (i1, i2 - i1)); } [Test()] @@ -268,7 +268,7 @@ namespace ICSharpCode.NRefactory.FormattingTests int i1 = result.Text.IndexOf ("MethodCall"); int i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"MethodCall ();", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"MethodCall ();", result.GetText (i1, i2 - i1)); result = GetResult (policy, @"class Test { @@ -282,7 +282,7 @@ namespace ICSharpCode.NRefactory.FormattingTests result = GetResult (policy, result.Text); i1 = result.Text.IndexOf ("MethodCall"); i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"MethodCall();", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"MethodCall();", result.GetText (i1, i2 - i1)); } [Test()] @@ -299,7 +299,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( true )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( true )", result.GetText (i1, i2 - i1)); policy.SpaceWithinMethodCallParentheses = false; @@ -312,7 +312,7 @@ namespace ICSharpCode.NRefactory.FormattingTests i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(true)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(true)", result.GetText (i1, i2 - i1)); } [Test()] @@ -329,7 +329,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("if"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"if (true)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"if (true)", result.GetText (i1, i2 - i1)); } [Test()] @@ -346,7 +346,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( true )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( true )", result.GetText (i1, i2 - i1)); } [Test()] @@ -363,7 +363,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("while"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"while (true)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"while (true)", result.GetText (i1, i2 - i1)); } [Test()] @@ -381,7 +381,7 @@ namespace ICSharpCode.NRefactory.FormattingTests int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( true )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( true )", result.GetText (i1, i2 - i1)); } [Test()] @@ -398,7 +398,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("for"); int i2 = result.Text.LastIndexOf ("(") + "(".Length; - Assert.AreEqual (@"for (", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"for (", result.GetText (i1, i2 - i1)); } [Test()] @@ -415,7 +415,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( ;; )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( ;; )", result.GetText (i1, i2 - i1)); } [Test()] @@ -432,7 +432,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("foreach"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"foreach (var o in list)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"foreach (var o in list)", result.GetText (i1, i2 - i1)); } [Test()] @@ -449,7 +449,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( var o in list )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( var o in list )", result.GetText (i1, i2 - i1)); } [Test()] @@ -466,7 +466,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("catch"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"catch (Exception)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"catch (Exception)", result.GetText (i1, i2 - i1)); } [Test()] @@ -483,7 +483,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( Exception )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( Exception )", result.GetText (i1, i2 - i1)); } [Test()] @@ -500,7 +500,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("lock"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"lock (this)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"lock (this)", result.GetText (i1, i2 - i1)); } [Test()] @@ -517,7 +517,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( this )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( this )", result.GetText (i1, i2 - i1)); } [Test()] @@ -535,7 +535,7 @@ namespace ICSharpCode.NRefactory.FormattingTests int i1 = result.Text.LastIndexOf ("for"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"for (int i; true; i++)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"for (int i; true; i++)", result.GetText (i1, i2 - i1)); } [Test()] @@ -554,7 +554,7 @@ namespace ICSharpCode.NRefactory.FormattingTests int i1 = result.Text.LastIndexOf ("for"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"for (int i ;true ;i++)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"for (int i ;true ;i++)", result.GetText (i1, i2 - i1)); } [Test()] @@ -572,7 +572,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("return"); int i2 = result.Text.LastIndexOf ("null") + "null".Length; - Assert.AreEqual (@"return (Test) null", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"return (Test) null", result.GetText (i1, i2 - i1)); } [Test()] @@ -589,7 +589,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("using"); int i2 = result.Text.LastIndexOf ("(") + "(".Length; - Assert.AreEqual (@"using (", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"using (", result.GetText (i1, i2 - i1)); } [Test()] @@ -606,7 +606,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( a )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( a )", result.GetText (i1, i2 - i1)); } static void TestAssignmentOperator (CSharpFormattingOptions policy, string op) @@ -617,7 +617,7 @@ return (Test)null; int i2 = result.Text.IndexOf ("right") + "right".Length; if (i1 < 0 || i2 < 0) Assert.Fail ("text invalid:" + result.Text); - Assert.AreEqual ("left " + op + " right", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual ("left " + op + " right", result.GetText (i1, i2 - i1)); } [Test()] @@ -653,7 +653,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("left"); int i2 = result.Text.LastIndexOf ("right") + "right".Length; - Assert.AreEqual (@"left = right", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"left = right", result.GetText (i1, i2 - i1)); } [Test()] @@ -670,7 +670,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("switch"); int i2 = result.Text.LastIndexOf ("(") + "(".Length; - Assert.AreEqual (@"switch (", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"switch (", result.GetText (i1, i2 - i1)); } [Test()] @@ -687,7 +687,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( test )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( test )", result.GetText (i1, i2 - i1)); } [Test()] @@ -704,7 +704,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( test )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( test )", result.GetText (i1, i2 - i1)); } [Test()] @@ -720,7 +720,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( int a )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( int a )", result.GetText (i1, i2 - i1)); } [Test()] @@ -737,7 +737,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( int )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( int )", result.GetText (i1, i2 - i1)); } [Test()] @@ -754,7 +754,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( int )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( int )", result.GetText (i1, i2 - i1)); } [Test()] @@ -771,7 +771,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("sizeof"); int i2 = result.Text.LastIndexOf ("(") + "(".Length; - Assert.AreEqual (@"sizeof (", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"sizeof (", result.GetText (i1, i2 - i1)); } [Test()] @@ -788,7 +788,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( int )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( int )", result.GetText (i1, i2 - i1)); } [Test()] @@ -806,7 +806,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("typeof"); int i2 = result.Text.LastIndexOf ("(") + "(".Length; - Assert.AreEqual (@"typeof (", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"typeof (", result.GetText (i1, i2 - i1)); } [Test()] @@ -823,7 +823,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( a + b )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( a + b )", result.GetText (i1, i2 - i1)); result = GetResult (policy, @"class Test { void TestMe () @@ -835,7 +835,7 @@ return (Test)null; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( a + b )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( a + b )", result.GetText (i1, i2 - i1)); } [Test()] @@ -852,7 +852,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("new"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"new Test ();", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"new Test ();", result.GetText (i1, i2 - i1)); } [Test()] @@ -869,7 +869,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("new"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"new Test ( 1 );", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"new Test ( 1 );", result.GetText (i1, i2 - i1)); } [Test()] @@ -886,7 +886,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("new"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"new Test ( );", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"new Test ( );", result.GetText (i1, i2 - i1)); } [Test()] @@ -904,7 +904,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("new"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"new Test (1 ,2);", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"new Test (1 ,2);", result.GetText (i1, i2 - i1)); } [Test()] @@ -921,7 +921,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("new"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"new Test (1, 2);", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"new Test (1, 2);", result.GetText (i1, i2 - i1)); } [Test()] @@ -936,20 +936,20 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("int"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"int a, b, c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a, b, c;", result.GetText (i1, i2 - i1)); policy.SpaceBeforeFieldDeclarationComma = true; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("int"); i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"int a , b , c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a , b , c;", result.GetText (i1, i2 - i1)); policy.SpaceBeforeFieldDeclarationComma = false; policy.SpaceAfterFieldDeclarationComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("int"); i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"int a,b,c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a,b,c;", result.GetText (i1, i2 - i1)); } [Test()] @@ -964,13 +964,13 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a ,int b ,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a ,int b ,int c)", result.GetText (i1, i2 - i1)); policy.SpaceBeforeMethodDeclarationParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a,int b,int c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -985,13 +985,13 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a, int b, int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a, int b, int c)", result.GetText (i1, i2 - i1)); policy.SpaceAfterMethodDeclarationParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a,int b,int c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1008,7 +1008,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("x"); int i2 = result.Text.LastIndexOf ("null") + "null".Length; - Assert.AreEqual (@"x => x != null", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"x => x != null", result.GetText (i1, i2 - i1)); } [Test()] @@ -1026,7 +1026,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("int"); int i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"int a ,b ,c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a ,b ,c;", result.GetText (i1, i2 - i1)); result = GetResult (policy, result.Text); @@ -1035,7 +1035,7 @@ return (Test)null; result = GetResult (policy, result.Text); i1 = result.Text.IndexOf ("int"); i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"int a,b,c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a,b,c;", result.GetText (i1, i2 - i1)); } [Test()] @@ -1053,7 +1053,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("int"); int i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"int a = 5 , b = 6 , c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a = 5 , b = 6 , c;", result.GetText (i1, i2 - i1)); result = GetResult (policy, result.Text); @@ -1063,7 +1063,7 @@ return (Test)null; result = GetResult (policy, result.Text); i1 = result.Text.IndexOf ("int"); i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"int a = 5,b = 6,c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a = 5,b = 6,c;", result.GetText (i1, i2 - i1)); } [Test()] @@ -1081,7 +1081,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("List"); int i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"List a;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"List a;", result.GetText (i1, i2 - i1)); } @@ -1121,14 +1121,14 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a ,int b ,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a ,int b ,int c)", result.GetText (i1, i2 - i1)); policy.SpaceBeforeConstructorDeclarationParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a,int b,int c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1143,13 +1143,13 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a, int b, int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a, int b, int c)", result.GetText (i1, i2 - i1)); policy.SpaceAfterConstructorDeclarationParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a,int b,int c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1165,7 +1165,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( int a )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( int a )", result.GetText (i1, i2 - i1)); } [Test()] @@ -1181,7 +1181,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( )", result.GetText (i1, i2 - i1)); } #endregion @@ -1220,13 +1220,13 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a ,int b ,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a ,int b ,int c)", result.GetText (i1, i2 - i1)); policy.SpaceBeforeDelegateDeclarationParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a,int b,int c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1240,13 +1240,13 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a, int b, int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a, int b, int c)", result.GetText (i1, i2 - i1)); policy.SpaceAfterDelegateDeclarationParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a,int b,int c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1258,7 +1258,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( int a )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( int a )", result.GetText (i1, i2 - i1)); } [Test()] @@ -1270,7 +1270,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( )", result.GetText (i1, i2 - i1)); } #endregion @@ -1315,13 +1315,13 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(a ,b ,c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(a ,b ,c)", result.GetText (i1, i2 - i1)); policy.SpaceBeforeMethodCallParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(a,b,c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(a,b,c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1340,13 +1340,13 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(a, b, c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(a, b, c)", result.GetText (i1, i2 - i1)); policy.SpaceAfterMethodCallParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(a,b,c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(a,b,c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1364,7 +1364,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( a )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( a )", result.GetText (i1, i2 - i1)); } [Test()] @@ -1382,7 +1382,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( )", result.GetText (i1, i2 - i1)); } #endregion @@ -1430,7 +1430,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("["); int i2 = result.Text.LastIndexOf ("]") + "]".Length; - Assert.AreEqual (@"[int a ,int b]", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"[int a ,int b]", result.GetText (i1, i2 - i1)); } @@ -1450,7 +1450,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("["); int i2 = result.Text.LastIndexOf ("]") + "]".Length; - Assert.AreEqual (@"[int a, int b]", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"[int a, int b]", result.GetText (i1, i2 - i1)); } [Test()] @@ -1469,7 +1469,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("["); int i2 = result.Text.LastIndexOf ("]") + "]".Length; - Assert.AreEqual (@"[ int a, int b ]", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"[ int a, int b ]", result.GetText (i1, i2 - i1)); } #endregion @@ -1540,7 +1540,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("["); int i2 = result.Text.LastIndexOf ("]") + "]".Length; - Assert.AreEqual (@"[1 ,2 ,3]", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"[1 ,2 ,3]", result.GetText (i1, i2 - i1)); } [Test()] @@ -1558,7 +1558,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("["); int i2 = result.Text.LastIndexOf ("]") + "]".Length; - Assert.AreEqual (@"[1, 2, 3]", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"[1, 2, 3]", result.GetText (i1, i2 - i1)); } #endregion @@ -1595,7 +1595,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("Foo"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"Foo ();", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"Foo ();", result.GetText (i1, i2 - i1)); } } diff --git a/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs b/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs index a9cef844fb..b127d10529 100644 --- a/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs +++ b/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs @@ -1,218 +1,14 @@ using System; using System.Collections.Generic; +using System.Text; using ICSharpCode.NRefactory.CSharp; using System.IO; +using ICSharpCode.NRefactory.Editor; using NUnit.Framework; using ICSharpCode.NRefactory.CSharp.Refactoring; namespace ICSharpCode.NRefactory.FormattingTests { - /// - /// Text editor test adapter. Only implemented for testing purposes. Don't use in production code. - /// - class TextEditorTestAdapter : ITextEditorAdapter - { - string text; - - public string Text { - get { - return this.text; - } - } - - List delimiters; - - struct Delimiter - { - public readonly int Offset; - public readonly int Length; - - public int EndOffset { - get { return Offset + Length; } - } - - public Delimiter (int offset, int length) - { - Offset = offset; - Length = length; - } - - public override string ToString () - { - return string.Format ("[Delimiter: Offset={0}, Length={1}]", Offset, Length); - } - } - public void Replace (int offset, int count, string value) - { - this.text = this.text.Substring (0, offset) + value + this.text.Substring (offset + count); - } - static IEnumerable FindDelimiter (string text) - { - for (int i = 0; i < text.Length; i++) { - switch (text [i]) { - case '\r': - if (i + 1 < text.Length && text [i + 1] == '\n') { - yield return new Delimiter (i, 2); - i++; - } else { - yield return new Delimiter (i, 1); - } - break; - case '\n': - yield return new Delimiter (i, 1); - break; - } - } - } - - public TextEditorTestAdapter (string text) - { - this.text = text; - delimiters = new List (FindDelimiter (text)); - } - - class Segment - { - public readonly int Offset; - public readonly int Length; - public readonly int DelimiterLength; - - public Segment (int offset, int length, int delimiterLength) - { - this.Offset = offset; - this.Length = length; - this.DelimiterLength = delimiterLength; - } - - public override string ToString () - { - return string.Format ("[Segment: Offset={0}, Length={1}, DelimiterLength={2}]", Offset, Length, DelimiterLength); - } - } - - Segment Get (int number) - { - number--; - if (number < 0 || number - 1 >= delimiters.Count) - return null; - int startOffset = number > 0 ? delimiters [number - 1].EndOffset : 0; - int endOffset; - int delimiterLength; - if (number < delimiters.Count) { - endOffset = delimiters [number].EndOffset; - delimiterLength = delimiters [number].Length; - } else { - endOffset = text.Length; - delimiterLength = 0; - } - return new Segment (startOffset, endOffset - startOffset, delimiterLength); - } - - #region ITextEditorAdapter implementation - public int LocationToOffset (int line, int col) - { - Segment seg = Get (line); - if (seg == null) - return 0; - return seg.Offset + col - 1; - } - - public char GetCharAt (int offset) - { - if (offset < 0 || offset >= text.Length) - return '\0'; - return text [offset]; - } - - public string GetTextAt (int offset, int length) - { - if (offset < 0 || offset + length >= text.Length) - return ""; - if (length <= 0) - return ""; - - return text.Substring (offset, length); - } - - public int GetEditableLength (int lineNumber) - { - var seg = Get (lineNumber); - if (seg == null) - return 0; - return seg.Length - seg.DelimiterLength; - } - - public string GetIndentation (int lineNumber) - { - var seg = Get (lineNumber); - if (seg == null) - return ""; - int start = seg.Offset; - int end = seg.Offset; - int endOffset = seg.Offset + seg.Length - seg.DelimiterLength; - - while (end < endOffset && (text[end] == ' ' || text[end] == '\t')) - end++; - - return start < end ? text.Substring (start, end - start) : ""; - } - - public int GetLineOffset (int lineNumber) - { - var seg = Get (lineNumber); - if (seg == null) - return 0; - return seg.Offset; - } - - public int GetLineLength (int lineNumber) - { - var seg = Get (lineNumber); - if (seg == null) - return 0; - return seg.Length; - } - - public int GetLineEndOffset (int lineNumber) - { - var seg = Get (lineNumber); - if (seg == null) - return 0; - return seg.Offset + seg.Length; - } - - public bool TabsToSpaces { - get { - return false; - } - } - - public int TabSize { - get { - return 4; - } - } - - public string EolMarker { - get { - return Environment.NewLine; - } - } - - public int Length { - get { - return text.Length; - } - } - - public int LineCount { - get { - return delimiters.Count + 1; - } - } - #endregion - } - public abstract class TestBase { static IActionFactory factory = new TestFactory (); @@ -236,59 +32,55 @@ namespace ICSharpCode.NRefactory.FormattingTests } } - static void ApplyChanges (TextEditorTestAdapter adapter, List changes) + static string ApplyChanges (string text, List changes) { changes.Sort ((x, y) => y.Offset.CompareTo (x.Offset)); + StringBuilder b = new StringBuilder(text); foreach (var change in changes) { // Console.WriteLine ("---- apply:" + change); // Console.WriteLine (adapter.Text); - if (change.Offset > adapter.Length) + if (change.Offset > b.Length) continue; - adapter.Replace (change.Offset, change.RemovedChars, change.InsertedText); + b.Remove(change.Offset, change.RemovedChars); + b.Insert(change.Offset, change.InsertedText); } // Console.WriteLine ("---result:"); // Console.WriteLine (adapter.Text); + return b.ToString(); } - protected static ITextEditorAdapter GetResult (CSharpFormattingOptions policy, string input) + protected static IDocument GetResult (CSharpFormattingOptions policy, string input) { - var adapter = new TextEditorTestAdapter (input); - var visitior = new AstFormattingVisitor (policy, adapter, factory); + var adapter = new ReadOnlyDocument (input); + var visitor = new AstFormattingVisitor (policy, adapter, factory); - var compilationUnit = new CSharpParser ().Parse (new StringReader (adapter.Text)); - compilationUnit.AcceptVisitor (visitior, null); + var compilationUnit = new CSharpParser ().Parse (new StringReader (input)); + compilationUnit.AcceptVisitor (visitor, null); - ApplyChanges (adapter, visitior.Changes); - - return adapter; + return new ReadOnlyDocument(ApplyChanges (input, visitor.Changes)); } - protected static ITextEditorAdapter Test (CSharpFormattingOptions policy, string input, string expectedOutput) + protected static IDocument Test (CSharpFormattingOptions policy, string input, string expectedOutput) { - var adapter = new TextEditorTestAdapter (input); - var visitior = new AstFormattingVisitor (policy, adapter, factory); - - var compilationUnit = new CSharpParser ().Parse (new StringReader (adapter.Text)); - compilationUnit.AcceptVisitor (visitior, null); - ApplyChanges (adapter, visitior.Changes); - if (expectedOutput != adapter.Text) { - Console.WriteLine (adapter.Text); + IDocument doc = GetResult(policy, input); + if (expectedOutput != doc.Text) { + Console.WriteLine (doc.Text); } - Assert.AreEqual (expectedOutput, adapter.Text); - return adapter; + Assert.AreEqual (expectedOutput, doc.Text); + return doc; } - protected static void Continue (CSharpFormattingOptions policy, ITextEditorAdapter adapter, string expectedOutput) + protected static void Continue (CSharpFormattingOptions policy, IDocument document, string expectedOutput) { - var visitior = new AstFormattingVisitor (policy, adapter, factory); + var visitior = new AstFormattingVisitor (policy, document, factory); - var compilationUnit = new CSharpParser ().Parse (new StringReader (adapter.Text)); + var compilationUnit = new CSharpParser ().Parse (new StringReader (document.Text)); compilationUnit.AcceptVisitor (visitior, null); - ApplyChanges (((TextEditorTestAdapter)adapter), visitior.Changes); - if (expectedOutput != adapter.Text) { - Console.WriteLine (adapter.Text); + string newText = ApplyChanges (document.Text, visitior.Changes); + if (expectedOutput != newText) { + Console.WriteLine (newText); } - Assert.AreEqual (expectedOutput, adapter.Text); + Assert.AreEqual (expectedOutput, newText); } diff --git a/ICSharpCode.NRefactory/Editor/IDocumentLine.cs b/ICSharpCode.NRefactory/Editor/IDocumentLine.cs index 193f761149..0471509fdd 100644 --- a/ICSharpCode.NRefactory/Editor/IDocumentLine.cs +++ b/ICSharpCode.NRefactory/Editor/IDocumentLine.cs @@ -41,5 +41,15 @@ namespace ICSharpCode.NRefactory.Editor /// The first line has the number 1. /// int LineNumber { get; } + + /// + /// Gets the previous line. Returns null if this is the first line in the document. + /// + IDocumentLine PreviousLine { get; } + + /// + /// Gets the next line. Returns null if this is the last line in the document. + /// + IDocumentLine NextLine { get; } } } diff --git a/ICSharpCode.NRefactory/Editor/ISegment.cs b/ICSharpCode.NRefactory/Editor/ISegment.cs index 8bf9c5172d..f0e430ec0b 100644 --- a/ICSharpCode.NRefactory/Editor/ISegment.cs +++ b/ICSharpCode.NRefactory/Editor/ISegment.cs @@ -33,7 +33,7 @@ namespace ICSharpCode.NRefactory.Editor /// /// Gets the length of the segment. /// - /// Must not be negative. + /// For line segments (IDocumentLine), the length does not include the line delimeter. int Length { get; } /// diff --git a/ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs b/ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs index 17c6d28936..0d5e810065 100644 --- a/ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs +++ b/ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs @@ -111,6 +111,24 @@ namespace ICSharpCode.NRefactory.Editor public int LineNumber { get { return lineNumber; } } + + public IDocumentLine PreviousLine { + get { + if (lineNumber == 1) + return null; + else + return new ReadOnlyDocumentLine(doc, lineNumber - 1); + } + } + + public IDocumentLine NextLine { + get { + if (lineNumber == doc.LineCount) + return null; + else + return new ReadOnlyDocumentLine(doc, lineNumber + 1); + } + } } int GetStartOffset(int lineNumber)