You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2198 lines
80 KiB
2198 lines
80 KiB
// |
|
// AstFormattingVisitor.cs |
|
// |
|
// Author: |
|
// Mike Krüger <mkrueger@novell.com> |
|
// |
|
// Copyright (c) 2010 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.Diagnostics; |
|
using System.Text; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using ICSharpCode.NRefactory.Editor; |
|
using ICSharpCode.NRefactory.TypeSystem; |
|
using ICSharpCode.NRefactory.CSharp.Refactoring; |
|
|
|
namespace ICSharpCode.NRefactory.CSharp |
|
{ |
|
public enum FormattingMode { |
|
OnTheFly, |
|
Intrusive |
|
} |
|
|
|
public class AstFormattingVisitor : DepthFirstAstVisitor |
|
{ |
|
sealed class TextReplaceAction |
|
{ |
|
internal readonly int Offset; |
|
internal readonly int RemovalLength; |
|
internal readonly string NewText; |
|
internal TextReplaceAction DependsOn; |
|
|
|
#if DEBUG |
|
internal readonly string StackTrace; |
|
#endif |
|
|
|
public TextReplaceAction (int offset, int removalLength, string newText) |
|
{ |
|
this.Offset = offset; |
|
this.RemovalLength = removalLength; |
|
this.NewText = newText ?? string.Empty; |
|
#if DEBUG |
|
this.StackTrace = Environment.StackTrace; |
|
#endif |
|
} |
|
|
|
public override bool Equals(object obj) |
|
{ |
|
TextReplaceAction other = obj as TextReplaceAction; |
|
if (other == null) { |
|
return false; |
|
} |
|
return this.Offset == other.Offset && this.RemovalLength == other.RemovalLength && this.NewText == other.NewText; |
|
} |
|
|
|
public override int GetHashCode() |
|
{ |
|
return 0; |
|
} |
|
|
|
public override string ToString() |
|
{ |
|
return string.Format("[TextReplaceAction: Offset={0}, RemovalLength={1}, NewText={2}]", Offset, RemovalLength, NewText); |
|
} |
|
} |
|
|
|
CSharpFormattingOptions policy; |
|
IDocument document; |
|
List<TextReplaceAction> changes = new List<TextReplaceAction> (); |
|
Indent curIndent; |
|
readonly TextEditorOptions options; |
|
|
|
public FormattingMode FormattingMode { |
|
get; |
|
set; |
|
} |
|
|
|
public bool HadErrors { |
|
get; |
|
set; |
|
} |
|
|
|
public DomRegion FormattingRegion { |
|
get; |
|
set; |
|
} |
|
|
|
public AstFormattingVisitor(CSharpFormattingOptions policy, IDocument document, TextEditorOptions options = null) |
|
{ |
|
if (policy == null) { |
|
throw new ArgumentNullException("policy"); |
|
} |
|
if (document == null) { |
|
throw new ArgumentNullException("document"); |
|
} |
|
this.policy = policy; |
|
this.document = document; |
|
this.options = options ?? TextEditorOptions.Default; |
|
curIndent = new Indent(this.options); |
|
} |
|
|
|
protected override void VisitChildren (AstNode node) |
|
{ |
|
AstNode next; |
|
for (var child = node.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 (child.StartLocation > FormattingRegion.End) { |
|
break; |
|
} |
|
} |
|
child.AcceptVisitor (this); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Applies the changes to the input document. |
|
/// </summary> |
|
public void ApplyChanges() |
|
{ |
|
ApplyChanges(0, document.TextLength, document.Replace, (o, l, v) => document.GetText(o, l) == v); |
|
} |
|
|
|
public void ApplyChanges(int startOffset, int length) |
|
{ |
|
ApplyChanges(startOffset, length, document.Replace, (o, l, v) => document.GetText(o, l) == v); |
|
} |
|
|
|
/// <summary> |
|
/// Applies the changes to the given Script instance. |
|
/// </summary> |
|
public void ApplyChanges(Script script) |
|
{ |
|
ApplyChanges(0, document.TextLength, script.Replace); |
|
} |
|
|
|
public void ApplyChanges(int startOffset, int length, Script script) |
|
{ |
|
ApplyChanges(startOffset, length, script.Replace); |
|
} |
|
|
|
public void ApplyChanges(int startOffset, int length, Action<int, int, string> documentReplace, Func<int, int, string, bool> filter = null) |
|
{ |
|
int endOffset = startOffset + length; |
|
TextReplaceAction previousChange = null; |
|
int delta = 0; |
|
var depChanges = new List<TextReplaceAction> (); |
|
foreach (var change in changes.OrderBy(c => c.Offset)) { |
|
if (previousChange != null) { |
|
if (change.Equals(previousChange)) { |
|
// ignore duplicate changes |
|
continue; |
|
} |
|
if (change.Offset < previousChange.Offset + previousChange.RemovalLength) { |
|
#if DEBUG |
|
Console.WriteLine ("change 1:" + change + " at " + document.GetLocation (change.Offset)); |
|
Console.WriteLine (change.StackTrace); |
|
|
|
Console.WriteLine ("change 2:" + previousChange + " at " + document.GetLocation (previousChange.Offset)); |
|
Console.WriteLine (previousChange.StackTrace); |
|
#endif |
|
throw new InvalidOperationException ("Detected overlapping changes " + change + "/" + previousChange); |
|
} |
|
} |
|
previousChange = change; |
|
|
|
bool skipChange = change.Offset < 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; |
|
if (change.DependsOn != null) { |
|
depChanges.Add(change.DependsOn); |
|
} |
|
} |
|
} |
|
changes.Clear(); |
|
} |
|
|
|
public override void VisitSyntaxTree(SyntaxTree unit) |
|
{ |
|
base.VisitSyntaxTree(unit); |
|
} |
|
|
|
public void EnsureBlankLinesAfter(AstNode node, int blankLines) |
|
{ |
|
if (FormattingMode != FormattingMode.Intrusive) |
|
return; |
|
var loc = node.EndLocation; |
|
int line = loc.Line; |
|
do { |
|
line++; |
|
} 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(this.options.EolMarker); |
|
} |
|
|
|
int ws = start; |
|
while (ws < document.TextLength && IsSpacing (document.GetCharAt (ws))) { |
|
ws++; |
|
} |
|
int removedChars = ws - start; |
|
if (foundBlankLines > blankLines) { |
|
removedChars += document.GetLineByNumber(loc.Line + foundBlankLines - blankLines).EndOffset |
|
- document.GetLineByNumber(loc.Line).EndOffset; |
|
} |
|
AddChange(start, removedChars, sb.ToString()); |
|
} |
|
|
|
public void EnsureBlankLinesBefore(AstNode node, int blankLines) |
|
{ |
|
if (FormattingMode != FormattingMode.Intrusive) |
|
return; |
|
var loc = node.StartLocation; |
|
int line = loc.Line; |
|
do { |
|
line--; |
|
} 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(this.options.EolMarker); |
|
} |
|
if (end - start == 0 && sb.Length == 0) |
|
return; |
|
AddChange(start, end - start, sb.ToString()); |
|
} |
|
|
|
public override void VisitUsingDeclaration(UsingDeclaration usingDeclaration) |
|
{ |
|
if (usingDeclaration.PrevSibling != null && !(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration)) { |
|
FixIndentationForceNewLine(usingDeclaration.StartLocation); |
|
EnsureBlankLinesBefore(usingDeclaration, policy.BlankLinesBeforeUsings); |
|
} else if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration)) { |
|
FixIndentationForceNewLine(usingDeclaration.StartLocation); |
|
EnsureBlankLinesAfter(usingDeclaration, policy.BlankLinesAfterUsings); |
|
} else { |
|
FixIndentationForceNewLine(usingDeclaration.StartLocation); |
|
} |
|
} |
|
|
|
public override void VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration) |
|
{ |
|
if (usingDeclaration.PrevSibling != null && !(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration)) { |
|
EnsureBlankLinesBefore(usingDeclaration, policy.BlankLinesBeforeUsings); |
|
} else if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration)) { |
|
FixIndentationForceNewLine(usingDeclaration.StartLocation); |
|
EnsureBlankLinesAfter(usingDeclaration, policy.BlankLinesAfterUsings); |
|
} else { |
|
FixIndentationForceNewLine(usingDeclaration.StartLocation); |
|
} |
|
} |
|
|
|
public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) |
|
{ |
|
var firstNsMember = namespaceDeclaration.Members.FirstOrDefault(); |
|
if (firstNsMember != null) { |
|
EnsureBlankLinesBefore(firstNsMember, policy.BlankLinesBeforeFirstDeclaration); |
|
} |
|
FixIndentationForceNewLine(namespaceDeclaration.StartLocation); |
|
EnforceBraceStyle(policy.NamespaceBraceStyle, namespaceDeclaration.LBraceToken, namespaceDeclaration.RBraceToken); |
|
if (policy.IndentNamespaceBody) { |
|
curIndent.Push(IndentType.Block); |
|
} |
|
base.VisitNamespaceDeclaration(namespaceDeclaration); |
|
if (policy.IndentNamespaceBody) { |
|
curIndent.Pop (); |
|
} |
|
FixIndentation(namespaceDeclaration.RBraceToken.StartLocation); |
|
} |
|
|
|
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration) |
|
{ |
|
FormatAttributedNode(typeDeclaration); |
|
BraceStyle braceStyle; |
|
bool indentBody = false; |
|
switch (typeDeclaration.ClassType) { |
|
case ClassType.Class: |
|
braceStyle = policy.ClassBraceStyle; |
|
indentBody = policy.IndentClassBody; |
|
break; |
|
case ClassType.Struct: |
|
braceStyle = policy.StructBraceStyle; |
|
indentBody = policy.IndentStructBody; |
|
break; |
|
case ClassType.Interface: |
|
braceStyle = policy.InterfaceBraceStyle; |
|
indentBody = policy.IndentInterfaceBody; |
|
break; |
|
case ClassType.Enum: |
|
braceStyle = policy.EnumBraceStyle; |
|
indentBody = policy.IndentEnumBody; |
|
break; |
|
default: |
|
throw new InvalidOperationException("unsupported class type : " + typeDeclaration.ClassType); |
|
} |
|
|
|
EnforceBraceStyle(braceStyle, typeDeclaration.LBraceToken, typeDeclaration.RBraceToken); |
|
|
|
if (indentBody) { |
|
curIndent.Push(IndentType.Block); |
|
} |
|
base.VisitTypeDeclaration(typeDeclaration); |
|
if (indentBody) { |
|
curIndent.Pop (); |
|
} |
|
|
|
if (typeDeclaration.NextSibling is TypeDeclaration || typeDeclaration.NextSibling is DelegateDeclaration) { |
|
EnsureBlankLinesAfter(typeDeclaration, policy.BlankLinesBetweenTypes); |
|
} |
|
|
|
} |
|
|
|
bool IsSimpleAccessor(Accessor accessor) |
|
{ |
|
if (accessor.IsNull || accessor.Body.IsNull || accessor.Body.FirstChild == null) { |
|
return true; |
|
} |
|
if (accessor.Body.Statements.Count() != 1) { |
|
return false; |
|
} |
|
return !(accessor.Body.Statements.FirstOrDefault() is BlockStatement); |
|
|
|
} |
|
|
|
bool IsSpacing(char ch) |
|
{ |
|
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) |
|
{ |
|
startOffset = System.Math.Max(0, startOffset); |
|
endOffset = System.Math.Max(startOffset, endOffset); |
|
if (startOffset >= endOffset) { |
|
return startOffset; |
|
} |
|
int result = -1; |
|
bool inComment = false; |
|
|
|
for (int i = startOffset; i < endOffset && i < document.TextLength; i++) { |
|
char ch = document.GetCharAt(i); |
|
if (IsSpacing(ch)) { |
|
continue; |
|
} |
|
if (ch == '/' && i + 1 < document.TextLength && document.GetCharAt(i + 1) == '/') { |
|
return result; |
|
} |
|
if (ch == '/' && i + 1 < document.TextLength && document.GetCharAt(i + 1) == '*') { |
|
inComment = true; |
|
i++; |
|
continue; |
|
} |
|
if (inComment && ch == '*' && i + 1 < document.TextLength && document.GetCharAt(i + 1) == '/') { |
|
inComment = false; |
|
i++; |
|
continue; |
|
} |
|
if (!inComment) { |
|
result = i; |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
void ForceSpace(int startOffset, int endOffset, bool forceSpace) |
|
{ |
|
int lastNonWs = SearchLastNonWsChar(startOffset, endOffset); |
|
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; |
|
} |
|
TextLocation location = n.EndLocation; |
|
int offset = document.GetOffset(location); |
|
if (location.Column > document.GetLineByNumber(location.Line).Length) { |
|
return; |
|
} |
|
int i = offset; |
|
while (i < document.TextLength && IsSpacing (document.GetCharAt (i))) { |
|
i++; |
|
} |
|
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; |
|
} |
|
TextLocation location = n.StartLocation; |
|
// respect manual line breaks. |
|
if (location.Column <= 1 || GetIndentation(location.Line).Length == location.Column - 1) { |
|
return 0; |
|
} |
|
|
|
int offset = document.GetOffset(location); |
|
int i = offset - 1; |
|
while (i >= 0 && IsSpacing (document.GetCharAt (i))) { |
|
i--; |
|
} |
|
ForceSpace(i, offset, forceSpaces); |
|
return i; |
|
} |
|
|
|
int ForceSpacesBeforeRemoveNewLines(AstNode n, bool forceSpace = true) |
|
{ |
|
if (n == null || n.IsNull) { |
|
return 0; |
|
} |
|
int offset = document.GetOffset(n.StartLocation); |
|
int i = offset - 1; |
|
while (i >= 0) { |
|
char ch = document.GetCharAt(i); |
|
if (!IsSpacing(ch) && ch != '\r' && ch != '\n') |
|
break; |
|
i--; |
|
} |
|
var length = System.Math.Max(0, (offset - 1) - i); |
|
AddChange(i + 1, length, forceSpace ? " " : ""); |
|
return i; |
|
} |
|
|
|
public override void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration) |
|
{ |
|
FormatAttributedNode(propertyDeclaration); |
|
bool oneLine = false; |
|
switch (policy.PropertyFormatting) { |
|
case PropertyFormatting.AllowOneLine: |
|
bool isSimple = IsSimpleAccessor(propertyDeclaration.Getter) && IsSimpleAccessor(propertyDeclaration.Setter); |
|
int accessorLine = propertyDeclaration.RBraceToken.StartLocation.Line; |
|
if (!propertyDeclaration.Getter.IsNull && propertyDeclaration.Setter.IsNull) { |
|
accessorLine = propertyDeclaration.Getter.StartLocation.Line; |
|
} else if (propertyDeclaration.Getter.IsNull && !propertyDeclaration.Setter.IsNull) { |
|
accessorLine = propertyDeclaration.Setter.StartLocation.Line; |
|
} else { |
|
var acc = propertyDeclaration.Getter.StartLocation < propertyDeclaration.Setter.StartLocation ? |
|
propertyDeclaration.Getter : propertyDeclaration.Setter; |
|
accessorLine = acc.StartLocation.Line; |
|
} |
|
if (!isSimple || propertyDeclaration.LBraceToken.StartLocation.Line != accessorLine) { |
|
EnforceBraceStyle(policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken); |
|
} else { |
|
ForceSpacesBefore(propertyDeclaration.Getter, true); |
|
ForceSpacesBefore(propertyDeclaration.Setter, true); |
|
ForceSpacesBeforeRemoveNewLines(propertyDeclaration.RBraceToken, true); |
|
oneLine = true; |
|
} |
|
break; |
|
case PropertyFormatting.ForceNewLine: |
|
EnforceBraceStyle(policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken); |
|
break; |
|
case PropertyFormatting.ForceOneLine: |
|
isSimple = IsSimpleAccessor(propertyDeclaration.Getter) && IsSimpleAccessor(propertyDeclaration.Setter); |
|
if (isSimple) { |
|
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.document.GetOffset(propertyDeclaration.RBraceToken.StartLocation); |
|
start = SearchWhitespaceStart(offset); |
|
AddChange(start, offset - start, " "); |
|
oneLine = true; |
|
|
|
} else { |
|
EnforceBraceStyle(policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken); |
|
} |
|
break; |
|
} |
|
if (policy.IndentPropertyBody) { |
|
curIndent.Push(IndentType.Block); |
|
} |
|
///System.Console.WriteLine ("one line: " + oneLine); |
|
if (!propertyDeclaration.Getter.IsNull) { |
|
if (!oneLine) { |
|
if (!IsLineIsEmptyUpToEol(propertyDeclaration.Getter.StartLocation)) { |
|
int offset = this.document.GetOffset(propertyDeclaration.Getter.StartLocation); |
|
int start = SearchWhitespaceStart(offset); |
|
string indentString = this.curIndent.IndentString; |
|
AddChange(start, offset - start, this.options.EolMarker + indentString); |
|
} else { |
|
FixIndentation(propertyDeclaration.Getter.StartLocation); |
|
} |
|
} else { |
|
int offset = this.document.GetOffset(propertyDeclaration.Getter.StartLocation); |
|
int start = SearchWhitespaceStart(offset); |
|
AddChange(start, offset - start, " "); |
|
|
|
ForceSpacesBefore(propertyDeclaration.Getter.Body.LBraceToken, true); |
|
ForceSpacesBefore(propertyDeclaration.Getter.Body.RBraceToken, true); |
|
} |
|
if (!propertyDeclaration.Getter.Body.IsNull) { |
|
if (!policy.AllowPropertyGetBlockInline || propertyDeclaration.Getter.Body.LBraceToken.StartLocation.Line != propertyDeclaration.Getter.Body.RBraceToken.StartLocation.Line) { |
|
EnforceBraceStyle(policy.PropertyGetBraceStyle, propertyDeclaration.Getter.Body.LBraceToken, propertyDeclaration.Getter.Body.RBraceToken); |
|
} else { |
|
nextStatementIndent = " "; |
|
} |
|
VisitBlockWithoutFixingBraces(propertyDeclaration.Getter.Body, policy.IndentBlocks); |
|
} |
|
} |
|
|
|
if (!propertyDeclaration.Setter.IsNull) { |
|
if (!oneLine) { |
|
if (!IsLineIsEmptyUpToEol(propertyDeclaration.Setter.StartLocation)) { |
|
int offset = this.document.GetOffset(propertyDeclaration.Setter.StartLocation); |
|
int start = SearchWhitespaceStart(offset); |
|
string indentString = this.curIndent.IndentString; |
|
AddChange(start, offset - start, this.options.EolMarker + indentString); |
|
} else { |
|
FixIndentation(propertyDeclaration.Setter.StartLocation); |
|
} |
|
} else { |
|
int offset = this.document.GetOffset(propertyDeclaration.Setter.StartLocation); |
|
int start = SearchWhitespaceStart(offset); |
|
AddChange(start, offset - start, " "); |
|
|
|
ForceSpacesBefore(propertyDeclaration.Setter.Body.LBraceToken, true); |
|
ForceSpacesBefore(propertyDeclaration.Setter.Body.RBraceToken, true); |
|
} |
|
if (!propertyDeclaration.Setter.Body.IsNull) { |
|
if (!policy.AllowPropertySetBlockInline || propertyDeclaration.Setter.Body.LBraceToken.StartLocation.Line != propertyDeclaration.Setter.Body.RBraceToken.StartLocation.Line) { |
|
EnforceBraceStyle(policy.PropertySetBraceStyle, propertyDeclaration.Setter.Body.LBraceToken, propertyDeclaration.Setter.Body.RBraceToken); |
|
} else { |
|
nextStatementIndent = " "; |
|
} |
|
VisitBlockWithoutFixingBraces(propertyDeclaration.Setter.Body, policy.IndentBlocks); |
|
} |
|
} |
|
|
|
if (policy.IndentPropertyBody) { |
|
curIndent.Pop (); |
|
} |
|
if (IsMember(propertyDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(propertyDeclaration, policy.BlankLinesBetweenMembers); |
|
} |
|
} |
|
|
|
public override void VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration) |
|
{ |
|
ForceSpacesBefore(indexerDeclaration.LBracketToken, policy.SpaceBeforeIndexerDeclarationBracket); |
|
ForceSpacesAfter(indexerDeclaration.LBracketToken, policy.SpaceWithinIndexerDeclarationBracket); |
|
|
|
FormatParameters(indexerDeclaration); |
|
|
|
FormatAttributedNode(indexerDeclaration); |
|
EnforceBraceStyle(policy.PropertyBraceStyle, indexerDeclaration.LBraceToken, indexerDeclaration.RBraceToken); |
|
if (policy.IndentPropertyBody) { |
|
curIndent.Push(IndentType.Block); |
|
} |
|
|
|
if (!indexerDeclaration.Getter.IsNull) { |
|
FixIndentation(indexerDeclaration.Getter.StartLocation); |
|
if (!indexerDeclaration.Getter.Body.IsNull) { |
|
if (!policy.AllowPropertyGetBlockInline || indexerDeclaration.Getter.Body.LBraceToken.StartLocation.Line != indexerDeclaration.Getter.Body.RBraceToken.StartLocation.Line) { |
|
EnforceBraceStyle(policy.PropertyGetBraceStyle, indexerDeclaration.Getter.Body.LBraceToken, indexerDeclaration.Getter.Body.RBraceToken); |
|
} else { |
|
nextStatementIndent = " "; |
|
} |
|
VisitBlockWithoutFixingBraces(indexerDeclaration.Getter.Body, policy.IndentBlocks); |
|
} |
|
} |
|
|
|
if (!indexerDeclaration.Setter.IsNull) { |
|
FixIndentation(indexerDeclaration.Setter.StartLocation); |
|
if (!indexerDeclaration.Setter.Body.IsNull) { |
|
if (!policy.AllowPropertySetBlockInline || indexerDeclaration.Setter.Body.LBraceToken.StartLocation.Line != indexerDeclaration.Setter.Body.RBraceToken.StartLocation.Line) { |
|
EnforceBraceStyle(policy.PropertySetBraceStyle, indexerDeclaration.Setter.Body.LBraceToken, indexerDeclaration.Setter.Body.RBraceToken); |
|
} else { |
|
nextStatementIndent = " "; |
|
} |
|
VisitBlockWithoutFixingBraces(indexerDeclaration.Setter.Body, policy.IndentBlocks); |
|
} |
|
} |
|
if (policy.IndentPropertyBody) { |
|
curIndent.Pop (); |
|
} |
|
if (IsMember(indexerDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(indexerDeclaration, policy.BlankLinesBetweenMembers); |
|
} |
|
} |
|
|
|
static bool IsSimpleEvent(AstNode node) |
|
{ |
|
return node is EventDeclaration; |
|
} |
|
|
|
public override void VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration) |
|
{ |
|
FormatAttributedNode(eventDeclaration); |
|
EnforceBraceStyle(policy.EventBraceStyle, eventDeclaration.LBraceToken, eventDeclaration.RBraceToken); |
|
if (policy.IndentEventBody) { |
|
curIndent.Push(IndentType.Block); |
|
} |
|
|
|
if (!eventDeclaration.AddAccessor.IsNull) { |
|
FixIndentation(eventDeclaration.AddAccessor.StartLocation); |
|
if (!eventDeclaration.AddAccessor.Body.IsNull) { |
|
if (!policy.AllowEventAddBlockInline || eventDeclaration.AddAccessor.Body.LBraceToken.StartLocation.Line != eventDeclaration.AddAccessor.Body.RBraceToken.StartLocation.Line) { |
|
EnforceBraceStyle(policy.EventAddBraceStyle, eventDeclaration.AddAccessor.Body.LBraceToken, eventDeclaration.AddAccessor.Body.RBraceToken); |
|
} else { |
|
nextStatementIndent = " "; |
|
} |
|
|
|
VisitBlockWithoutFixingBraces(eventDeclaration.AddAccessor.Body, policy.IndentBlocks); |
|
} |
|
} |
|
|
|
if (!eventDeclaration.RemoveAccessor.IsNull) { |
|
FixIndentation(eventDeclaration.RemoveAccessor.StartLocation); |
|
if (!eventDeclaration.RemoveAccessor.Body.IsNull) { |
|
if (!policy.AllowEventRemoveBlockInline || eventDeclaration.RemoveAccessor.Body.LBraceToken.StartLocation.Line != eventDeclaration.RemoveAccessor.Body.RBraceToken.StartLocation.Line) { |
|
EnforceBraceStyle(policy.EventRemoveBraceStyle, eventDeclaration.RemoveAccessor.Body.LBraceToken, eventDeclaration.RemoveAccessor.Body.RBraceToken); |
|
} else { |
|
nextStatementIndent = " "; |
|
} |
|
VisitBlockWithoutFixingBraces(eventDeclaration.RemoveAccessor.Body, policy.IndentBlocks); |
|
} |
|
} |
|
|
|
if (policy.IndentEventBody) { |
|
curIndent.Pop (); |
|
} |
|
|
|
if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent(eventDeclaration) && IsSimpleEvent(eventDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(eventDeclaration, policy.BlankLinesBetweenEventFields); |
|
} else if (IsMember(eventDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(eventDeclaration, policy.BlankLinesBetweenMembers); |
|
} |
|
} |
|
|
|
public override void VisitEventDeclaration(EventDeclaration eventDeclaration) |
|
{ |
|
FormatAttributedNode(eventDeclaration); |
|
if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent(eventDeclaration) && IsSimpleEvent(eventDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(eventDeclaration, policy.BlankLinesBetweenEventFields); |
|
} else if (IsMember(eventDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(eventDeclaration, policy.BlankLinesBetweenMembers); |
|
} |
|
|
|
var lastLoc = eventDeclaration.StartLocation; |
|
curIndent.Push(IndentType.Block); |
|
foreach (var initializer in eventDeclaration.Variables) { |
|
if (lastLoc.Line != initializer.StartLocation.Line) { |
|
FixStatementIndentation(initializer.StartLocation); |
|
lastLoc = initializer.StartLocation; |
|
} |
|
initializer.AcceptVisitor(this); |
|
} |
|
curIndent.Pop (); |
|
} |
|
|
|
public override void VisitAccessor(Accessor accessor) |
|
{ |
|
FixIndentationForceNewLine(accessor.StartLocation); |
|
base.VisitAccessor(accessor); |
|
} |
|
|
|
public override void VisitFieldDeclaration(FieldDeclaration fieldDeclaration) |
|
{ |
|
FormatAttributedNode(fieldDeclaration); |
|
fieldDeclaration.ReturnType.AcceptVisitor(this); |
|
FormatCommas(fieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma); |
|
if (fieldDeclaration.NextSibling is FieldDeclaration || fieldDeclaration.NextSibling is FixedFieldDeclaration) { |
|
EnsureBlankLinesAfter(fieldDeclaration, policy.BlankLinesBetweenFields); |
|
} else if (IsMember(fieldDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(fieldDeclaration, policy.BlankLinesBetweenMembers); |
|
} |
|
|
|
var lastLoc = fieldDeclaration.StartLocation; |
|
foreach (var initializer in fieldDeclaration.Variables) { |
|
if (lastLoc.Line != initializer.StartLocation.Line) { |
|
curIndent.Push(IndentType.Block); |
|
FixStatementIndentation(initializer.StartLocation); |
|
curIndent.Pop (); |
|
lastLoc = initializer.StartLocation; |
|
} |
|
initializer.AcceptVisitor(this); |
|
} |
|
} |
|
|
|
public override void VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration) |
|
{ |
|
FormatAttributedNode(fixedFieldDeclaration); |
|
FormatCommas(fixedFieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma); |
|
if (fixedFieldDeclaration.NextSibling is FieldDeclaration || fixedFieldDeclaration.NextSibling is FixedFieldDeclaration) { |
|
EnsureBlankLinesAfter(fixedFieldDeclaration, policy.BlankLinesBetweenFields); |
|
} else if (IsMember(fixedFieldDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(fixedFieldDeclaration, policy.BlankLinesBetweenMembers); |
|
} |
|
|
|
var lastLoc = fixedFieldDeclaration.StartLocation; |
|
curIndent.Push(IndentType.Block); |
|
foreach (var initializer in fixedFieldDeclaration.Variables) { |
|
if (lastLoc.Line != initializer.StartLocation.Line) { |
|
FixStatementIndentation(initializer.StartLocation); |
|
lastLoc = initializer.StartLocation; |
|
} |
|
initializer.AcceptVisitor(this); |
|
} |
|
curIndent.Pop (); |
|
} |
|
|
|
public override void VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration) |
|
{ |
|
FormatAttributedNode(enumMemberDeclaration); |
|
base.VisitEnumMemberDeclaration(enumMemberDeclaration); |
|
} |
|
|
|
public override void VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration) |
|
{ |
|
FormatAttributedNode(delegateDeclaration); |
|
|
|
ForceSpacesBefore(delegateDeclaration.LParToken, policy.SpaceBeforeDelegateDeclarationParentheses); |
|
if (delegateDeclaration.Parameters.Any()) { |
|
ForceSpacesAfter(delegateDeclaration.LParToken, policy.SpaceWithinDelegateDeclarationParentheses); |
|
ForceSpacesBefore(delegateDeclaration.RParToken, policy.SpaceWithinDelegateDeclarationParentheses); |
|
} else { |
|
ForceSpacesAfter(delegateDeclaration.LParToken, policy.SpaceBetweenEmptyDelegateDeclarationParentheses); |
|
ForceSpacesBefore(delegateDeclaration.RParToken, policy.SpaceBetweenEmptyDelegateDeclarationParentheses); |
|
} |
|
FormatCommas(delegateDeclaration, policy.SpaceBeforeDelegateDeclarationParameterComma, policy.SpaceAfterDelegateDeclarationParameterComma); |
|
|
|
if (delegateDeclaration.NextSibling is TypeDeclaration || delegateDeclaration.NextSibling is DelegateDeclaration) { |
|
EnsureBlankLinesAfter(delegateDeclaration, policy.BlankLinesBetweenTypes); |
|
} else if (IsMember(delegateDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(delegateDeclaration, policy.BlankLinesBetweenMembers); |
|
} |
|
|
|
base.VisitDelegateDeclaration(delegateDeclaration); |
|
} |
|
|
|
static bool IsMember(AstNode nextSibling) |
|
{ |
|
return nextSibling != null && nextSibling.NodeType == NodeType.Member; |
|
} |
|
|
|
void FormatAttributedNode(AstNode node) |
|
{ |
|
if (node == null) { |
|
return; |
|
} |
|
AstNode child = node.FirstChild; |
|
while (child != null && child is AttributeSection) { |
|
FixIndentationForceNewLine(child.StartLocation); |
|
child = child.NextSibling; |
|
} |
|
if (child != null) { |
|
FixIndentationForceNewLine(child.StartLocation); |
|
} |
|
} |
|
|
|
|
|
void FormatParameters(AstNode node) |
|
{ |
|
Wrapping methodCallArgumentWrapping; |
|
bool newLineAferMethodCallOpenParentheses; |
|
bool methodClosingParenthesesOnNewLine; |
|
bool spaceWithinMethodCallParentheses; |
|
bool spaceAfterMethodCallParameterComma; |
|
bool spaceBeforeMethodCallParameterComma; |
|
|
|
CSharpTokenNode rParToken; |
|
AstNodeCollection<ParameterDeclaration> parameters; |
|
|
|
var constructorDeclaration = node as ConstructorDeclaration; |
|
if (constructorDeclaration != null) { |
|
methodCallArgumentWrapping = policy.MethodDeclarationParameterWrapping; |
|
newLineAferMethodCallOpenParentheses = policy.NewLineAferMethodDeclarationOpenParentheses; |
|
methodClosingParenthesesOnNewLine = policy.MethodDeclarationClosingParenthesesOnNewLine; |
|
|
|
spaceWithinMethodCallParentheses = policy.SpaceWithinConstructorDeclarationParentheses; |
|
spaceAfterMethodCallParameterComma = policy.SpaceAfterConstructorDeclarationParameterComma; |
|
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeConstructorDeclarationParameterComma; |
|
rParToken = constructorDeclaration.RParToken; |
|
parameters = constructorDeclaration.Parameters; |
|
} else if (node is IndexerDeclaration) { |
|
var indexer = (IndexerDeclaration)node; |
|
methodCallArgumentWrapping = policy.IndexerDeclarationParameterWrapping; |
|
newLineAferMethodCallOpenParentheses = policy.NewLineAferIndexerDeclarationOpenBracket; |
|
methodClosingParenthesesOnNewLine = policy.IndexerDeclarationClosingBracketOnNewLine; |
|
|
|
spaceWithinMethodCallParentheses = policy.SpaceWithinIndexerDeclarationBracket; |
|
spaceAfterMethodCallParameterComma = policy.SpaceAfterIndexerDeclarationParameterComma; |
|
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeIndexerDeclarationParameterComma; |
|
rParToken = indexer.RBracketToken; |
|
parameters = indexer.Parameters; |
|
} else if (node is OperatorDeclaration) { |
|
var op = (OperatorDeclaration)node; |
|
methodCallArgumentWrapping = policy.MethodDeclarationParameterWrapping; |
|
newLineAferMethodCallOpenParentheses = policy.NewLineAferMethodDeclarationOpenParentheses; |
|
methodClosingParenthesesOnNewLine = policy.MethodDeclarationClosingParenthesesOnNewLine; |
|
spaceWithinMethodCallParentheses = policy.SpaceWithinMethodDeclarationParentheses; |
|
spaceAfterMethodCallParameterComma = policy.SpaceAfterMethodDeclarationParameterComma; |
|
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeMethodDeclarationParameterComma; |
|
rParToken = op.RParToken; |
|
parameters = op.Parameters; |
|
} else { |
|
var methodDeclaration = node as MethodDeclaration; |
|
methodCallArgumentWrapping = policy.MethodDeclarationParameterWrapping; |
|
newLineAferMethodCallOpenParentheses = policy.NewLineAferMethodDeclarationOpenParentheses; |
|
methodClosingParenthesesOnNewLine = policy.MethodDeclarationClosingParenthesesOnNewLine; |
|
spaceWithinMethodCallParentheses = policy.SpaceWithinMethodDeclarationParentheses; |
|
spaceAfterMethodCallParameterComma = policy.SpaceAfterMethodDeclarationParameterComma; |
|
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeMethodDeclarationParameterComma; |
|
rParToken = methodDeclaration.RParToken; |
|
parameters = methodDeclaration.Parameters; |
|
} |
|
if (FormattingMode == ICSharpCode.NRefactory.CSharp.FormattingMode.OnTheFly) |
|
methodCallArgumentWrapping = Wrapping.DoNotChange; |
|
|
|
bool wrapMethodCall = DoWrap(methodCallArgumentWrapping, rParToken, parameters.Count); |
|
if (wrapMethodCall && parameters.Any()) { |
|
if (newLineAferMethodCallOpenParentheses) { |
|
curIndent.Push(IndentType.Continuation); |
|
foreach (var arg in parameters) { |
|
FixStatementIndentation(arg.StartLocation); |
|
} |
|
curIndent.Pop(); |
|
} else { |
|
int extraSpaces = parameters.First().StartLocation.Column - 1 - curIndent.IndentString.Length; |
|
curIndent.ExtraSpaces += extraSpaces; |
|
foreach (var arg in parameters.Skip(1)) { |
|
FixStatementIndentation(arg.StartLocation); |
|
} |
|
curIndent.ExtraSpaces -= extraSpaces; |
|
} |
|
if (!rParToken.IsNull) { |
|
if (methodClosingParenthesesOnNewLine) { |
|
FixStatementIndentation(rParToken.StartLocation); |
|
} else { |
|
ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses); |
|
} |
|
} |
|
} else { |
|
foreach (var arg in parameters) { |
|
if (arg.PrevSibling != null) { |
|
if (methodCallArgumentWrapping == Wrapping.DoNotWrap) { |
|
ForceSpacesBeforeRemoveNewLines(arg, spaceAfterMethodCallParameterComma && arg.PrevSibling.Role == Roles.Comma); |
|
} else { |
|
ForceSpacesBefore(arg, spaceAfterMethodCallParameterComma && arg.PrevSibling.Role == Roles.Comma); |
|
} |
|
} |
|
arg.AcceptVisitor(this); |
|
} |
|
if (!rParToken.IsNull) { |
|
if (methodCallArgumentWrapping == Wrapping.DoNotWrap) { |
|
ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses); |
|
} else { |
|
bool sameLine = rParToken.GetPrevNode().StartLocation.Line == rParToken.StartLocation.Line; |
|
if (sameLine) { |
|
ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses); |
|
} else { |
|
FixStatementIndentation(rParToken.StartLocation); |
|
} |
|
} |
|
} |
|
} |
|
if (!rParToken.IsNull) { |
|
foreach (CSharpTokenNode comma in rParToken.Parent.Children.Where(n => n.Role == Roles.Comma)) { |
|
ForceSpacesBefore(comma, spaceBeforeMethodCallParameterComma); |
|
} |
|
} |
|
} |
|
|
|
public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration) |
|
{ |
|
FormatAttributedNode(methodDeclaration); |
|
|
|
ForceSpacesBefore(methodDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses); |
|
if (methodDeclaration.Parameters.Any()) { |
|
ForceSpacesAfter(methodDeclaration.LParToken, policy.SpaceWithinMethodDeclarationParentheses); |
|
FormatParameters(methodDeclaration); |
|
} else { |
|
ForceSpacesAfter(methodDeclaration.LParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); |
|
ForceSpacesBefore(methodDeclaration.RParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); |
|
} |
|
|
|
if (!methodDeclaration.Body.IsNull) { |
|
EnforceBraceStyle(policy.MethodBraceStyle, methodDeclaration.Body.LBraceToken, methodDeclaration.Body.RBraceToken); |
|
VisitBlockWithoutFixingBraces(methodDeclaration.Body, policy.IndentMethodBody); |
|
} |
|
if (IsMember(methodDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(methodDeclaration, policy.BlankLinesBetweenMembers); |
|
} |
|
} |
|
|
|
public override void VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration) |
|
{ |
|
FormatAttributedNode(operatorDeclaration); |
|
|
|
ForceSpacesBefore(operatorDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses); |
|
if (operatorDeclaration.Parameters.Any()) { |
|
ForceSpacesAfter(operatorDeclaration.LParToken, policy.SpaceWithinMethodDeclarationParentheses); |
|
FormatParameters(operatorDeclaration); |
|
} else { |
|
ForceSpacesAfter(operatorDeclaration.LParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); |
|
ForceSpacesBefore(operatorDeclaration.RParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); |
|
} |
|
|
|
if (!operatorDeclaration.Body.IsNull) { |
|
EnforceBraceStyle(policy.MethodBraceStyle, operatorDeclaration.Body.LBraceToken, operatorDeclaration.Body.RBraceToken); |
|
VisitBlockWithoutFixingBraces(operatorDeclaration.Body, policy.IndentMethodBody); |
|
} |
|
if (IsMember(operatorDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(operatorDeclaration, policy.BlankLinesBetweenMembers); |
|
} |
|
} |
|
|
|
public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration) |
|
{ |
|
FormatAttributedNode(constructorDeclaration); |
|
|
|
ForceSpacesBefore(constructorDeclaration.LParToken, policy.SpaceBeforeConstructorDeclarationParentheses); |
|
if (constructorDeclaration.Parameters.Any()) { |
|
ForceSpacesAfter(constructorDeclaration.LParToken, policy.SpaceWithinConstructorDeclarationParentheses); |
|
FormatParameters(constructorDeclaration); |
|
} else { |
|
ForceSpacesAfter(constructorDeclaration.LParToken, policy.SpaceBetweenEmptyConstructorDeclarationParentheses); |
|
ForceSpacesBefore(constructorDeclaration.RParToken, policy.SpaceBetweenEmptyConstructorDeclarationParentheses); |
|
} |
|
|
|
if (!constructorDeclaration.Body.IsNull) { |
|
EnforceBraceStyle(policy.ConstructorBraceStyle, constructorDeclaration.Body.LBraceToken, constructorDeclaration.Body.RBraceToken); |
|
VisitBlockWithoutFixingBraces(constructorDeclaration.Body, policy.IndentMethodBody); |
|
} |
|
if (IsMember(constructorDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(constructorDeclaration, policy.BlankLinesBetweenMembers); |
|
} |
|
} |
|
|
|
public override void VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration) |
|
{ |
|
FormatAttributedNode(destructorDeclaration); |
|
|
|
CSharpTokenNode lParen = destructorDeclaration.LParToken; |
|
int offset = this.document.GetOffset(lParen.StartLocation); |
|
ForceSpaceBefore(offset, policy.SpaceBeforeConstructorDeclarationParentheses); |
|
|
|
if (!destructorDeclaration.Body.IsNull) { |
|
EnforceBraceStyle(policy.DestructorBraceStyle, destructorDeclaration.Body.LBraceToken, destructorDeclaration.Body.RBraceToken); |
|
VisitBlockWithoutFixingBraces(destructorDeclaration.Body, policy.IndentMethodBody); |
|
} |
|
if (IsMember(destructorDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter(destructorDeclaration, policy.BlankLinesBetweenMembers); |
|
} |
|
} |
|
|
|
#region Statements |
|
public override void VisitExpressionStatement(ExpressionStatement expressionStatement) |
|
{ |
|
base.VisitExpressionStatement(expressionStatement); |
|
FixSemicolon(expressionStatement.SemicolonToken); |
|
} |
|
|
|
void VisitBlockWithoutFixingBraces(BlockStatement blockStatement, bool indent) |
|
{ |
|
if (indent) { |
|
curIndent.Push(IndentType.Block); |
|
} |
|
foreach (var child in blockStatement.Children) { |
|
if (child.Role == Roles.LBrace || child.Role == Roles.RBrace) { |
|
continue; |
|
} |
|
if (child is Statement) { |
|
FixStatementIndentation(child.StartLocation); |
|
child.AcceptVisitor(this); |
|
} else if (child is Comment) { |
|
child.AcceptVisitor(this); |
|
} else if (child is NewLineNode) { |
|
// ignore |
|
} else { |
|
// pre processor directives at line start, if they are there. |
|
if (child.StartLocation.Column > 1) |
|
FixStatementIndentation(child.StartLocation); |
|
} |
|
} |
|
if (indent) { |
|
curIndent.Pop (); |
|
} |
|
} |
|
|
|
public override void VisitBlockStatement(BlockStatement blockStatement) |
|
{ |
|
FixIndentation(blockStatement.StartLocation); |
|
VisitBlockWithoutFixingBraces(blockStatement, policy.IndentBlocks); |
|
FixIndentation(blockStatement.EndLocation, -1); |
|
} |
|
|
|
public override void VisitComment(Comment comment) |
|
{ |
|
if (comment.StartsLine && !HadErrors && (!policy.KeepCommentsAtFirstColumn || comment.StartLocation.Column > 1)) { |
|
FixIndentation(comment.StartLocation); |
|
} |
|
} |
|
|
|
public override void VisitBreakStatement(BreakStatement breakStatement) |
|
{ |
|
FixSemicolon(breakStatement.SemicolonToken); |
|
} |
|
|
|
public override void VisitCheckedStatement(CheckedStatement checkedStatement) |
|
{ |
|
FixEmbeddedStatment(policy.StatementBraceStyle, policy.FixedBraceForcement, checkedStatement.Body); |
|
} |
|
|
|
public override void VisitContinueStatement(ContinueStatement continueStatement) |
|
{ |
|
FixSemicolon(continueStatement.SemicolonToken); |
|
} |
|
|
|
public override void VisitEmptyStatement(EmptyStatement emptyStatement) |
|
{ |
|
// Empty |
|
} |
|
|
|
public override void VisitFixedStatement(FixedStatement fixedStatement) |
|
{ |
|
FixEmbeddedStatment(policy.StatementBraceStyle, policy.FixedBraceForcement, fixedStatement.EmbeddedStatement); |
|
} |
|
|
|
public override void VisitForeachStatement(ForeachStatement foreachStatement) |
|
{ |
|
ForceSpacesBefore(foreachStatement.LParToken, policy.SpaceBeforeForeachParentheses); |
|
|
|
ForceSpacesAfter(foreachStatement.LParToken, policy.SpacesWithinForeachParentheses); |
|
ForceSpacesBefore(foreachStatement.RParToken, policy.SpacesWithinForeachParentheses); |
|
|
|
FixEmbeddedStatment(policy.StatementBraceStyle, policy.ForEachBraceForcement, foreachStatement.EmbeddedStatement); |
|
} |
|
|
|
void FixEmbeddedStatment(BraceStyle braceStyle, BraceForcement braceForcement, AstNode node) |
|
{ |
|
FixEmbeddedStatment(braceStyle, braceForcement, null, false, node); |
|
} |
|
|
|
void FixEmbeddedStatment(BraceStyle braceStyle, BraceForcement braceForcement, CSharpTokenNode token, bool allowInLine, AstNode node, bool statementAlreadyIndented = false) |
|
{ |
|
if (node == null) { |
|
return; |
|
} |
|
bool isBlock = node is BlockStatement; |
|
TextReplaceAction beginBraceAction = null; |
|
TextReplaceAction endBraceAction = null; |
|
|
|
switch (braceForcement) { |
|
case BraceForcement.DoNotChange: |
|
//nothing |
|
break; |
|
case BraceForcement.AddBraces: |
|
if (!isBlock) { |
|
AstNode n = node.Parent.GetCSharpNodeBefore(node); |
|
int start = document.GetOffset(n.EndLocation); |
|
string startBrace = ""; |
|
switch (braceStyle) { |
|
case BraceStyle.EndOfLineWithoutSpace: |
|
startBrace = "{"; |
|
break; |
|
case BraceStyle.BannerStyle: |
|
case BraceStyle.EndOfLine: |
|
startBrace = " {"; |
|
break; |
|
case BraceStyle.NextLine: |
|
startBrace = this.options.EolMarker + curIndent.IndentString + "{"; |
|
break; |
|
case BraceStyle.NextLineShifted2: |
|
case BraceStyle.NextLineShifted: |
|
curIndent.Push(IndentType.Block); |
|
startBrace = this.options.EolMarker + curIndent.IndentString + "{"; |
|
curIndent.Pop(); |
|
break; |
|
} |
|
beginBraceAction = AddChange(start, 0, startBrace); |
|
} |
|
break; |
|
case BraceForcement.RemoveBraces: |
|
if (isBlock) { |
|
BlockStatement block = node as BlockStatement; |
|
if (block.Statements.Count() == 1) { |
|
int offset1 = document.GetOffset(node.StartLocation); |
|
int start = SearchWhitespaceStart(offset1); |
|
|
|
int offset2 = document.GetOffset(node.EndLocation); |
|
int end = SearchWhitespaceStart(offset2 - 1); |
|
|
|
beginBraceAction = AddChange(start, offset1 - start + 1, null); |
|
endBraceAction = AddChange(end + 1, offset2 - end, null); |
|
node = block.FirstChild; |
|
isBlock = false; |
|
} |
|
} |
|
break; |
|
} |
|
if (isBlock) { |
|
BlockStatement block = node as BlockStatement; |
|
if (allowInLine && block.StartLocation.Line == block.EndLocation.Line && block.Statements.Count() <= 1) { |
|
if (block.Statements.Count() == 1) { |
|
nextStatementIndent = " "; |
|
} |
|
} else { |
|
if (!statementAlreadyIndented) { |
|
EnforceBraceStyle(braceStyle, block.LBraceToken, block.RBraceToken); |
|
} |
|
} |
|
if (braceStyle == BraceStyle.NextLineShifted2) { |
|
curIndent.Push(IndentType.Block); |
|
} |
|
} else { |
|
if (allowInLine && token.StartLocation.Line == node.EndLocation.Line) { |
|
nextStatementIndent = " "; |
|
} |
|
} |
|
bool pushed = false; |
|
if (policy.IndentBlocks && !(policy.AlignEmbeddedIfStatements && node is IfElseStatement && node.Parent is IfElseStatement || policy.AlignEmbeddedUsingStatements && node is UsingStatement && node.Parent is UsingStatement)) { |
|
curIndent.Push(IndentType.Block); |
|
pushed = true; |
|
} |
|
if (isBlock) { |
|
VisitBlockWithoutFixingBraces((BlockStatement)node, false); |
|
} else { |
|
if (!statementAlreadyIndented) { |
|
FixStatementIndentation(node.StartLocation); |
|
} |
|
node.AcceptVisitor(this); |
|
} |
|
if (pushed) { |
|
curIndent.Pop(); |
|
} |
|
switch (braceForcement) { |
|
case BraceForcement.DoNotChange: |
|
break; |
|
case BraceForcement.AddBraces: |
|
if (!isBlock) { |
|
int offset = document.GetOffset(node.EndLocation); |
|
if (!char.IsWhiteSpace(document.GetCharAt(offset))) { |
|
offset++; |
|
} |
|
string startBrace = ""; |
|
switch (braceStyle) { |
|
case BraceStyle.DoNotChange: |
|
startBrace = null; |
|
break; |
|
case BraceStyle.EndOfLineWithoutSpace: |
|
startBrace = this.options.EolMarker + curIndent.IndentString + "}"; |
|
break; |
|
case BraceStyle.EndOfLine: |
|
startBrace = this.options.EolMarker + curIndent.IndentString + "}"; |
|
break; |
|
case BraceStyle.NextLine: |
|
startBrace = this.options.EolMarker + curIndent.IndentString + "}"; |
|
break; |
|
case BraceStyle.BannerStyle: |
|
case BraceStyle.NextLineShifted2: |
|
case BraceStyle.NextLineShifted: |
|
curIndent.Push(IndentType.Block); |
|
startBrace = this.options.EolMarker + curIndent.IndentString + "}"; |
|
curIndent.Pop (); |
|
break; |
|
|
|
} |
|
if (startBrace != null) { |
|
endBraceAction = AddChange(offset, 0, startBrace); |
|
} |
|
} |
|
break; |
|
} |
|
if (beginBraceAction != null && endBraceAction != null) { |
|
beginBraceAction.DependsOn = endBraceAction; |
|
endBraceAction.DependsOn = beginBraceAction; |
|
} |
|
} |
|
|
|
void EnforceBraceStyle(BraceStyle braceStyle, AstNode lbrace, AstNode rbrace) |
|
{ |
|
if (lbrace.IsNull || rbrace.IsNull) { |
|
return; |
|
} |
|
|
|
// LineSegment lbraceLineSegment = data.Document.GetLine (lbrace.StartLocation.Line); |
|
int lbraceOffset = document.GetOffset(lbrace.StartLocation); |
|
|
|
// LineSegment rbraceLineSegment = data.Document.GetLine (rbrace.StartLocation.Line); |
|
int rbraceOffset = document.GetOffset(rbrace.StartLocation); |
|
int whitespaceStart = SearchWhitespaceStart(lbraceOffset); |
|
int whitespaceEnd = SearchWhitespaceLineStart(rbraceOffset); |
|
string startIndent = ""; |
|
string endIndent = ""; |
|
switch (braceStyle) { |
|
case BraceStyle.DoNotChange: |
|
startIndent = endIndent = null; |
|
break; |
|
case BraceStyle.EndOfLineWithoutSpace: |
|
startIndent = ""; |
|
endIndent = IsLineIsEmptyUpToEol(rbraceOffset) ? curIndent.IndentString : this.options.EolMarker + curIndent.IndentString; |
|
break; |
|
case BraceStyle.BannerStyle: |
|
var prevNode = lbrace.GetPrevNode(); |
|
if (prevNode is Comment) { |
|
// delete old bracket |
|
AddChange(whitespaceStart, lbraceOffset - whitespaceStart + 1, ""); |
|
|
|
while (prevNode is Comment) { |
|
prevNode = prevNode.GetPrevNode(); |
|
} |
|
whitespaceStart = document.GetOffset(prevNode.EndLocation); |
|
lbraceOffset = whitespaceStart; |
|
startIndent = " {"; |
|
} else { |
|
startIndent = " "; |
|
} |
|
curIndent.Push(IndentType.Block); |
|
endIndent = IsLineIsEmptyUpToEol(rbraceOffset) ? curIndent.IndentString : this.options.EolMarker + curIndent.IndentString; |
|
curIndent.Pop(); |
|
break; |
|
case BraceStyle.EndOfLine: |
|
prevNode = lbrace.GetPrevNode(); |
|
if (prevNode is Comment) { |
|
// delete old bracket |
|
AddChange(whitespaceStart, lbraceOffset - whitespaceStart + 1, ""); |
|
|
|
while (prevNode is Comment) { |
|
prevNode = prevNode.GetPrevNode(); |
|
} |
|
whitespaceStart = document.GetOffset(prevNode.EndLocation); |
|
lbraceOffset = whitespaceStart; |
|
startIndent = " {"; |
|
} else { |
|
startIndent = " "; |
|
} |
|
endIndent = IsLineIsEmptyUpToEol(rbraceOffset) ? curIndent.IndentString : this.options.EolMarker + curIndent.IndentString; |
|
break; |
|
case BraceStyle.NextLine: |
|
startIndent = this.options.EolMarker + curIndent.IndentString; |
|
endIndent = IsLineIsEmptyUpToEol(rbraceOffset) ? curIndent.IndentString : this.options.EolMarker + curIndent.IndentString; |
|
break; |
|
case BraceStyle.NextLineShifted2: |
|
case BraceStyle.NextLineShifted: |
|
curIndent.Push(IndentType.Block); |
|
startIndent = this.options.EolMarker + curIndent.IndentString; |
|
endIndent = IsLineIsEmptyUpToEol(rbraceOffset) ? curIndent.IndentString : this.options.EolMarker + curIndent.IndentString; |
|
curIndent.Pop (); |
|
break; |
|
} |
|
|
|
if (lbraceOffset > 0 && startIndent != null) { |
|
AddChange(whitespaceStart, lbraceOffset - whitespaceStart, startIndent); |
|
} |
|
if (rbraceOffset > 0 && endIndent != null) { |
|
AddChange(whitespaceEnd, rbraceOffset - whitespaceEnd, endIndent); |
|
} |
|
} |
|
|
|
TextReplaceAction AddChange(int offset, int removedChars, string insertedText) |
|
{ |
|
if (removedChars == 0 && string.IsNullOrEmpty (insertedText)) |
|
return null; |
|
var action = new TextReplaceAction (offset, removedChars, insertedText); |
|
changes.Add(action); |
|
return action; |
|
} |
|
|
|
public bool IsLineIsEmptyUpToEol(TextLocation startLocation) |
|
{ |
|
return IsLineIsEmptyUpToEol(document.GetOffset(startLocation) - 1); |
|
} |
|
|
|
bool IsLineIsEmptyUpToEol(int startOffset) |
|
{ |
|
for (int offset = startOffset - 1; offset >= 0; offset--) { |
|
char ch = document.GetCharAt(offset); |
|
if (ch != ' ' && ch != '\t') { |
|
return ch == '\n' || ch == '\r'; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
int SearchWhitespaceStart(int startOffset) |
|
{ |
|
if (startOffset < 0) { |
|
throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); |
|
} |
|
for (int offset = startOffset - 1; offset >= 0; offset--) { |
|
char ch = document.GetCharAt(offset); |
|
if (!Char.IsWhiteSpace(ch)) { |
|
return offset + 1; |
|
} |
|
} |
|
return 0; |
|
} |
|
|
|
int SearchWhitespaceEnd(int startOffset) |
|
{ |
|
if (startOffset > document.TextLength) { |
|
throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); |
|
} |
|
for (int offset = startOffset + 1; offset < document.TextLength; offset++) { |
|
char ch = document.GetCharAt(offset); |
|
if (!Char.IsWhiteSpace(ch)) { |
|
return offset + 1; |
|
} |
|
} |
|
return document.TextLength - 1; |
|
} |
|
|
|
int SearchWhitespaceLineStart(int startOffset) |
|
{ |
|
if (startOffset < 0) { |
|
throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); |
|
} |
|
for (int offset = startOffset - 1; offset >= 0; offset--) { |
|
char ch = document.GetCharAt(offset); |
|
if (ch != ' ' && ch != '\t') { |
|
return offset + 1; |
|
} |
|
} |
|
return 0; |
|
} |
|
|
|
public override void VisitForStatement(ForStatement forStatement) |
|
{ |
|
foreach (AstNode node in forStatement.Children) { |
|
if (node.Role == Roles.Semicolon) { |
|
if (node.NextSibling is CSharpTokenNode || node.NextSibling is EmptyStatement) { |
|
continue; |
|
} |
|
ForceSpacesBefore(node, policy.SpaceBeforeForSemicolon); |
|
ForceSpacesAfter(node, policy.SpaceAfterForSemicolon); |
|
} |
|
} |
|
|
|
ForceSpacesBefore(forStatement.LParToken, policy.SpaceBeforeForParentheses); |
|
|
|
ForceSpacesAfter(forStatement.LParToken, policy.SpacesWithinForParentheses); |
|
ForceSpacesBefore(forStatement.RParToken, policy.SpacesWithinForParentheses); |
|
|
|
FixEmbeddedStatment(policy.StatementBraceStyle, policy.ForBraceForcement, forStatement.EmbeddedStatement); |
|
} |
|
|
|
public override void VisitGotoStatement(GotoStatement gotoStatement) |
|
{ |
|
VisitChildren(gotoStatement); |
|
FixSemicolon(gotoStatement.SemicolonToken); |
|
} |
|
|
|
public override void VisitIfElseStatement(IfElseStatement ifElseStatement) |
|
{ |
|
ForceSpacesBefore(ifElseStatement.LParToken, policy.SpaceBeforeIfParentheses); |
|
|
|
ForceSpacesAfter(ifElseStatement.LParToken, policy.SpacesWithinIfParentheses); |
|
ForceSpacesBefore(ifElseStatement.RParToken, policy.SpacesWithinIfParentheses); |
|
|
|
if (!(ifElseStatement.Parent is IfElseStatement && ((IfElseStatement)ifElseStatement.Parent).FalseStatement == ifElseStatement)) { |
|
FixStatementIndentation(ifElseStatement.StartLocation); |
|
} |
|
|
|
if (!ifElseStatement.Condition.IsNull) { |
|
ifElseStatement.Condition.AcceptVisitor(this); |
|
} |
|
|
|
if (!ifElseStatement.TrueStatement.IsNull) { |
|
FixEmbeddedStatment(policy.StatementBraceStyle, policy.IfElseBraceForcement, ifElseStatement.IfToken, policy.AllowIfBlockInline, ifElseStatement.TrueStatement); |
|
} |
|
|
|
if (!ifElseStatement.FalseStatement.IsNull) { |
|
var placeElseOnNewLine = policy.ElseNewLinePlacement; |
|
if (!(ifElseStatement.TrueStatement is BlockStatement) && policy.IfElseBraceForcement != BraceForcement.AddBraces) |
|
placeElseOnNewLine = NewLinePlacement.NewLine; |
|
PlaceOnNewLine(placeElseOnNewLine, ifElseStatement.ElseToken); |
|
var forcement = policy.IfElseBraceForcement; |
|
if (ifElseStatement.FalseStatement is IfElseStatement) { |
|
forcement = BraceForcement.DoNotChange; |
|
PlaceOnNewLine(policy.ElseIfNewLinePlacement, ((IfElseStatement)ifElseStatement.FalseStatement).IfToken); |
|
} |
|
FixEmbeddedStatment(policy.StatementBraceStyle, forcement, ifElseStatement.ElseToken, policy.AllowIfBlockInline, ifElseStatement.FalseStatement, ifElseStatement.FalseStatement is IfElseStatement); |
|
} |
|
} |
|
|
|
public override void VisitLabelStatement(LabelStatement labelStatement) |
|
{ |
|
// TODO |
|
VisitChildren(labelStatement); |
|
} |
|
|
|
public override void VisitLockStatement(LockStatement lockStatement) |
|
{ |
|
ForceSpacesBefore(lockStatement.LParToken, policy.SpaceBeforeLockParentheses); |
|
|
|
ForceSpacesAfter(lockStatement.LParToken, policy.SpacesWithinLockParentheses); |
|
ForceSpacesBefore(lockStatement.RParToken, policy.SpacesWithinLockParentheses); |
|
|
|
FixEmbeddedStatment(policy.StatementBraceStyle, policy.FixedBraceForcement, lockStatement.EmbeddedStatement); |
|
} |
|
|
|
public override void VisitReturnStatement(ReturnStatement returnStatement) |
|
{ |
|
VisitChildren(returnStatement); |
|
FixSemicolon(returnStatement.SemicolonToken); |
|
} |
|
|
|
public override void VisitSwitchStatement(SwitchStatement switchStatement) |
|
{ |
|
ForceSpacesBefore(switchStatement.LParToken, policy.SpaceBeforeSwitchParentheses); |
|
|
|
ForceSpacesAfter(switchStatement.LParToken, policy.SpacesWithinSwitchParentheses); |
|
ForceSpacesBefore(switchStatement.RParToken, policy.SpacesWithinSwitchParentheses); |
|
|
|
EnforceBraceStyle(policy.StatementBraceStyle, switchStatement.LBraceToken, switchStatement.RBraceToken); |
|
VisitChildren(switchStatement); |
|
} |
|
|
|
public override void VisitSwitchSection(SwitchSection switchSection) |
|
{ |
|
if (policy.IndentSwitchBody) { |
|
curIndent.Push(IndentType.Block); |
|
} |
|
|
|
foreach (CaseLabel label in switchSection.CaseLabels) { |
|
FixStatementIndentation(label.StartLocation); |
|
label.AcceptVisitor(this); |
|
} |
|
if (policy.IndentCaseBody) { |
|
curIndent.Push(IndentType.Block); |
|
} |
|
|
|
foreach (var stmt in switchSection.Statements) { |
|
if (stmt is BreakStatement && !policy.IndentBreakStatements && policy.IndentCaseBody) { |
|
curIndent.Pop(); |
|
FixStatementIndentation(stmt.StartLocation); |
|
stmt.AcceptVisitor(this); |
|
curIndent.Push(IndentType.Block); |
|
continue; |
|
} |
|
FixStatementIndentation(stmt.StartLocation); |
|
stmt.AcceptVisitor(this); |
|
} |
|
if (policy.IndentCaseBody) { |
|
curIndent.Pop (); |
|
} |
|
|
|
if (policy.IndentSwitchBody) { |
|
curIndent.Pop (); |
|
} |
|
} |
|
|
|
public override void VisitCaseLabel(CaseLabel caseLabel) |
|
{ |
|
FixSemicolon(caseLabel.ColonToken); |
|
} |
|
|
|
public override void VisitThrowStatement(ThrowStatement throwStatement) |
|
{ |
|
VisitChildren(throwStatement); |
|
FixSemicolon(throwStatement.SemicolonToken); |
|
} |
|
|
|
public override void VisitTryCatchStatement(TryCatchStatement tryCatchStatement) |
|
{ |
|
if (!tryCatchStatement.TryBlock.IsNull) { |
|
FixEmbeddedStatment(policy.StatementBraceStyle, BraceForcement.DoNotChange, tryCatchStatement.TryBlock); |
|
} |
|
|
|
foreach (CatchClause clause in tryCatchStatement.CatchClauses) { |
|
PlaceOnNewLine(policy.CatchNewLinePlacement, clause.CatchToken); |
|
if (!clause.LParToken.IsNull) { |
|
ForceSpacesBefore(clause.LParToken, policy.SpaceBeforeCatchParentheses); |
|
|
|
ForceSpacesAfter(clause.LParToken, policy.SpacesWithinCatchParentheses); |
|
ForceSpacesBefore(clause.RParToken, policy.SpacesWithinCatchParentheses); |
|
} |
|
FixEmbeddedStatment(policy.StatementBraceStyle, BraceForcement.DoNotChange, clause.Body); |
|
} |
|
|
|
if (!tryCatchStatement.FinallyBlock.IsNull) { |
|
PlaceOnNewLine(policy.FinallyNewLinePlacement, tryCatchStatement.FinallyToken); |
|
|
|
FixEmbeddedStatment(policy.StatementBraceStyle, BraceForcement.DoNotChange, tryCatchStatement.FinallyBlock); |
|
} |
|
|
|
} |
|
|
|
public override void VisitCatchClause(CatchClause catchClause) |
|
{ |
|
// Handled in TryCatchStatement |
|
} |
|
|
|
public override void VisitUncheckedStatement(UncheckedStatement uncheckedStatement) |
|
{ |
|
FixEmbeddedStatment(policy.StatementBraceStyle, policy.FixedBraceForcement, uncheckedStatement.Body); |
|
} |
|
|
|
public override void VisitUnsafeStatement(UnsafeStatement unsafeStatement) |
|
{ |
|
FixEmbeddedStatment(policy.StatementBraceStyle, BraceForcement.DoNotChange, unsafeStatement.Body); |
|
} |
|
|
|
public override void VisitUsingStatement(UsingStatement usingStatement) |
|
{ |
|
ForceSpacesBefore(usingStatement.LParToken, policy.SpaceBeforeUsingParentheses); |
|
|
|
ForceSpacesAfter(usingStatement.LParToken, policy.SpacesWithinUsingParentheses); |
|
ForceSpacesBefore(usingStatement.RParToken, policy.SpacesWithinUsingParentheses); |
|
|
|
FixEmbeddedStatment(policy.StatementBraceStyle, policy.UsingBraceForcement, usingStatement.EmbeddedStatement); |
|
} |
|
|
|
public override void VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement) |
|
{ |
|
if ((variableDeclarationStatement.Modifiers & Modifiers.Const) == Modifiers.Const) { |
|
ForceSpacesAround(variableDeclarationStatement.Type, true); |
|
} else { |
|
ForceSpacesAfter(variableDeclarationStatement.Type, true); |
|
} |
|
var lastLoc = variableDeclarationStatement.StartLocation; |
|
foreach (var initializer in variableDeclarationStatement.Variables) { |
|
if (lastLoc.Line != initializer.StartLocation.Line) { |
|
FixStatementIndentation(initializer.StartLocation); |
|
lastLoc = initializer.StartLocation; |
|
} |
|
initializer.AcceptVisitor(this); |
|
} |
|
|
|
FormatCommas(variableDeclarationStatement, policy.SpaceBeforeLocalVariableDeclarationComma, policy.SpaceAfterLocalVariableDeclarationComma); |
|
FixSemicolon(variableDeclarationStatement.SemicolonToken); |
|
} |
|
|
|
public override void VisitDoWhileStatement(DoWhileStatement doWhileStatement) |
|
{ |
|
PlaceOnNewLine(policy.WhileNewLinePlacement, doWhileStatement.WhileToken); |
|
FixEmbeddedStatment(policy.StatementBraceStyle, policy.WhileBraceForcement, doWhileStatement.EmbeddedStatement); |
|
} |
|
|
|
public override void VisitWhileStatement(WhileStatement whileStatement) |
|
{ |
|
ForceSpacesBefore(whileStatement.LParToken, policy.SpaceBeforeWhileParentheses); |
|
|
|
ForceSpacesAfter(whileStatement.LParToken, policy.SpacesWithinWhileParentheses); |
|
ForceSpacesBefore(whileStatement.RParToken, policy.SpacesWithinWhileParentheses); |
|
|
|
FixEmbeddedStatment(policy.StatementBraceStyle, policy.WhileBraceForcement, whileStatement.EmbeddedStatement); |
|
} |
|
|
|
public override void VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement) |
|
{ |
|
FixSemicolon(yieldBreakStatement.SemicolonToken); |
|
} |
|
|
|
public override void VisitYieldReturnStatement(YieldReturnStatement yieldStatement) |
|
{ |
|
yieldStatement.Expression.AcceptVisitor(this); |
|
FixSemicolon(yieldStatement.SemicolonToken); |
|
} |
|
|
|
public override void VisitVariableInitializer(VariableInitializer variableInitializer) |
|
{ |
|
if (!variableInitializer.AssignToken.IsNull) { |
|
ForceSpacesAround(variableInitializer.AssignToken, policy.SpaceAroundAssignment); |
|
} |
|
if (!variableInitializer.Initializer.IsNull) { |
|
variableInitializer.Initializer.AcceptVisitor(this); |
|
} |
|
} |
|
|
|
#endregion |
|
|
|
#region Expressions |
|
public override void VisitComposedType(ComposedType composedType) |
|
{ |
|
var spec = composedType.ArraySpecifiers.FirstOrDefault(); |
|
if (spec != null) { |
|
ForceSpacesBefore(spec.LBracketToken, policy.SpaceBeforeArrayDeclarationBrackets); |
|
} |
|
|
|
base.VisitComposedType(composedType); |
|
} |
|
|
|
public override void VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression) |
|
{ |
|
if (!anonymousMethodExpression.Body.IsNull) { |
|
EnforceBraceStyle(policy.AnonymousMethodBraceStyle, anonymousMethodExpression.Body.LBraceToken, anonymousMethodExpression.Body.RBraceToken); |
|
VisitBlockWithoutFixingBraces(anonymousMethodExpression.Body, policy.IndentBlocks); |
|
return; |
|
} |
|
base.VisitAnonymousMethodExpression(anonymousMethodExpression); |
|
} |
|
|
|
public override void VisitAssignmentExpression(AssignmentExpression assignmentExpression) |
|
{ |
|
ForceSpacesAround(assignmentExpression.OperatorToken, policy.SpaceAroundAssignment); |
|
base.VisitAssignmentExpression(assignmentExpression); |
|
} |
|
|
|
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) |
|
{ |
|
bool forceSpaces = false; |
|
switch (binaryOperatorExpression.Operator) { |
|
case BinaryOperatorType.Equality: |
|
case BinaryOperatorType.InEquality: |
|
forceSpaces = policy.SpaceAroundEqualityOperator; |
|
break; |
|
case BinaryOperatorType.GreaterThan: |
|
case BinaryOperatorType.GreaterThanOrEqual: |
|
case BinaryOperatorType.LessThan: |
|
case BinaryOperatorType.LessThanOrEqual: |
|
forceSpaces = policy.SpaceAroundRelationalOperator; |
|
break; |
|
case BinaryOperatorType.ConditionalAnd: |
|
case BinaryOperatorType.ConditionalOr: |
|
forceSpaces = policy.SpaceAroundLogicalOperator; |
|
break; |
|
case BinaryOperatorType.BitwiseAnd: |
|
case BinaryOperatorType.BitwiseOr: |
|
case BinaryOperatorType.ExclusiveOr: |
|
forceSpaces = policy.SpaceAroundBitwiseOperator; |
|
break; |
|
case BinaryOperatorType.Add: |
|
case BinaryOperatorType.Subtract: |
|
forceSpaces = policy.SpaceAroundAdditiveOperator; |
|
break; |
|
case BinaryOperatorType.Multiply: |
|
case BinaryOperatorType.Divide: |
|
case BinaryOperatorType.Modulus: |
|
forceSpaces = policy.SpaceAroundMultiplicativeOperator; |
|
break; |
|
case BinaryOperatorType.ShiftLeft: |
|
case BinaryOperatorType.ShiftRight: |
|
forceSpaces = policy.SpaceAroundShiftOperator; |
|
break; |
|
case BinaryOperatorType.NullCoalescing: |
|
forceSpaces = policy.SpaceAroundNullCoalescingOperator; |
|
break; |
|
} |
|
ForceSpacesAround(binaryOperatorExpression.OperatorToken, forceSpaces); |
|
|
|
base.VisitBinaryOperatorExpression(binaryOperatorExpression); |
|
// Handle line breaks in binary opeartor expression. |
|
if (binaryOperatorExpression.Left.EndLocation.Line != binaryOperatorExpression.Right.StartLocation.Line) { |
|
curIndent.Push(IndentType.Block); |
|
if (binaryOperatorExpression.OperatorToken.StartLocation.Line == binaryOperatorExpression.Right.StartLocation.Line) { |
|
FixStatementIndentation(binaryOperatorExpression.OperatorToken.StartLocation); |
|
} else { |
|
FixStatementIndentation(binaryOperatorExpression.Right.StartLocation); |
|
} |
|
curIndent.Pop (); |
|
} |
|
} |
|
|
|
public override void VisitConditionalExpression(ConditionalExpression conditionalExpression) |
|
{ |
|
ForceSpacesBefore(conditionalExpression.QuestionMarkToken, policy.SpaceBeforeConditionalOperatorCondition); |
|
ForceSpacesAfter(conditionalExpression.QuestionMarkToken, policy.SpaceAfterConditionalOperatorCondition); |
|
ForceSpacesBefore(conditionalExpression.ColonToken, policy.SpaceBeforeConditionalOperatorSeparator); |
|
ForceSpacesAfter(conditionalExpression.ColonToken, policy.SpaceAfterConditionalOperatorSeparator); |
|
base.VisitConditionalExpression(conditionalExpression); |
|
} |
|
|
|
public override void VisitCastExpression(CastExpression castExpression) |
|
{ |
|
if (castExpression.RParToken != null) { |
|
ForceSpacesAfter(castExpression.LParToken, policy.SpacesWithinCastParentheses); |
|
ForceSpacesBefore(castExpression.RParToken, policy.SpacesWithinCastParentheses); |
|
|
|
ForceSpacesAfter(castExpression.RParToken, policy.SpaceAfterTypecast); |
|
} |
|
base.VisitCastExpression(castExpression); |
|
} |
|
|
|
void ForceSpacesAround(AstNode node, bool forceSpaces) |
|
{ |
|
if (node.IsNull) { |
|
return; |
|
} |
|
ForceSpacesBefore(node, forceSpaces); |
|
ForceSpacesAfter(node, forceSpaces); |
|
} |
|
|
|
void FormatCommas(AstNode parent, bool before, bool after) |
|
{ |
|
if (parent.IsNull) { |
|
return; |
|
} |
|
foreach (CSharpTokenNode comma in parent.Children.Where (node => node.Role == Roles.Comma)) { |
|
ForceSpacesAfter(comma, after); |
|
ForceSpacesBefore(comma, before); |
|
} |
|
} |
|
|
|
bool DoWrap (Wrapping wrapping, AstNode wrapNode, int argumentCount) |
|
{ |
|
return wrapping == Wrapping.WrapAlways || |
|
options.WrapLineLength > 0 && argumentCount > 1 && wrapping == Wrapping.WrapIfTooLong && wrapNode.StartLocation.Column >= options.WrapLineLength; |
|
} |
|
|
|
void FormatArguments(AstNode node) |
|
{ |
|
Wrapping methodCallArgumentWrapping; |
|
bool newLineAferMethodCallOpenParentheses; |
|
bool methodClosingParenthesesOnNewLine; |
|
bool spaceWithinMethodCallParentheses; |
|
bool spaceWithinEmptyParentheses; |
|
bool spaceAfterMethodCallParameterComma; |
|
bool spaceBeforeMethodCallParameterComma; |
|
|
|
CSharpTokenNode rParToken; |
|
AstNodeCollection<Expression> arguments; |
|
var indexer = node as IndexerExpression; |
|
if (indexer != null) { |
|
methodCallArgumentWrapping = policy.IndexerArgumentWrapping; |
|
newLineAferMethodCallOpenParentheses = policy.NewLineAferIndexerOpenBracket; |
|
methodClosingParenthesesOnNewLine = policy.IndexerClosingBracketOnNewLine; |
|
spaceWithinMethodCallParentheses = policy.SpacesWithinBrackets; |
|
spaceAfterMethodCallParameterComma = policy.SpaceAfterBracketComma; |
|
spaceWithinEmptyParentheses = spaceWithinMethodCallParentheses; |
|
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeBracketComma; |
|
rParToken = indexer.RBracketToken; |
|
arguments = indexer.Arguments; |
|
} else if (node is ObjectCreateExpression) { |
|
var oce = node as ObjectCreateExpression; |
|
methodCallArgumentWrapping = policy.MethodCallArgumentWrapping; |
|
newLineAferMethodCallOpenParentheses = policy.NewLineAferMethodCallOpenParentheses; |
|
methodClosingParenthesesOnNewLine = policy.MethodCallClosingParenthesesOnNewLine; |
|
spaceWithinMethodCallParentheses = policy.SpacesWithinNewParentheses; |
|
spaceAfterMethodCallParameterComma = policy.SpaceAfterNewParameterComma; |
|
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeNewParameterComma; |
|
spaceWithinEmptyParentheses = policy.SpacesBetweenEmptyNewParentheses; |
|
|
|
rParToken = oce.RParToken; |
|
arguments = oce.Arguments; |
|
} else { |
|
InvocationExpression invocationExpression = node as InvocationExpression; |
|
methodCallArgumentWrapping = policy.MethodCallArgumentWrapping; |
|
newLineAferMethodCallOpenParentheses = policy.NewLineAferMethodCallOpenParentheses; |
|
methodClosingParenthesesOnNewLine = policy.MethodCallClosingParenthesesOnNewLine; |
|
spaceWithinMethodCallParentheses = policy.SpaceWithinMethodCallParentheses; |
|
spaceAfterMethodCallParameterComma = policy.SpaceAfterMethodCallParameterComma; |
|
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeMethodCallParameterComma; |
|
spaceWithinEmptyParentheses = policy.SpaceBetweenEmptyMethodCallParentheses; |
|
|
|
rParToken = invocationExpression.RParToken; |
|
arguments = invocationExpression.Arguments; |
|
} |
|
|
|
if (FormattingMode == ICSharpCode.NRefactory.CSharp.FormattingMode.OnTheFly) |
|
methodCallArgumentWrapping = Wrapping.DoNotChange; |
|
|
|
bool wrapMethodCall = DoWrap(methodCallArgumentWrapping, rParToken, arguments.Count); |
|
if (wrapMethodCall && arguments.Any()) { |
|
if (newLineAferMethodCallOpenParentheses) { |
|
curIndent.Push(IndentType.Continuation); |
|
foreach (var arg in arguments) { |
|
FixStatementIndentation(arg.StartLocation); |
|
} |
|
curIndent.Pop(); |
|
} else { |
|
int extraSpaces = arguments.First().StartLocation.Column - 1 - curIndent.IndentString.Length; |
|
curIndent.ExtraSpaces += extraSpaces; |
|
foreach (var arg in arguments.Skip(1)) { |
|
FixStatementIndentation(arg.StartLocation); |
|
} |
|
curIndent.ExtraSpaces -= extraSpaces; |
|
} |
|
if (!rParToken.IsNull) { |
|
if (methodClosingParenthesesOnNewLine) { |
|
FixStatementIndentation(rParToken.StartLocation); |
|
} else { |
|
ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses); |
|
} |
|
} |
|
} else { |
|
foreach (var arg in arguments) { |
|
if (arg.PrevSibling != null) { |
|
if (methodCallArgumentWrapping == Wrapping.DoNotWrap) { |
|
ForceSpacesBeforeRemoveNewLines(arg, spaceAfterMethodCallParameterComma && arg.PrevSibling.Role == Roles.Comma); |
|
} else { |
|
ForceSpacesBefore(arg, spaceAfterMethodCallParameterComma && arg.PrevSibling.Role == Roles.Comma); |
|
} |
|
} |
|
arg.AcceptVisitor(this); |
|
} |
|
if (!rParToken.IsNull) { |
|
if (methodCallArgumentWrapping == Wrapping.DoNotWrap) { |
|
ForceSpacesBeforeRemoveNewLines(rParToken, arguments.Any() ? spaceWithinMethodCallParentheses : spaceWithinEmptyParentheses); |
|
} else { |
|
bool sameLine = rParToken.GetPrevNode().EndLocation.Line == rParToken.StartLocation.Line; |
|
if (sameLine) { |
|
ForceSpacesBeforeRemoveNewLines(rParToken, arguments.Any() ? spaceWithinMethodCallParentheses : spaceWithinEmptyParentheses); |
|
} else { |
|
FixStatementIndentation(rParToken.StartLocation); |
|
} |
|
} |
|
} |
|
} |
|
if (!rParToken.IsNull) { |
|
foreach (CSharpTokenNode comma in rParToken.Parent.Children.Where(n => n.Role == Roles.Comma)) { |
|
ForceSpacesBefore(comma, spaceBeforeMethodCallParameterComma); |
|
} |
|
} |
|
} |
|
|
|
public override void VisitInvocationExpression(InvocationExpression invocationExpression) |
|
{ |
|
ForceSpacesBefore(invocationExpression.LParToken, policy.SpaceBeforeMethodCallParentheses); |
|
if (invocationExpression.Arguments.Any()) { |
|
ForceSpacesAfter(invocationExpression.LParToken, policy.SpaceWithinMethodCallParentheses); |
|
} else { |
|
ForceSpacesAfter(invocationExpression.LParToken, policy.SpaceBetweenEmptyMethodCallParentheses); |
|
ForceSpacesBefore(invocationExpression.RParToken, policy.SpaceBetweenEmptyMethodCallParentheses); |
|
} |
|
|
|
if (!invocationExpression.Target.IsNull) |
|
invocationExpression.Target.AcceptVisitor(this); |
|
|
|
if (invocationExpression.Target is MemberReferenceExpression) { |
|
var mt = (MemberReferenceExpression)invocationExpression.Target; |
|
if (mt.Target is InvocationExpression) { |
|
if (DoWrap(policy.ChainedMethodCallWrapping, mt.DotToken, 2)) { |
|
curIndent.Push(IndentType.Continuation); |
|
FixStatementIndentation(mt.DotToken.StartLocation); |
|
curIndent.Pop(); |
|
} else { |
|
if (policy.ChainedMethodCallWrapping == Wrapping.DoNotWrap) |
|
ForceSpacesBeforeRemoveNewLines(mt.DotToken, false); |
|
} |
|
} |
|
} |
|
FormatArguments(invocationExpression); |
|
} |
|
|
|
public override void VisitIndexerExpression(IndexerExpression indexerExpression) |
|
{ |
|
ForceSpacesBefore(indexerExpression.LBracketToken, policy.SpacesBeforeBrackets); |
|
ForceSpacesAfter(indexerExpression.LBracketToken, policy.SpacesWithinBrackets); |
|
|
|
if (!indexerExpression.Target.IsNull) |
|
indexerExpression.Target.AcceptVisitor(this); |
|
|
|
FormatArguments(indexerExpression); |
|
|
|
|
|
|
|
} |
|
|
|
public override void VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression) |
|
{ |
|
ForceSpacesAfter(parenthesizedExpression.LParToken, policy.SpacesWithinParentheses); |
|
ForceSpacesBefore(parenthesizedExpression.RParToken, policy.SpacesWithinParentheses); |
|
base.VisitParenthesizedExpression(parenthesizedExpression); |
|
} |
|
|
|
public override void VisitSizeOfExpression(SizeOfExpression sizeOfExpression) |
|
{ |
|
ForceSpacesBefore(sizeOfExpression.LParToken, policy.SpaceBeforeSizeOfParentheses); |
|
ForceSpacesAfter(sizeOfExpression.LParToken, policy.SpacesWithinSizeOfParentheses); |
|
ForceSpacesBefore(sizeOfExpression.RParToken, policy.SpacesWithinSizeOfParentheses); |
|
base.VisitSizeOfExpression(sizeOfExpression); |
|
} |
|
|
|
public override void VisitTypeOfExpression(TypeOfExpression typeOfExpression) |
|
{ |
|
ForceSpacesBefore(typeOfExpression.LParToken, policy.SpaceBeforeTypeOfParentheses); |
|
ForceSpacesAfter(typeOfExpression.LParToken, policy.SpacesWithinTypeOfParentheses); |
|
ForceSpacesBefore(typeOfExpression.RParToken, policy.SpacesWithinTypeOfParentheses); |
|
base.VisitTypeOfExpression(typeOfExpression); |
|
} |
|
|
|
public override void VisitCheckedExpression(CheckedExpression checkedExpression) |
|
{ |
|
ForceSpacesAfter(checkedExpression.LParToken, policy.SpacesWithinCheckedExpressionParantheses); |
|
ForceSpacesBefore(checkedExpression.RParToken, policy.SpacesWithinCheckedExpressionParantheses); |
|
base.VisitCheckedExpression(checkedExpression); |
|
} |
|
|
|
public override void VisitUncheckedExpression(UncheckedExpression uncheckedExpression) |
|
{ |
|
ForceSpacesAfter(uncheckedExpression.LParToken, policy.SpacesWithinCheckedExpressionParantheses); |
|
ForceSpacesBefore(uncheckedExpression.RParToken, policy.SpacesWithinCheckedExpressionParantheses); |
|
base.VisitUncheckedExpression(uncheckedExpression); |
|
} |
|
|
|
public override void VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression) |
|
{ |
|
ForceSpacesBefore(objectCreateExpression.LParToken, policy.SpaceBeforeNewParentheses); |
|
|
|
if (objectCreateExpression.Arguments.Any()) { |
|
if (!objectCreateExpression.LParToken.IsNull) |
|
ForceSpacesAfter(objectCreateExpression.LParToken, policy.SpacesWithinNewParentheses); |
|
} else { |
|
if (!objectCreateExpression.LParToken.IsNull) |
|
ForceSpacesAfter(objectCreateExpression.LParToken, policy.SpacesBetweenEmptyNewParentheses); |
|
} |
|
|
|
if (!objectCreateExpression.Type.IsNull) |
|
objectCreateExpression.Type.AcceptVisitor(this); |
|
|
|
FormatArguments(objectCreateExpression); |
|
|
|
} |
|
|
|
public override void VisitArrayCreateExpression(ArrayCreateExpression arrayObjectCreateExpression) |
|
{ |
|
FormatCommas(arrayObjectCreateExpression, policy.SpaceBeforeMethodCallParameterComma, policy.SpaceAfterMethodCallParameterComma); |
|
base.VisitArrayCreateExpression(arrayObjectCreateExpression); |
|
} |
|
|
|
public override void VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression) |
|
{ |
|
if (DoWrap(policy.ArrayInitializerWrapping, arrayInitializerExpression.RBraceToken, arrayInitializerExpression.Elements.Count)) { |
|
EnforceBraceStyle(policy.ArrayInitializerBraceStyle, arrayInitializerExpression.LBraceToken, arrayInitializerExpression.RBraceToken); |
|
curIndent.Push(IndentType.Block); |
|
foreach (var init in arrayInitializerExpression.Elements) { |
|
FixStatementIndentation(init.StartLocation); |
|
init.AcceptVisitor(this); |
|
} |
|
curIndent.Pop(); |
|
} else if (policy.ArrayInitializerWrapping == Wrapping.DoNotWrap) { |
|
ForceSpacesBeforeRemoveNewLines(arrayInitializerExpression.LBraceToken); |
|
ForceSpacesBeforeRemoveNewLines(arrayInitializerExpression.RBraceToken); |
|
foreach (var init in arrayInitializerExpression.Elements) { |
|
ForceSpacesBeforeRemoveNewLines(init); |
|
init.AcceptVisitor(this); |
|
} |
|
} else { |
|
base.VisitArrayInitializerExpression(arrayInitializerExpression); |
|
} |
|
} |
|
|
|
public override void VisitLambdaExpression(LambdaExpression lambdaExpression) |
|
{ |
|
ForceSpacesAfter(lambdaExpression.ArrowToken, true); |
|
ForceSpacesBefore(lambdaExpression.ArrowToken, true); |
|
|
|
base.VisitLambdaExpression(lambdaExpression); |
|
} |
|
|
|
public override void VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression) |
|
{ |
|
ForceSpacesAfter(namedArgumentExpression.ColonToken, policy.SpaceInNamedArgumentAfterDoubleColon); |
|
base.VisitNamedArgumentExpression(namedArgumentExpression); |
|
} |
|
|
|
public override void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) |
|
{ |
|
ForceSpacesAfter(memberReferenceExpression.DotToken, false); |
|
base.VisitMemberReferenceExpression(memberReferenceExpression); |
|
} |
|
|
|
#endregion |
|
|
|
void ForceSpaceBefore(int offset, bool forceSpace) |
|
{ |
|
bool insertedSpace = false; |
|
do { |
|
char ch = document.GetCharAt(offset); |
|
//Console.WriteLine (ch); |
|
if (!IsSpacing(ch) && (insertedSpace || !forceSpace)) { |
|
break; |
|
} |
|
if (ch == ' ' && forceSpace) { |
|
if (insertedSpace) { |
|
AddChange(offset, 1, null); |
|
} else { |
|
insertedSpace = true; |
|
} |
|
} else if (forceSpace) { |
|
if (!insertedSpace) { |
|
AddChange(offset, IsSpacing(ch) ? 1 : 0, " "); |
|
insertedSpace = true; |
|
} else if (IsSpacing(ch)) { |
|
AddChange(offset, 1, null); |
|
} |
|
} |
|
|
|
offset--; |
|
} while (offset >= 0); |
|
} |
|
|
|
|
|
|
|
/* |
|
int GetLastNonWsChar (LineSegment line, int lastColumn) |
|
{ |
|
int result = -1; |
|
bool inComment = false; |
|
for (int i = 0; i < lastColumn; i++) { |
|
char ch = data.GetCharAt (line.Offset + i); |
|
if (Char.IsWhiteSpace (ch)) |
|
continue; |
|
if (ch == '/' && i + 1 < line.EditableLength && data.GetCharAt (line.Offset + i + 1) == '/') |
|
return result; |
|
if (ch == '/' && i + 1 < line.EditableLength && data.GetCharAt (line.Offset + i + 1) == '*') { |
|
inComment = true; |
|
i++; |
|
continue; |
|
} |
|
if (inComment && ch == '*' && i + 1 < line.EditableLength && data.GetCharAt (line.Offset + i + 1) == '/') { |
|
inComment = false; |
|
i++; |
|
continue; |
|
} |
|
if (!inComment) |
|
result = i; |
|
} |
|
return result; |
|
} |
|
*/ |
|
|
|
|
|
public void FixSemicolon(CSharpTokenNode semicolon) |
|
{ |
|
if (semicolon.IsNull) { |
|
return; |
|
} |
|
int endOffset = document.GetOffset(semicolon.StartLocation); |
|
int offset = endOffset; |
|
while (offset - 1 > 0 && char.IsWhiteSpace (document.GetCharAt (offset - 1))) { |
|
offset--; |
|
} |
|
if (offset < endOffset) { |
|
AddChange(offset, endOffset - offset, null); |
|
} |
|
} |
|
|
|
void PlaceOnNewLine(NewLinePlacement newLine, AstNode keywordNode) |
|
{ |
|
if (keywordNode == null || newLine == NewLinePlacement.DoNotCare) { |
|
return; |
|
} |
|
|
|
var prev = keywordNode.GetPrevNode (); |
|
if (prev is Comment || prev is PreProcessorDirective) |
|
return; |
|
|
|
int offset = document.GetOffset(keywordNode.StartLocation); |
|
|
|
int whitespaceStart = SearchWhitespaceStart(offset); |
|
string indentString = newLine == NewLinePlacement.NewLine ? this.options.EolMarker + this.curIndent.IndentString : " "; |
|
AddChange(whitespaceStart, offset - whitespaceStart, indentString); |
|
} |
|
|
|
string nextStatementIndent = null; |
|
|
|
void FixStatementIndentation(TextLocation location) |
|
{ |
|
if (location.Line < 1 || location.Column < 1) { |
|
Console.WriteLine("invalid location!"); |
|
return; |
|
} |
|
int offset = document.GetOffset(location); |
|
if (offset <= 0) { |
|
Console.WriteLine("possible wrong offset"); |
|
Console.WriteLine(Environment.StackTrace); |
|
return; |
|
} |
|
bool isEmpty = IsLineIsEmptyUpToEol(offset); |
|
int lineStart = SearchWhitespaceLineStart(offset); |
|
string indentString = nextStatementIndent == null ? (isEmpty ? "" : this.options.EolMarker) + this.curIndent.IndentString : nextStatementIndent; |
|
nextStatementIndent = null; |
|
AddChange(lineStart, offset - lineStart, indentString); |
|
} |
|
|
|
void FixIndentation(TextLocation location) |
|
{ |
|
FixIndentation(location, 0); |
|
} |
|
|
|
void FixIndentation(TextLocation location, int relOffset) |
|
{ |
|
if (location.Line < 1 || location.Line > document.LineCount) { |
|
Console.WriteLine("Invalid location " + location); |
|
Console.WriteLine(Environment.StackTrace); |
|
return; |
|
} |
|
|
|
string lineIndent = GetIndentation(location.Line); |
|
string indentString = this.curIndent.IndentString; |
|
if (indentString != lineIndent && location.Column - 1 + relOffset == lineIndent.Length) { |
|
AddChange(document.GetOffset(location.Line, 1), lineIndent.Length, indentString); |
|
} |
|
} |
|
|
|
void FixIndentationForceNewLine(TextLocation location) |
|
{ |
|
string lineIndent = GetIndentation(location.Line); |
|
string indentString = this.curIndent.IndentString; |
|
if (location.Column - 1 == lineIndent.Length) { |
|
AddChange(document.GetOffset(location.Line, 1), lineIndent.Length, indentString); |
|
} else { |
|
int offset = document.GetOffset(location); |
|
int start = SearchWhitespaceLineStart(offset); |
|
if (start > 0) { |
|
char ch = document.GetCharAt(start - 1); |
|
if (ch == '\n') { |
|
start--; |
|
if (start > 1 && document.GetCharAt(start - 1) == '\r') { |
|
start--; |
|
} |
|
} else if (ch == '\r') { |
|
start--; |
|
} |
|
AddChange(start, offset - start, this.options.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(); |
|
} |
|
} |
|
} |
|
|
|
|