mirror of https://github.com/icsharpcode/ILSpy.git
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.
1659 lines
64 KiB
1659 lines
64 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.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 class AstFormattingVisitor : DepthFirstAstVisitor<object, object> |
|
{ |
|
CSharpFormattingOptions policy; |
|
IDocument document; |
|
IActionFactory factory; |
|
List<TextReplaceAction> changes = new List<TextReplaceAction> (); |
|
Indent curIndent = new Indent (); |
|
|
|
public int IndentLevel { |
|
get { |
|
return curIndent.Level; |
|
} |
|
set { |
|
curIndent.Level = value; |
|
} |
|
} |
|
|
|
public int CurrentSpaceIndents { |
|
get; |
|
set; |
|
} |
|
|
|
public List<TextReplaceAction> Changes { |
|
get { return this.changes; } |
|
} |
|
|
|
public bool CorrectBlankLines { |
|
get; |
|
set; |
|
} |
|
|
|
public bool HadErrors { |
|
get; |
|
set; |
|
} |
|
|
|
public string EolMarker { get; set; } |
|
|
|
public AstFormattingVisitor (CSharpFormattingOptions policy, IDocument document, IActionFactory factory, |
|
bool tabsToSpaces = false, int indentationSize = 4) |
|
{ |
|
if (factory == null) |
|
throw new ArgumentNullException ("factory"); |
|
this.policy = policy; |
|
this.document = document; |
|
this.curIndent.TabsToSpaces = tabsToSpaces; |
|
this.curIndent.TabSize = indentationSize; |
|
this.factory = factory; |
|
this.EolMarker = Environment.NewLine; |
|
CorrectBlankLines = true; |
|
} |
|
|
|
public override object VisitCompilationUnit (CompilationUnit unit, object data) |
|
{ |
|
base.VisitCompilationUnit (unit, data); |
|
return null; |
|
} |
|
|
|
public void EnsureBlankLinesAfter (AstNode node, int blankLines) |
|
{ |
|
if (!CorrectBlankLines) |
|
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.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 (!CorrectBlankLines) |
|
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.EolMarker); |
|
AddChange (start, end - start, sb.ToString ()); |
|
} |
|
|
|
public override object VisitUsingDeclaration (UsingDeclaration usingDeclaration, object data) |
|
{ |
|
if (!(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration)) |
|
EnsureBlankLinesBefore (usingDeclaration, policy.BlankLinesBeforeUsings); |
|
if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration)) |
|
EnsureBlankLinesAfter (usingDeclaration, policy.BlankLinesAfterUsings); |
|
|
|
return null; |
|
} |
|
|
|
public override object VisitUsingAliasDeclaration (UsingAliasDeclaration usingDeclaration, object data) |
|
{ |
|
if (!(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration)) |
|
EnsureBlankLinesBefore (usingDeclaration, policy.BlankLinesBeforeUsings); |
|
if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration)) |
|
EnsureBlankLinesAfter (usingDeclaration, policy.BlankLinesAfterUsings); |
|
return null; |
|
} |
|
|
|
public override object VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration, object data) |
|
{ |
|
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) |
|
IndentLevel++; |
|
object result = base.VisitNamespaceDeclaration (namespaceDeclaration, data); |
|
if (policy.IndentNamespaceBody) |
|
IndentLevel--; |
|
FixIndentation (namespaceDeclaration.RBraceToken.StartLocation); |
|
return result; |
|
} |
|
|
|
public override object VisitTypeDeclaration (TypeDeclaration typeDeclaration, object data) |
|
{ |
|
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) |
|
IndentLevel++; |
|
object result = base.VisitTypeDeclaration (typeDeclaration, data); |
|
if (indentBody) |
|
IndentLevel--; |
|
|
|
if (typeDeclaration.NextSibling is TypeDeclaration || typeDeclaration.NextSibling is DelegateDeclaration) |
|
EnsureBlankLinesAfter (typeDeclaration, policy.BlankLinesBetweenTypes); |
|
return result; |
|
} |
|
|
|
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); |
|
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; |
|
} |
|
|
|
public override object VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, object data) |
|
{ |
|
FormatAttributedNode (propertyDeclaration); |
|
bool oneLine = false; |
|
switch (policy.PropertyFormatting) { |
|
case PropertyFormatting.AllowOneLine: |
|
bool isSimple = IsSimpleAccessor (propertyDeclaration.Getter) && IsSimpleAccessor (propertyDeclaration.Setter); |
|
if (!isSimple || propertyDeclaration.LBraceToken.StartLocation.Line != propertyDeclaration.RBraceToken.StartLocation.Line) { |
|
EnforceBraceStyle (policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken); |
|
} else { |
|
ForceSpacesBefore (propertyDeclaration.Getter, true); |
|
ForceSpacesBefore (propertyDeclaration.Setter, true); |
|
ForceSpacesBefore (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) |
|
IndentLevel++; |
|
///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.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 = " "; |
|
} |
|
VisitBlockWithoutFixIndentation (propertyDeclaration.Getter.Body, policy.IndentBlocks, data); |
|
} |
|
} |
|
|
|
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.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 = " "; |
|
} |
|
VisitBlockWithoutFixIndentation (propertyDeclaration.Setter.Body, policy.IndentBlocks, data); |
|
} |
|
} |
|
|
|
if (policy.IndentPropertyBody) |
|
IndentLevel--; |
|
if (IsMember (propertyDeclaration.NextSibling)) |
|
EnsureBlankLinesAfter (propertyDeclaration, policy.BlankLinesBetweenMembers); |
|
return null; |
|
} |
|
|
|
public override object VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, object data) |
|
{ |
|
ForceSpacesBefore (indexerDeclaration.LBracketToken, policy.SpaceBeforeIndexerDeclarationBracket); |
|
ForceSpacesAfter (indexerDeclaration.LBracketToken, policy.SpaceWithinIndexerDeclarationBracket); |
|
ForceSpacesBefore (indexerDeclaration.RBracketToken, policy.SpaceWithinIndexerDeclarationBracket); |
|
|
|
FormatCommas (indexerDeclaration, policy.SpaceBeforeIndexerDeclarationParameterComma, policy.SpaceAfterIndexerDeclarationParameterComma); |
|
|
|
|
|
FormatAttributedNode (indexerDeclaration); |
|
EnforceBraceStyle (policy.PropertyBraceStyle, indexerDeclaration.LBraceToken, indexerDeclaration.RBraceToken); |
|
if (policy.IndentPropertyBody) |
|
IndentLevel++; |
|
|
|
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 = " "; |
|
} |
|
VisitBlockWithoutFixIndentation (indexerDeclaration.Getter.Body, policy.IndentBlocks, data); |
|
} |
|
} |
|
|
|
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 = " "; |
|
} |
|
VisitBlockWithoutFixIndentation (indexerDeclaration.Setter.Body, policy.IndentBlocks, data); |
|
} |
|
} |
|
if (policy.IndentPropertyBody) |
|
IndentLevel--; |
|
if (IsMember (indexerDeclaration.NextSibling)) |
|
EnsureBlankLinesAfter (indexerDeclaration, policy.BlankLinesBetweenMembers); |
|
return null; |
|
} |
|
|
|
static bool IsSimpleEvent (AstNode node) |
|
{ |
|
return node is EventDeclaration; |
|
} |
|
|
|
public override object VisitCustomEventDeclaration (CustomEventDeclaration eventDeclaration, object data) |
|
{ |
|
FormatAttributedNode (eventDeclaration); |
|
EnforceBraceStyle (policy.EventBraceStyle, eventDeclaration.LBraceToken, eventDeclaration.RBraceToken); |
|
if (policy.IndentEventBody) |
|
IndentLevel++; |
|
|
|
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 = " "; |
|
} |
|
|
|
VisitBlockWithoutFixIndentation (eventDeclaration.AddAccessor.Body, policy.IndentBlocks, data); |
|
} |
|
} |
|
|
|
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 = " "; |
|
} |
|
VisitBlockWithoutFixIndentation (eventDeclaration.RemoveAccessor.Body, policy.IndentBlocks, data); |
|
} |
|
} |
|
|
|
if (policy.IndentEventBody) |
|
IndentLevel--; |
|
|
|
if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent (eventDeclaration) && IsSimpleEvent (eventDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenEventFields); |
|
} else if (IsMember (eventDeclaration.NextSibling)) { |
|
EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenMembers); |
|
} |
|
return null; |
|
} |
|
|
|
public override object VisitEventDeclaration (EventDeclaration eventDeclaration, object data) |
|
{ |
|
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); |
|
} |
|
return null; |
|
} |
|
|
|
public override object VisitAccessor (Accessor accessor, object data) |
|
{ |
|
FixIndentationForceNewLine (accessor.StartLocation); |
|
object result = base.VisitAccessor (accessor, data); |
|
return result; |
|
} |
|
|
|
public override object VisitFieldDeclaration (FieldDeclaration fieldDeclaration, object data) |
|
{ |
|
FormatAttributedNode (fieldDeclaration); |
|
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); |
|
} |
|
return base.VisitFieldDeclaration (fieldDeclaration, data); |
|
} |
|
|
|
public override object VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, object data) |
|
{ |
|
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); |
|
} |
|
return base.VisitFixedFieldDeclaration (fixedFieldDeclaration, data); |
|
} |
|
|
|
public override object VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration, object data) |
|
{ |
|
FormatAttributedNode (enumMemberDeclaration); |
|
return base.VisitEnumMemberDeclaration (enumMemberDeclaration, data); |
|
} |
|
|
|
public override object VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, object data) |
|
{ |
|
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); |
|
} |
|
|
|
return base.VisitDelegateDeclaration (delegateDeclaration, data); |
|
} |
|
|
|
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); |
|
} |
|
|
|
public override object VisitMethodDeclaration (MethodDeclaration methodDeclaration, object data) |
|
{ |
|
FormatAttributedNode (methodDeclaration); |
|
|
|
ForceSpacesBefore (methodDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses); |
|
if (methodDeclaration.Parameters.Any ()) { |
|
ForceSpacesAfter (methodDeclaration.LParToken, policy.SpaceWithinMethodDeclarationParentheses); |
|
ForceSpacesBefore (methodDeclaration.RParToken, policy.SpaceWithinMethodDeclarationParentheses); |
|
} else { |
|
ForceSpacesAfter (methodDeclaration.LParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); |
|
ForceSpacesBefore (methodDeclaration.RParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); |
|
} |
|
FormatCommas (methodDeclaration, policy.SpaceBeforeMethodDeclarationParameterComma, policy.SpaceAfterMethodDeclarationParameterComma); |
|
|
|
if (!methodDeclaration.Body.IsNull) { |
|
EnforceBraceStyle (policy.MethodBraceStyle, methodDeclaration.Body.LBraceToken, methodDeclaration.Body.RBraceToken); |
|
if (policy.IndentMethodBody) |
|
IndentLevel++; |
|
base.VisitBlockStatement (methodDeclaration.Body, data); |
|
if (policy.IndentMethodBody) |
|
IndentLevel--; |
|
} |
|
if (IsMember (methodDeclaration.NextSibling)) |
|
EnsureBlankLinesAfter (methodDeclaration, policy.BlankLinesBetweenMembers); |
|
|
|
return null; |
|
} |
|
|
|
public override object VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, object data) |
|
{ |
|
FormatAttributedNode (operatorDeclaration); |
|
|
|
ForceSpacesBefore (operatorDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses); |
|
if (operatorDeclaration.Parameters.Any ()) { |
|
ForceSpacesAfter (operatorDeclaration.LParToken, policy.SpaceWithinMethodDeclarationParentheses); |
|
ForceSpacesBefore (operatorDeclaration.RParToken, policy.SpaceWithinMethodDeclarationParentheses); |
|
} else { |
|
ForceSpacesAfter (operatorDeclaration.LParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); |
|
ForceSpacesBefore (operatorDeclaration.RParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); |
|
} |
|
FormatCommas (operatorDeclaration, policy.SpaceBeforeMethodDeclarationParameterComma, policy.SpaceAfterMethodDeclarationParameterComma); |
|
|
|
if (!operatorDeclaration.Body.IsNull) { |
|
EnforceBraceStyle (policy.MethodBraceStyle, operatorDeclaration.Body.LBraceToken, operatorDeclaration.Body.RBraceToken); |
|
if (policy.IndentMethodBody) |
|
IndentLevel++; |
|
base.VisitBlockStatement (operatorDeclaration.Body, data); |
|
if (policy.IndentMethodBody) |
|
IndentLevel--; |
|
} |
|
if (IsMember (operatorDeclaration.NextSibling)) |
|
EnsureBlankLinesAfter (operatorDeclaration, policy.BlankLinesBetweenMembers); |
|
|
|
return null; |
|
} |
|
|
|
public override object VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, object data) |
|
{ |
|
FormatAttributedNode (constructorDeclaration); |
|
|
|
ForceSpacesBefore (constructorDeclaration.LParToken, policy.SpaceBeforeConstructorDeclarationParentheses); |
|
if (constructorDeclaration.Parameters.Any ()) { |
|
ForceSpacesAfter (constructorDeclaration.LParToken, policy.SpaceWithinConstructorDeclarationParentheses); |
|
ForceSpacesBefore (constructorDeclaration.RParToken, policy.SpaceWithinConstructorDeclarationParentheses); |
|
} else { |
|
ForceSpacesAfter (constructorDeclaration.LParToken, policy.SpaceBetweenEmptyConstructorDeclarationParentheses); |
|
ForceSpacesBefore (constructorDeclaration.RParToken, policy.SpaceBetweenEmptyConstructorDeclarationParentheses); |
|
} |
|
FormatCommas (constructorDeclaration, policy.SpaceBeforeConstructorDeclarationParameterComma, policy.SpaceAfterConstructorDeclarationParameterComma); |
|
|
|
object result = null; |
|
if (!constructorDeclaration.Body.IsNull) { |
|
EnforceBraceStyle (policy.ConstructorBraceStyle, constructorDeclaration.Body.LBraceToken, constructorDeclaration.Body.RBraceToken); |
|
if (policy.IndentMethodBody) |
|
IndentLevel++; |
|
result = base.VisitBlockStatement (constructorDeclaration.Body, data); |
|
if (policy.IndentMethodBody) |
|
IndentLevel--; |
|
} |
|
if (IsMember (constructorDeclaration.NextSibling)) |
|
EnsureBlankLinesAfter (constructorDeclaration, policy.BlankLinesBetweenMembers); |
|
return result; |
|
} |
|
|
|
public override object VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, object data) |
|
{ |
|
FormatAttributedNode (destructorDeclaration); |
|
|
|
CSharpTokenNode lParen = destructorDeclaration.LParToken; |
|
int offset = this.document.GetOffset (lParen.StartLocation); |
|
ForceSpaceBefore (offset, policy.SpaceBeforeConstructorDeclarationParentheses); |
|
|
|
object result = null; |
|
if (!destructorDeclaration.Body.IsNull) { |
|
EnforceBraceStyle (policy.DestructorBraceStyle, destructorDeclaration.Body.LBraceToken, destructorDeclaration.Body.RBraceToken); |
|
if (policy.IndentMethodBody) |
|
IndentLevel++; |
|
result = base.VisitBlockStatement (destructorDeclaration.Body, data); |
|
if (policy.IndentMethodBody) |
|
IndentLevel--; |
|
} |
|
if (IsMember (destructorDeclaration.NextSibling)) |
|
EnsureBlankLinesAfter (destructorDeclaration, policy.BlankLinesBetweenMembers); |
|
return result; |
|
} |
|
|
|
#region Statements |
|
public override object VisitExpressionStatement (ExpressionStatement expressionStatement, object data) |
|
{ |
|
FixStatementIndentation (expressionStatement.StartLocation); |
|
FixSemicolon (expressionStatement.SemicolonToken); |
|
return base.VisitExpressionStatement (expressionStatement, data); |
|
} |
|
|
|
object VisitBlockWithoutFixIndentation (BlockStatement blockStatement, bool indent, object data) |
|
{ |
|
if (indent) |
|
IndentLevel++; |
|
object result = base.VisitBlockStatement (blockStatement, data); |
|
if (indent) |
|
IndentLevel--; |
|
return result; |
|
} |
|
|
|
public override object VisitBlockStatement (BlockStatement blockStatement, object data) |
|
{ |
|
FixIndentation (blockStatement.StartLocation); |
|
object result = VisitBlockWithoutFixIndentation (blockStatement, policy.IndentBlocks, data); |
|
FixIndentation (blockStatement.EndLocation, -1); |
|
return result; |
|
} |
|
|
|
public override object VisitComment (Comment comment, object data) |
|
{ |
|
if (comment.StartsLine && !HadErrors && comment.StartLocation.Column > 1) |
|
FixIndentation (comment.StartLocation); |
|
return null; |
|
} |
|
|
|
public override object VisitBreakStatement (BreakStatement breakStatement, object data) |
|
{ |
|
FixStatementIndentation (breakStatement.StartLocation); |
|
return null; |
|
} |
|
|
|
public override object VisitCheckedStatement (CheckedStatement checkedStatement, object data) |
|
{ |
|
FixStatementIndentation (checkedStatement.StartLocation); |
|
return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, checkedStatement.Body); |
|
} |
|
|
|
public override object VisitContinueStatement (ContinueStatement continueStatement, object data) |
|
{ |
|
FixStatementIndentation (continueStatement.StartLocation); |
|
return null; |
|
} |
|
|
|
public override object VisitEmptyStatement (EmptyStatement emptyStatement, object data) |
|
{ |
|
FixStatementIndentation (emptyStatement.StartLocation); |
|
return null; |
|
} |
|
|
|
public override object VisitFixedStatement (FixedStatement fixedStatement, object data) |
|
{ |
|
FixStatementIndentation (fixedStatement.StartLocation); |
|
return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, fixedStatement.EmbeddedStatement); |
|
} |
|
|
|
public override object VisitForeachStatement (ForeachStatement foreachStatement, object data) |
|
{ |
|
FixStatementIndentation (foreachStatement.StartLocation); |
|
ForceSpacesBefore (foreachStatement.LParToken, policy.SpaceBeforeForeachParentheses); |
|
|
|
ForceSpacesAfter (foreachStatement.LParToken, policy.SpacesWithinForeachParentheses); |
|
ForceSpacesBefore (foreachStatement.RParToken, policy.SpacesWithinForeachParentheses); |
|
|
|
return FixEmbeddedStatment (policy.StatementBraceStyle, policy.ForEachBraceForcement, foreachStatement.EmbeddedStatement); |
|
} |
|
|
|
object FixEmbeddedStatment (BraceStyle braceStyle, BraceForcement braceForcement, AstNode node) |
|
{ |
|
return FixEmbeddedStatment (braceStyle, braceForcement, null, false, node); |
|
} |
|
|
|
object FixEmbeddedStatment (BraceStyle braceStyle, BraceForcement braceForcement, CSharpTokenNode token, bool allowInLine, AstNode node) |
|
{ |
|
if (node == null) |
|
return null; |
|
int originalLevel = curIndent.Level; |
|
bool isBlock = node is BlockStatement; |
|
switch (braceForcement) { |
|
case BraceForcement.DoNotChange: |
|
//nothing |
|
break; |
|
case BraceForcement.AddBraces: |
|
if (!isBlock) { |
|
AstNode n = node.Parent.GetCSharpNodeBefore (node); |
|
int start = document.GetOffset (n.EndLocation); |
|
var next = n.GetNextNode (); |
|
int offset = document.GetOffset (next.StartLocation); |
|
string startBrace = ""; |
|
switch (braceStyle) { |
|
case BraceStyle.EndOfLineWithoutSpace: |
|
startBrace = "{"; |
|
break; |
|
case BraceStyle.EndOfLine: |
|
startBrace = " {"; |
|
break; |
|
case BraceStyle.NextLine: |
|
startBrace = this.EolMarker + curIndent.IndentString + "{"; |
|
break; |
|
case BraceStyle.NextLineShifted2: |
|
case BraceStyle.NextLineShifted: |
|
startBrace = this.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "{"; |
|
break; |
|
} |
|
if (IsLineIsEmptyUpToEol (document.GetOffset (node.StartLocation))) |
|
startBrace += this.EolMarker + GetIndentation (node.StartLocation.Line); |
|
AddChange (start, offset - start, 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); |
|
|
|
AddChange (start, offset1 - start + 1, null); |
|
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 { |
|
EnforceBraceStyle (braceStyle, block.LBraceToken, block.RBraceToken); |
|
} |
|
if (braceStyle == BraceStyle.NextLineShifted2) |
|
curIndent.Level++; |
|
} else { |
|
if (allowInLine && token.StartLocation.Line == node.EndLocation.Line) { |
|
nextStatementIndent = " "; |
|
} |
|
} |
|
if (policy.IndentBlocks && |
|
!(policy.AlignEmbeddedIfStatements && node is IfElseStatement && node.Parent is IfElseStatement || |
|
policy.AlignEmbeddedUsingStatements && node is UsingStatement && node.Parent is UsingStatement)) |
|
curIndent.Level++; |
|
object result = isBlock ? base.VisitBlockStatement ((BlockStatement)node, null) : node.AcceptVisitor (this, null); |
|
curIndent.Level = originalLevel; |
|
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.EolMarker + curIndent.IndentString + "}"; |
|
break; |
|
case BraceStyle.EndOfLine: |
|
startBrace = this.EolMarker + curIndent.IndentString + "}"; |
|
break; |
|
case BraceStyle.NextLine: |
|
startBrace = this.EolMarker + curIndent.IndentString + "}"; |
|
break; |
|
case BraceStyle.NextLineShifted2: |
|
case BraceStyle.NextLineShifted: |
|
startBrace = this.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "}"; |
|
break; |
|
} |
|
if (startBrace != null) |
|
AddChange (offset, 0, startBrace); |
|
} |
|
break; |
|
} |
|
return result; |
|
} |
|
|
|
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.EolMarker + curIndent.IndentString; |
|
break; |
|
case BraceStyle.EndOfLine: |
|
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 = " "; |
|
} |
|
endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : this.EolMarker + curIndent.IndentString; |
|
break; |
|
case BraceStyle.NextLine: |
|
startIndent = this.EolMarker + curIndent.IndentString; |
|
endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : this.EolMarker + curIndent.IndentString; |
|
break; |
|
case BraceStyle.NextLineShifted2: |
|
case BraceStyle.NextLineShifted: |
|
startIndent = this.EolMarker + curIndent.IndentString + curIndent.SingleIndent; |
|
endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString + curIndent.SingleIndent : this.EolMarker + curIndent.IndentString + curIndent.SingleIndent; |
|
break; |
|
} |
|
|
|
if (lbraceOffset > 0 && startIndent != null) |
|
AddChange (whitespaceStart, lbraceOffset - whitespaceStart, startIndent); |
|
if (rbraceOffset > 0 && endIndent != null) |
|
AddChange (whitespaceEnd, rbraceOffset - whitespaceEnd, endIndent); |
|
} |
|
|
|
void AddChange (int offset, int removedChars, string insertedText) |
|
{ |
|
if (changes.Any (c => c.Offset == offset && c.RemovedChars == removedChars |
|
&& c.InsertedText == insertedText)) |
|
return; |
|
string currentText = document.GetText (offset, removedChars); |
|
if (currentText == insertedText) |
|
return; |
|
if (currentText.Any (c => !(char.IsWhiteSpace (c) || c == '\r' || c == '\t' || c == '{' || c == '}'))) |
|
throw new InvalidOperationException ("Tried to remove non ws chars: '" + currentText + "'"); |
|
foreach (var change in changes) { |
|
if (change.Offset == offset) { |
|
if (removedChars > 0 && insertedText == change.InsertedText) { |
|
change.RemovedChars = removedChars; |
|
// change.InsertedText = insertedText; |
|
return; |
|
} |
|
if (!string.IsNullOrEmpty (change.InsertedText)) { |
|
change.InsertedText += insertedText; |
|
} else { |
|
change.InsertedText = insertedText; |
|
} |
|
change.RemovedChars = System.Math.Max (removedChars, change.RemovedChars); |
|
return; |
|
} |
|
} |
|
//Console.WriteLine ("offset={0}, removedChars={1}, insertedText={2}", offset, removedChars, insertedText == null ? "<null>" : insertedText.Replace ("\n", "\\n").Replace ("\r", "\\r").Replace ("\t", "\\t").Replace (" ", ".")); |
|
//Console.WriteLine (Environment.StackTrace); |
|
|
|
changes.Add (factory.CreateTextReplaceAction (offset, removedChars, insertedText)); |
|
} |
|
|
|
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 object VisitForStatement (ForStatement forStatement, object data) |
|
{ |
|
FixStatementIndentation (forStatement.StartLocation); |
|
foreach (AstNode node in forStatement.Children) { |
|
if (node.Role == ForStatement.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); |
|
|
|
return FixEmbeddedStatment (policy.StatementBraceStyle, policy.ForBraceForcement, forStatement.EmbeddedStatement); |
|
} |
|
|
|
public override object VisitGotoStatement (GotoStatement gotoStatement, object data) |
|
{ |
|
FixStatementIndentation (gotoStatement.StartLocation); |
|
return VisitChildren (gotoStatement, data); |
|
} |
|
|
|
public override object VisitIfElseStatement (IfElseStatement ifElseStatement, object data) |
|
{ |
|
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, data); |
|
|
|
if (!ifElseStatement.TrueStatement.IsNull) |
|
FixEmbeddedStatment (policy.StatementBraceStyle, policy.IfElseBraceForcement, ifElseStatement.IfToken, policy.AllowIfBlockInline, ifElseStatement.TrueStatement); |
|
|
|
if (!ifElseStatement.FalseStatement.IsNull) { |
|
PlaceOnNewLine (policy.PlaceElseOnNewLine || !(ifElseStatement.TrueStatement is BlockStatement) && policy.IfElseBraceForcement != BraceForcement.AddBraces, ifElseStatement.ElseToken); |
|
var forcement = policy.IfElseBraceForcement; |
|
if (ifElseStatement.FalseStatement is IfElseStatement) { |
|
forcement = BraceForcement.DoNotChange; |
|
PlaceOnNewLine (policy.PlaceElseIfOnNewLine, ((IfElseStatement)ifElseStatement.FalseStatement).IfToken); |
|
} |
|
FixEmbeddedStatment (policy.StatementBraceStyle, forcement, ifElseStatement.ElseToken, policy.AllowIfBlockInline, ifElseStatement.FalseStatement); |
|
} |
|
|
|
return null; |
|
} |
|
|
|
public override object VisitLabelStatement (LabelStatement labelStatement, object data) |
|
{ |
|
// TODO |
|
return VisitChildren (labelStatement, data); |
|
} |
|
|
|
public override object VisitLockStatement (LockStatement lockStatement, object data) |
|
{ |
|
FixStatementIndentation (lockStatement.StartLocation); |
|
ForceSpacesBefore (lockStatement.LParToken, policy.SpaceBeforeLockParentheses); |
|
|
|
ForceSpacesAfter (lockStatement.LParToken, policy.SpacesWithinLockParentheses); |
|
ForceSpacesBefore (lockStatement.RParToken, policy.SpacesWithinLockParentheses); |
|
|
|
return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, lockStatement.EmbeddedStatement); |
|
} |
|
|
|
public override object VisitReturnStatement (ReturnStatement returnStatement, object data) |
|
{ |
|
FixStatementIndentation (returnStatement.StartLocation); |
|
return VisitChildren (returnStatement, data); |
|
} |
|
|
|
public override object VisitSwitchStatement (SwitchStatement switchStatement, object data) |
|
{ |
|
FixStatementIndentation (switchStatement.StartLocation); |
|
ForceSpacesBefore (switchStatement.LParToken, policy.SpaceBeforeSwitchParentheses); |
|
|
|
ForceSpacesAfter (switchStatement.LParToken, policy.SpacesWithinSwitchParentheses); |
|
ForceSpacesBefore (switchStatement.RParToken, policy.SpacesWithinSwitchParentheses); |
|
|
|
EnforceBraceStyle (policy.StatementBraceStyle, switchStatement.LBraceToken, switchStatement.RBraceToken); |
|
object result = VisitChildren (switchStatement, data); |
|
return result; |
|
} |
|
|
|
public override object VisitSwitchSection (SwitchSection switchSection, object data) |
|
{ |
|
if (policy.IndentSwitchBody) |
|
curIndent.Level++; |
|
|
|
foreach (CaseLabel label in switchSection.CaseLabels) { |
|
FixStatementIndentation (label.StartLocation); |
|
} |
|
if (policy.IndentCaseBody) |
|
curIndent.Level++; |
|
|
|
foreach (var stmt in switchSection.Statements) { |
|
if (stmt is BreakStatement && !policy.IndentBreakStatements && policy.IndentCaseBody) { |
|
curIndent.Level--; |
|
stmt.AcceptVisitor (this, null); |
|
curIndent.Level++; |
|
continue; |
|
} |
|
stmt.AcceptVisitor (this, null); |
|
} |
|
if (policy.IndentCaseBody) |
|
curIndent.Level--; |
|
|
|
if (policy.IndentSwitchBody) |
|
curIndent.Level--; |
|
return null; |
|
} |
|
|
|
public override object VisitCaseLabel (CaseLabel caseLabel, object data) |
|
{ |
|
// handled in switchsection |
|
return null; |
|
} |
|
|
|
public override object VisitThrowStatement (ThrowStatement throwStatement, object data) |
|
{ |
|
FixStatementIndentation (throwStatement.StartLocation); |
|
return VisitChildren (throwStatement, data); |
|
} |
|
|
|
public override object VisitTryCatchStatement (TryCatchStatement tryCatchStatement, object data) |
|
{ |
|
FixStatementIndentation (tryCatchStatement.StartLocation); |
|
|
|
if (!tryCatchStatement.TryBlock.IsNull) |
|
FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, tryCatchStatement.TryBlock); |
|
|
|
foreach (CatchClause clause in tryCatchStatement.CatchClauses) { |
|
PlaceOnNewLine (policy.PlaceCatchOnNewLine, 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.PlaceFinallyOnNewLine, tryCatchStatement.FinallyToken); |
|
|
|
FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, tryCatchStatement.FinallyBlock); |
|
} |
|
|
|
return VisitChildren (tryCatchStatement, data); |
|
} |
|
|
|
public override object VisitCatchClause (CatchClause catchClause, object data) |
|
{ |
|
// Handled in TryCatchStatement |
|
return null; |
|
} |
|
|
|
public override object VisitUncheckedStatement (UncheckedStatement uncheckedStatement, object data) |
|
{ |
|
FixStatementIndentation (uncheckedStatement.StartLocation); |
|
return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, uncheckedStatement.Body); |
|
} |
|
|
|
public override object VisitUnsafeStatement (UnsafeStatement unsafeStatement, object data) |
|
{ |
|
FixStatementIndentation (unsafeStatement.StartLocation); |
|
return FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, unsafeStatement.Body); |
|
} |
|
|
|
public override object VisitUsingStatement (UsingStatement usingStatement, object data) |
|
{ |
|
FixStatementIndentation (usingStatement.StartLocation); |
|
ForceSpacesBefore (usingStatement.LParToken, policy.SpaceBeforeUsingParentheses); |
|
|
|
ForceSpacesAfter (usingStatement.LParToken, policy.SpacesWithinUsingParentheses); |
|
ForceSpacesBefore (usingStatement.RParToken, policy.SpacesWithinUsingParentheses); |
|
|
|
return FixEmbeddedStatment (policy.StatementBraceStyle, policy.UsingBraceForcement, usingStatement.EmbeddedStatement); |
|
} |
|
|
|
public override object VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, object data) |
|
{ |
|
if (!variableDeclarationStatement.SemicolonToken.IsNull) |
|
FixStatementIndentation (variableDeclarationStatement.StartLocation); |
|
|
|
if ((variableDeclarationStatement.Modifiers & Modifiers.Const) == Modifiers.Const) { |
|
ForceSpacesAround (variableDeclarationStatement.Type, true); |
|
} else { |
|
ForceSpacesAfter (variableDeclarationStatement.Type, true); |
|
} |
|
foreach (var initializer in variableDeclarationStatement.Variables) { |
|
initializer.AcceptVisitor (this, data); |
|
} |
|
FormatCommas (variableDeclarationStatement, policy.SpaceBeforeLocalVariableDeclarationComma, policy.SpaceAfterLocalVariableDeclarationComma); |
|
FixSemicolon (variableDeclarationStatement.SemicolonToken); |
|
return null; |
|
} |
|
|
|
public override object VisitDoWhileStatement (DoWhileStatement doWhileStatement, object data) |
|
{ |
|
FixStatementIndentation (doWhileStatement.StartLocation); |
|
PlaceOnNewLine (policy.PlaceWhileOnNewLine, doWhileStatement.WhileToken); |
|
return FixEmbeddedStatment (policy.StatementBraceStyle, policy.WhileBraceForcement, doWhileStatement.EmbeddedStatement); |
|
} |
|
|
|
public override object VisitWhileStatement (WhileStatement whileStatement, object data) |
|
{ |
|
FixStatementIndentation (whileStatement.StartLocation); |
|
ForceSpacesBefore (whileStatement.LParToken, policy.SpaceBeforeWhileParentheses); |
|
|
|
ForceSpacesAfter (whileStatement.LParToken, policy.SpacesWithinWhileParentheses); |
|
ForceSpacesBefore (whileStatement.RParToken, policy.SpacesWithinWhileParentheses); |
|
|
|
return FixEmbeddedStatment (policy.StatementBraceStyle, policy.WhileBraceForcement, whileStatement.EmbeddedStatement); |
|
} |
|
|
|
public override object VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement, object data) |
|
{ |
|
FixStatementIndentation (yieldBreakStatement.StartLocation); |
|
return null; |
|
} |
|
|
|
public override object VisitYieldReturnStatement (YieldReturnStatement yieldStatement, object data) |
|
{ |
|
FixStatementIndentation (yieldStatement.StartLocation); |
|
return null; |
|
} |
|
|
|
public override object VisitVariableInitializer (VariableInitializer variableInitializer, object data) |
|
{ |
|
if (!variableInitializer.AssignToken.IsNull) |
|
ForceSpacesAround (variableInitializer.AssignToken, policy.SpaceAroundAssignment); |
|
if (!variableInitializer.Initializer.IsNull) |
|
variableInitializer.Initializer.AcceptVisitor (this, data); |
|
return data; |
|
} |
|
|
|
#endregion |
|
|
|
#region Expressions |
|
public override object VisitComposedType (ComposedType composedType, object data) |
|
{ |
|
var spec = composedType.ArraySpecifiers.FirstOrDefault (); |
|
if (spec != null) |
|
ForceSpacesBefore (spec.LBracketToken, policy.SpaceBeforeArrayDeclarationBrackets); |
|
|
|
return base.VisitComposedType (composedType, data); |
|
} |
|
|
|
public override object VisitAssignmentExpression (AssignmentExpression assignmentExpression, object data) |
|
{ |
|
ForceSpacesAround (assignmentExpression.OperatorToken, policy.SpaceAroundAssignment); |
|
return base.VisitAssignmentExpression (assignmentExpression, data); |
|
} |
|
|
|
public override object VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression, object data) |
|
{ |
|
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); |
|
|
|
return base.VisitBinaryOperatorExpression (binaryOperatorExpression, data); |
|
} |
|
|
|
public override object VisitConditionalExpression (ConditionalExpression conditionalExpression, object data) |
|
{ |
|
ForceSpacesBefore (conditionalExpression.QuestionMarkToken, policy.SpaceBeforeConditionalOperatorCondition); |
|
ForceSpacesAfter (conditionalExpression.QuestionMarkToken, policy.SpaceAfterConditionalOperatorCondition); |
|
ForceSpacesBefore (conditionalExpression.ColonToken, policy.SpaceBeforeConditionalOperatorSeparator); |
|
ForceSpacesAfter (conditionalExpression.ColonToken, policy.SpaceAfterConditionalOperatorSeparator); |
|
return base.VisitConditionalExpression (conditionalExpression, data); |
|
} |
|
|
|
public override object VisitCastExpression (CastExpression castExpression, object data) |
|
{ |
|
if (castExpression.RParToken != null) { |
|
ForceSpacesAfter (castExpression.LParToken, policy.SpacesWithinCastParentheses); |
|
ForceSpacesBefore (castExpression.RParToken, policy.SpacesWithinCastParentheses); |
|
|
|
ForceSpacesAfter (castExpression.RParToken, policy.SpaceAfterTypecast); |
|
} |
|
return base.VisitCastExpression (castExpression, data); |
|
} |
|
|
|
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 == FieldDeclaration.Roles.Comma)) { |
|
ForceSpacesAfter (comma, after); |
|
ForceSpacesBefore (comma, before); |
|
} |
|
} |
|
|
|
public override object VisitInvocationExpression (InvocationExpression invocationExpression, object data) |
|
{ |
|
ForceSpacesBefore (invocationExpression.LParToken, policy.SpaceBeforeMethodCallParentheses); |
|
if (invocationExpression.Arguments.Any ()) { |
|
ForceSpacesAfter (invocationExpression.LParToken, policy.SpaceWithinMethodCallParentheses); |
|
ForceSpacesBefore (invocationExpression.RParToken, policy.SpaceWithinMethodCallParentheses); |
|
} else { |
|
ForceSpacesAfter (invocationExpression.LParToken, policy.SpaceBetweenEmptyMethodCallParentheses); |
|
ForceSpacesBefore (invocationExpression.RParToken, policy.SpaceBetweenEmptyMethodCallParentheses); |
|
} |
|
FormatCommas (invocationExpression, policy.SpaceBeforeMethodCallParameterComma, policy.SpaceAfterMethodCallParameterComma); |
|
|
|
return base.VisitInvocationExpression (invocationExpression, data); |
|
} |
|
|
|
public override object VisitIndexerExpression (IndexerExpression indexerExpression, object data) |
|
{ |
|
ForceSpacesBefore (indexerExpression.LBracketToken, policy.SpacesBeforeBrackets); |
|
ForceSpacesAfter (indexerExpression.LBracketToken, policy.SpacesWithinBrackets); |
|
ForceSpacesBefore (indexerExpression.RBracketToken, policy.SpacesWithinBrackets); |
|
FormatCommas (indexerExpression, policy.SpaceBeforeBracketComma, policy.SpaceAfterBracketComma); |
|
|
|
return base.VisitIndexerExpression (indexerExpression, data); |
|
} |
|
|
|
public override object VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, object data) |
|
{ |
|
ForceSpacesAfter (parenthesizedExpression.LParToken, policy.SpacesWithinParentheses); |
|
ForceSpacesBefore (parenthesizedExpression.RParToken, policy.SpacesWithinParentheses); |
|
return base.VisitParenthesizedExpression (parenthesizedExpression, data); |
|
} |
|
|
|
public override object VisitSizeOfExpression (SizeOfExpression sizeOfExpression, object data) |
|
{ |
|
ForceSpacesBefore (sizeOfExpression.LParToken, policy.SpaceBeforeSizeOfParentheses); |
|
ForceSpacesAfter (sizeOfExpression.LParToken, policy.SpacesWithinSizeOfParentheses); |
|
ForceSpacesBefore (sizeOfExpression.RParToken, policy.SpacesWithinSizeOfParentheses); |
|
return base.VisitSizeOfExpression (sizeOfExpression, data); |
|
} |
|
|
|
public override object VisitTypeOfExpression (TypeOfExpression typeOfExpression, object data) |
|
{ |
|
ForceSpacesBefore (typeOfExpression.LParToken, policy.SpaceBeforeTypeOfParentheses); |
|
ForceSpacesAfter (typeOfExpression.LParToken, policy.SpacesWithinTypeOfParentheses); |
|
ForceSpacesBefore (typeOfExpression.RParToken, policy.SpacesWithinTypeOfParentheses); |
|
return base.VisitTypeOfExpression (typeOfExpression, data); |
|
} |
|
|
|
public override object VisitCheckedExpression (CheckedExpression checkedExpression, object data) |
|
{ |
|
ForceSpacesAfter (checkedExpression.LParToken, policy.SpacesWithinCheckedExpressionParantheses); |
|
ForceSpacesBefore (checkedExpression.RParToken, policy.SpacesWithinCheckedExpressionParantheses); |
|
return base.VisitCheckedExpression (checkedExpression, data); |
|
} |
|
|
|
public override object VisitUncheckedExpression (UncheckedExpression uncheckedExpression, object data) |
|
{ |
|
ForceSpacesAfter (uncheckedExpression.LParToken, policy.SpacesWithinCheckedExpressionParantheses); |
|
ForceSpacesBefore (uncheckedExpression.RParToken, policy.SpacesWithinCheckedExpressionParantheses); |
|
return base.VisitUncheckedExpression (uncheckedExpression, data); |
|
} |
|
|
|
public override object VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression, object data) |
|
{ |
|
ForceSpacesBefore (objectCreateExpression.LParToken, policy.SpaceBeforeNewParentheses); |
|
|
|
if (objectCreateExpression.Arguments.Any ()) { |
|
if (!objectCreateExpression.LParToken.IsNull) |
|
ForceSpacesAfter (objectCreateExpression.LParToken, policy.SpacesWithinNewParentheses); |
|
if (!objectCreateExpression.RParToken.IsNull) |
|
ForceSpacesBefore (objectCreateExpression.RParToken, policy.SpacesWithinNewParentheses); |
|
} else { |
|
if (!objectCreateExpression.LParToken.IsNull) |
|
ForceSpacesAfter (objectCreateExpression.LParToken, policy.SpacesBetweenEmptyNewParentheses); |
|
if (!objectCreateExpression.RParToken.IsNull) |
|
ForceSpacesBefore (objectCreateExpression.RParToken, policy.SpacesBetweenEmptyNewParentheses); |
|
} |
|
FormatCommas (objectCreateExpression, policy.SpaceBeforeNewParameterComma, policy.SpaceAfterNewParameterComma); |
|
|
|
return base.VisitObjectCreateExpression (objectCreateExpression, data); |
|
} |
|
|
|
public override object VisitArrayCreateExpression (ArrayCreateExpression arrayObjectCreateExpression, object data) |
|
{ |
|
FormatCommas (arrayObjectCreateExpression, policy.SpaceBeforeMethodCallParameterComma, policy.SpaceAfterMethodCallParameterComma); |
|
return base.VisitArrayCreateExpression (arrayObjectCreateExpression, data); |
|
} |
|
|
|
public override object VisitLambdaExpression (LambdaExpression lambdaExpression, object data) |
|
{ |
|
ForceSpacesAfter (lambdaExpression.ArrowToken, true); |
|
ForceSpacesBefore (lambdaExpression.ArrowToken, true); |
|
|
|
return base.VisitLambdaExpression (lambdaExpression, data); |
|
} |
|
|
|
#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 (bool newLine, AstNode keywordNode) |
|
{ |
|
if (keywordNode == null) |
|
return; |
|
int offset = document.GetOffset (keywordNode.StartLocation); |
|
|
|
int whitespaceStart = SearchWhitespaceStart (offset); |
|
string indentString = newLine ? this.EolMarker + this.curIndent.IndentString : " "; |
|
AddChange (whitespaceStart, offset - whitespaceStart, indentString); |
|
} |
|
|
|
string nextStatementIndent = null; |
|
|
|
void FixStatementIndentation (TextLocation location) |
|
{ |
|
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.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.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(); |
|
} |
|
} |
|
}
|
|
|