|
|
|
|
@ -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,24 +130,33 @@ namespace ICSharpCode.NRefactory.CSharp
@@ -117,24 +130,33 @@ 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>
|
|
|
|
|
@ -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 (); |
|
|
|
|
} |
|
|
|
|
|