Browse Source

Speeded up document script node formatting.

pull/32/merge
Mike Krüger 13 years ago
parent
commit
8639ca4d5b
  1. 7
      ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs
  2. 126
      ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs
  3. 26
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/SortUsingsAction.cs
  4. 12
      ICSharpCode.NRefactory.CSharp/Refactoring/DocumentScript.cs
  5. 20
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/MoveToOuterScopeTests.cs
  6. 1
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/SplitDeclarationAndAssignmentTests.cs

7
ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs

@ -31,6 +31,7 @@ using System.Diagnostics; @@ -31,6 +31,7 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp
{
@ -193,6 +194,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -193,6 +194,12 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public DomRegion Region {
get {
return new DomRegion (StartLocation, EndLocation);
}
}
/// <summary>
/// Gets the region from StartLocation to EndLocation for this node.
/// The file name of the region is set based on the parent SyntaxTree's file name.

126
ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs

@ -48,9 +48,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -48,9 +48,9 @@ namespace ICSharpCode.NRefactory.CSharp
internal readonly string NewText;
internal TextReplaceAction DependsOn;
#if DEBUG
#if DEBUG
internal readonly string StackTrace;
#endif
#endif
public TextReplaceAction (int offset, int removalLength, string newText)
{
@ -98,9 +98,22 @@ namespace ICSharpCode.NRefactory.CSharp @@ -98,9 +98,22 @@ namespace ICSharpCode.NRefactory.CSharp
set;
}
public DomRegion FormattingRegion {
get;
set;
List<DomRegion> formattingRegions = new List<DomRegion> ();
TextLocation lastFormattingLocation = new TextLocation(int.MaxValue, int.MaxValue);
public IEnumerable<DomRegion> FormattingRegions {
get {
return formattingRegions;
}
}
public void AddFormattingRegion (DomRegion region)
{
formattingRegions.Add(region);
if (formattingRegions.Count == 1) {
lastFormattingLocation = region.End;
} else {
lastFormattingLocation = lastFormattingLocation < region.End ? region.End : lastFormattingLocation;
}
}
public AstFormattingVisitor(CSharpFormattingOptions policy, IDocument document, TextEditorOptions options = null)
@ -117,26 +130,35 @@ namespace ICSharpCode.NRefactory.CSharp @@ -117,26 +130,35 @@ namespace ICSharpCode.NRefactory.CSharp
curIndent = new Indent(this.options);
}
protected override void VisitChildren (AstNode node)
void VisitChildrenToFormat (AstNode parent, Action<AstNode> callback)
{
AstNode next;
for (var child = node.FirstChild; child != null; child = next) {
for (var child = parent.FirstChild; child != null; child = next) {
// Store next to allow the loop to continue
// if the visitor removes/replaces child.
next = child.NextSibling;
if (!FormattingRegion.IsEmpty) {
if (child.EndLocation < FormattingRegion.Begin) {
continue;
if (formattingRegions.Count > 0) {
if (formattingRegions.Any(r => r.IsInside(child.StartLocation) || r.IsInside(child.EndLocation))) {
callback(child);
} else {
var childRegion = child.Region;
if (formattingRegions.Any(r => childRegion.IsInside(r.Begin) || childRegion.IsInside(r.End)))
callback(child);
}
if (child.StartLocation > FormattingRegion.End) {
if (child.StartLocation > lastFormattingLocation)
break;
}
} else {
callback(child);
}
child.AcceptVisitor (this);
}
}
protected override void VisitChildren (AstNode node)
{
VisitChildrenToFormat (node, n => n.AcceptVisitor (this));
}
/// <summary>
/// Applies the changes to the input document.
/// </summary>
@ -166,6 +188,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -166,6 +188,9 @@ namespace ICSharpCode.NRefactory.CSharp
public void ApplyChanges(int startOffset, int length, Action<int, int, string> documentReplace, Func<int, int, string, bool> filter = null)
{
int endOffset = startOffset + length;
// Console.WriteLine ("apply:"+ startOffset + "->" + endOffset);
// Console.WriteLine (document.Text.Substring (0, startOffset) + new string ('x',length) + document.Text.Substring (startOffset+ length));
TextReplaceAction previousChange = null;
int delta = 0;
var depChanges = new List<TextReplaceAction> ();
@ -187,11 +212,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -187,11 +212,9 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
previousChange = change;
bool skipChange = change.Offset < startOffset || change.Offset > endOffset;
bool skipChange = change.Offset + change.RemovalLength < startOffset || change.Offset > endOffset;
skipChange |= filter != null && filter(change.Offset + delta, change.RemovalLength, change.NewText);
skipChange &= !depChanges.Contains(change);
if (!skipChange) {
documentReplace(change.Offset + delta, change.RemovalLength, change.NewText);
delta += change.NewText.Length - change.RemovalLength;
@ -350,15 +373,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -350,15 +373,11 @@ namespace ICSharpCode.NRefactory.CSharp
curIndent.Push(IndentType.Block);
}
AstNode next;
for (var child = typeDeclaration.FirstChild; child != null; child = next) {
// Store next to allow the loop to continue
// if the visitor removes/replaces child.
next = child.NextSibling;
VisitChildrenToFormat (typeDeclaration, child => {
if (child is EntityDeclaration)
FormatAttributedNode(child);
child.AcceptVisitor (this);
}
});
if (indentBody) {
curIndent.Pop ();
@ -439,18 +458,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -439,18 +458,18 @@ namespace ICSharpCode.NRefactory.CSharp
if (lastNonWs >= 0)
AddChange(lastNonWs + 1, System.Math.Max(0, endOffset - lastNonWs - 1), forceSpace ? " " : "");
}
// void ForceSpacesAfter (AstNode n, bool forceSpaces)
// {
// if (n == null)
// return;
// AstLocation location = n.EndLocation;
// int offset = data.LocationToOffset (location.Line, location.Column);
// int i = offset;
// while (i < data.Length && IsSpacing (data.GetCharAt (i))) {
// i++;
// }
// ForceSpace (offset - 1, i, forceSpaces);
// }
// void ForceSpacesAfter (AstNode n, bool forceSpaces)
// {
// if (n == null)
// return;
// AstLocation location = n.EndLocation;
// int offset = data.LocationToOffset (location.Line, location.Column);
// int i = offset;
// while (i < data.Length && IsSpacing (data.GetCharAt (i))) {
// i++;
// }
// ForceSpace (offset - 1, i, forceSpaces);
// }
void ForceSpacesAfter(AstNode n, bool forceSpaces)
{
@ -469,21 +488,21 @@ namespace ICSharpCode.NRefactory.CSharp @@ -469,21 +488,21 @@ namespace ICSharpCode.NRefactory.CSharp
ForceSpace(offset - 1, i, forceSpaces);
}
// int ForceSpacesBefore (AstNode n, bool forceSpaces)
// {
// if (n == null || n.IsNull)
// return 0;
// AstLocation location = n.StartLocation;
//
// int offset = data.LocationToOffset (location.Line, location.Column);
// int i = offset - 1;
//
// while (i >= 0 && IsSpacing (data.GetCharAt (i))) {
// i--;
// }
// ForceSpace (i, offset, forceSpaces);
// return i;
// }
// int ForceSpacesBefore (AstNode n, bool forceSpaces)
// {
// if (n == null || n.IsNull)
// return 0;
// AstLocation location = n.StartLocation;
//
// int offset = data.LocationToOffset (location.Line, location.Column);
// int i = offset - 1;
//
// while (i >= 0 && IsSpacing (data.GetCharAt (i))) {
// i--;
// }
// ForceSpace (i, offset, forceSpaces);
// return i;
// }
int ForceSpacesBefore(AstNode n, bool forceSpaces)
{
@ -1045,10 +1064,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1045,10 +1064,12 @@ namespace ICSharpCode.NRefactory.CSharp
if (indent) {
curIndent.Push(IndentType.Block);
}
foreach (var child in blockStatement.Children) {
VisitChildrenToFormat (blockStatement, child => {
if (child.Role == Roles.LBrace || child.Role == Roles.RBrace) {
continue;
return;
}
if (child is Statement) {
FixStatementIndentation(child.StartLocation);
child.AcceptVisitor(this);
@ -1061,7 +1082,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1061,7 +1082,8 @@ namespace ICSharpCode.NRefactory.CSharp
if (child.StartLocation.Column > 1)
FixStatementIndentation(child.StartLocation);
}
}
});
if (indent) {
curIndent.Pop ();
}

26
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/SortUsingsAction.cs

@ -1,3 +1,29 @@ @@ -1,3 +1,29 @@
//
// SortUsingsAction.cs
//
// Author:
// Lopatkin Ilja
//
// Copyright (c) 2012 Lopatkin Ilja
//
// 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;
using System.Linq;

12
ICSharpCode.NRefactory.CSharp/Refactoring/DocumentScript.cs

@ -101,15 +101,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -101,15 +101,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public override void FormatText(IEnumerable<AstNode> nodes)
{
var syntaxTree = SyntaxTree.Parse(currentDocument, "dummy.cs");
var formatter = new AstFormattingVisitor(FormattingOptions, currentDocument, Options);
var segments = new List<ISegment>();
foreach (var node in nodes.OrderByDescending (n => n.StartLocation)) {
var segment = GetSegment(node);
var formatter = new AstFormattingVisitor(FormattingOptions, currentDocument, Options);
formatter.FormattingRegion = new ICSharpCode.NRefactory.TypeSystem.DomRegion (
formatter.AddFormattingRegion (new ICSharpCode.NRefactory.TypeSystem.DomRegion (
currentDocument.GetLocation (segment.Offset),
currentDocument.GetLocation (segment.EndOffset)
);
syntaxTree.AcceptVisitor(formatter);
));
segments.Add(segment);
}
syntaxTree.AcceptVisitor(formatter);
foreach (var segment in segments) {
formatter.ApplyChanges(segment.Offset, segment.Length);
}
}

20
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/MoveToOuterScopeTests.cs

@ -58,8 +58,8 @@ class A @@ -58,8 +58,8 @@ class A
int $i = 2;
}
", @"
int i = 2;
while (true) {
int i = 2;
while (true) {
}
");
}
@ -86,8 +86,8 @@ class A @@ -86,8 +86,8 @@ class A
}
", @"
int i = 2;
while (true) {
int j = 3;
while (true) {
int j = 3;
}
");
}
@ -100,8 +100,8 @@ class A @@ -100,8 +100,8 @@ class A
i$nt i = 2, j = 3;
}
", @"
int i = 2, j = 3;
while (true) {
int i = 2, j = 3;
while (true) {
}
");
}
@ -115,11 +115,11 @@ class A @@ -115,11 +115,11 @@ class A
int j$ = i;
}
", @"
int j;
int j;
while (true) {
int i = 2;
j = i;
}
}
");
}
@ -131,8 +131,8 @@ class A @@ -131,8 +131,8 @@ class A
int j$ = 2;
});
", @"
int j = 2;
var action = new Action<int>(i => {
int j = 2;
var action = new Action<int>(i => {
});
");
}

1
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/SplitDeclarationAndAssignmentTests.cs

@ -101,7 +101,6 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions @@ -101,7 +101,6 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
" {" + Environment.NewLine +
" int i;" + Environment.NewLine +
" for (i = 1; i < 10; i++) {" + Environment.NewLine +
" " + Environment.NewLine +
" }" + Environment.NewLine +
" }" + Environment.NewLine +
"}", result);

Loading…
Cancel
Save