2
// AstFormattingVisitor.cs
5
// Mike KrĆ¼ger <mkrueger@novell.com>
7
// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
10
// of this software and associated documentation files (the "Software"), to deal
11
// in the Software without restriction, including without limitation the rights
12
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
// copies of the Software, and to permit persons to whom the Software is
14
// furnished to do so, subject to the following conditions:
16
// The above copyright notice and this permission notice shall be included in
17
// all copies or substantial portions of the Software.
19
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
using System.Diagnostics;
29
using System.Collections.Generic;
31
using ICSharpCode.NRefactory.Editor;
32
using ICSharpCode.NRefactory.TypeSystem;
33
using ICSharpCode.NRefactory.CSharp.Refactoring;
35
namespace ICSharpCode.NRefactory.CSharp
37
public enum FormattingMode {
42
public class AstFormattingVisitor : DepthFirstAstVisitor
44
sealed class TextReplaceAction
46
internal readonly int Offset;
47
internal readonly int RemovalLength;
48
internal readonly string NewText;
49
internal TextReplaceAction DependsOn;
52
internal readonly string StackTrace;
55
public TextReplaceAction (int offset, int removalLength, string newText)
58
this.RemovalLength = removalLength;
59
this.NewText = newText ?? string.Empty;
61
this.StackTrace = Environment.StackTrace;
65
public override bool Equals(object obj)
67
TextReplaceAction other = obj as TextReplaceAction;
71
return this.Offset == other.Offset && this.RemovalLength == other.RemovalLength && this.NewText == other.NewText;
74
public override int GetHashCode()
79
public override string ToString()
81
return string.Format("[TextReplaceAction: Offset={0}, RemovalLength={1}, NewText={2}]", Offset, RemovalLength, NewText);
85
CSharpFormattingOptions policy;
87
List<TextReplaceAction> changes = new List<TextReplaceAction> ();
89
readonly TextEditorOptions options;
91
public FormattingMode FormattingMode {
96
public bool HadErrors {
101
public DomRegion FormattingRegion {
106
public AstFormattingVisitor(CSharpFormattingOptions policy, IDocument document, TextEditorOptions options = null)
108
if (policy == null) {
109
throw new ArgumentNullException("policy");
111
if (document == null) {
112
throw new ArgumentNullException("document");
114
this.policy = policy;
115
this.document = document;
116
this.options = options ?? TextEditorOptions.Default;
117
curIndent = new Indent(this.options);
120
protected virtual void VisitChildren (AstNode node)
122
if (!FormattingRegion.IsEmpty) {
123
if (node.EndLocation < FormattingRegion.Begin || node.StartLocation > FormattingRegion.End)
128
for (var child = node.FirstChild; child != null; child = next) {
129
// Store next to allow the loop to continue
130
// if the visitor removes/replaces child.
131
next = child.NextSibling;
132
child.AcceptVisitor (this);
137
/// Applies the changes to the input document.
139
public void ApplyChanges()
141
ApplyChanges(0, document.TextLength, document.Replace, (o, l, v) => document.GetText(o, l) == v);
144
public void ApplyChanges(int startOffset, int length)
146
ApplyChanges(startOffset, length, document.Replace, (o, l, v) => document.GetText(o, l) == v);
150
/// Applies the changes to the given Script instance.
152
public void ApplyChanges(Script script)
154
ApplyChanges(0, document.TextLength, script.Replace);
157
public void ApplyChanges(int startOffset, int length, Script script)
159
ApplyChanges(startOffset, length, script.Replace);
162
public void ApplyChanges(int startOffset, int length, Action<int, int, string> documentReplace, Func<int, int, string, bool> filter = null)
164
int endOffset = startOffset + length;
165
TextReplaceAction previousChange = null;
167
var depChanges = new List<TextReplaceAction> ();
168
foreach (var change in changes.OrderBy(c => c.Offset)) {
169
if (previousChange != null) {
170
if (change.Equals(previousChange)) {
171
// ignore duplicate changes
174
if (change.Offset < previousChange.Offset + previousChange.RemovalLength) {
176
Console.WriteLine ("change 1:" + change);
177
Console.WriteLine (change.StackTrace);
179
Console.WriteLine ("change 2:" + change);
180
Console.WriteLine (previousChange.StackTrace);
182
throw new InvalidOperationException ("Detected overlapping changes " + change + "/" + previousChange);
185
previousChange = change;
187
bool skipChange = change.Offset < startOffset || change.Offset > endOffset;
188
skipChange |= filter != null && filter(change.Offset + delta, change.RemovalLength, change.NewText);
189
skipChange &= !depChanges.Contains(change);
192
documentReplace(change.Offset + delta, change.RemovalLength, change.NewText);
193
delta += change.NewText.Length - change.RemovalLength;
194
if (change.DependsOn != null) {
195
depChanges.Add(change.DependsOn);
202
public override void VisitCompilationUnit(CompilationUnit unit)
204
base.VisitCompilationUnit(unit);
207
public void EnsureBlankLinesAfter(AstNode node, int blankLines)
209
if (FormattingMode != FormattingMode.Intrusive)
211
var loc = node.EndLocation;
215
} while (line < document.LineCount && IsSpacing(document.GetLineByNumber(line)));
216
var start = document.GetOffset(node.EndLocation);
218
int foundBlankLines = line - loc.Line - 1;
220
StringBuilder sb = new StringBuilder();
221
for (int i = 0; i < blankLines - foundBlankLines; i++) {
222
sb.Append(this.options.EolMarker);
226
while (ws < document.TextLength && IsSpacing (document.GetCharAt (ws))) {
229
int removedChars = ws - start;
230
if (foundBlankLines > blankLines) {
231
removedChars += document.GetLineByNumber(loc.Line + foundBlankLines - blankLines).EndOffset
232
- document.GetLineByNumber(loc.Line).EndOffset;
234
AddChange(start, removedChars, sb.ToString());
237
public void EnsureBlankLinesBefore(AstNode node, int blankLines)
239
if (FormattingMode != FormattingMode.Intrusive)
241
var loc = node.StartLocation;
245
} while (line > 0 && IsSpacing(document.GetLineByNumber(line)));
246
int end = document.GetOffset(loc.Line, 1);
247
int start = document.GetOffset(line + 1, 1);
248
StringBuilder sb = new StringBuilder ();
249
for (int i = 0; i < blankLines; i++) {
250
sb.Append(this.options.EolMarker);
252
if (end - start == 0 && sb.Length == 0)
254
AddChange(start, end - start, sb.ToString());
257
public override void VisitUsingDeclaration(UsingDeclaration usingDeclaration)
259
if (usingDeclaration.PrevSibling != null && !(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration)) {
260
EnsureBlankLinesBefore(usingDeclaration, policy.BlankLinesBeforeUsings);
261
} else if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration)) {
262
FixIndentationForceNewLine(usingDeclaration.StartLocation);
263
EnsureBlankLinesAfter(usingDeclaration, policy.BlankLinesAfterUsings);
265
FixIndentationForceNewLine(usingDeclaration.StartLocation);
269
public override void VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration)
271
if (usingDeclaration.PrevSibling != null && !(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration)) {
272
EnsureBlankLinesBefore(usingDeclaration, policy.BlankLinesBeforeUsings);
273
} else if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration)) {
274
FixIndentationForceNewLine(usingDeclaration.StartLocation);
275
EnsureBlankLinesAfter(usingDeclaration, policy.BlankLinesAfterUsings);
277
FixIndentationForceNewLine(usingDeclaration.StartLocation);
281
public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
283
var firstNsMember = namespaceDeclaration.Members.FirstOrDefault();
284
if (firstNsMember != null) {
285
EnsureBlankLinesBefore(firstNsMember, policy.BlankLinesBeforeFirstDeclaration);
287
FixIndentationForceNewLine(namespaceDeclaration.StartLocation);
288
EnforceBraceStyle(policy.NamespaceBraceStyle, namespaceDeclaration.LBraceToken, namespaceDeclaration.RBraceToken);
289
if (policy.IndentNamespaceBody) {
290
curIndent.Push(IndentType.Block);
292
base.VisitNamespaceDeclaration(namespaceDeclaration);
293
if (policy.IndentNamespaceBody) {
296
FixIndentation(namespaceDeclaration.RBraceToken.StartLocation);
299
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
301
FormatAttributedNode(typeDeclaration);
302
BraceStyle braceStyle;
303
bool indentBody = false;
304
switch (typeDeclaration.ClassType) {
305
case ClassType.Class:
306
braceStyle = policy.ClassBraceStyle;
307
indentBody = policy.IndentClassBody;
309
case ClassType.Struct:
310
braceStyle = policy.StructBraceStyle;
311
indentBody = policy.IndentStructBody;
313
case ClassType.Interface:
314
braceStyle = policy.InterfaceBraceStyle;
315
indentBody = policy.IndentInterfaceBody;
318
braceStyle = policy.EnumBraceStyle;
319
indentBody = policy.IndentEnumBody;
322
throw new InvalidOperationException("unsupported class type : " + typeDeclaration.ClassType);
325
EnforceBraceStyle(braceStyle, typeDeclaration.LBraceToken, typeDeclaration.RBraceToken);
328
curIndent.Push(IndentType.Block);
330
base.VisitTypeDeclaration(typeDeclaration);
335
if (typeDeclaration.NextSibling is TypeDeclaration || typeDeclaration.NextSibling is DelegateDeclaration) {
336
EnsureBlankLinesAfter(typeDeclaration, policy.BlankLinesBetweenTypes);
341
bool IsSimpleAccessor(Accessor accessor)
343
if (accessor.IsNull || accessor.Body.IsNull || accessor.Body.FirstChild == null) {
346
if (accessor.Body.Statements.Count() != 1) {
349
return !(accessor.Body.Statements.FirstOrDefault() is BlockStatement);
353
bool IsSpacing(char ch)
355
return ch == ' ' || ch == '\t';
358
bool IsSpacing(ISegment segment)
360
int endOffset = segment.EndOffset;
361
for (int i = segment.Offset; i < endOffset; i++) {
362
if (!IsSpacing(document.GetCharAt(i))) {
369
int SearchLastNonWsChar(int startOffset, int endOffset)
371
startOffset = System.Math.Max(0, startOffset);
372
endOffset = System.Math.Max(startOffset, endOffset);
373
if (startOffset >= endOffset) {
377
bool inComment = false;
379
for (int i = startOffset; i < endOffset && i < document.TextLength; i++) {
380
char ch = document.GetCharAt(i);
384
if (ch == '/' && i + 1 < document.TextLength && document.GetCharAt(i + 1) == '/') {
387
if (ch == '/' && i + 1 < document.TextLength && document.GetCharAt(i + 1) == '*') {
392
if (inComment && ch == '*' && i + 1 < document.TextLength && document.GetCharAt(i + 1) == '/') {
404
void ForceSpace(int startOffset, int endOffset, bool forceSpace)
406
int lastNonWs = SearchLastNonWsChar(startOffset, endOffset);
407
AddChange(lastNonWs + 1, System.Math.Max(0, endOffset - lastNonWs - 1), forceSpace ? " " : "");
409
// void ForceSpacesAfter (AstNode n, bool forceSpaces)
413
// AstLocation location = n.EndLocation;
414
// int offset = data.LocationToOffset (location.Line, location.Column);
416
// while (i < data.Length && IsSpacing (data.GetCharAt (i))) {
419
// ForceSpace (offset - 1, i, forceSpaces);
422
void ForceSpacesAfter(AstNode n, bool forceSpaces)
427
TextLocation location = n.EndLocation;
428
int offset = document.GetOffset(location);
429
if (location.Column > document.GetLineByNumber(location.Line).Length) {
433
while (i < document.TextLength && IsSpacing (document.GetCharAt (i))) {
436
ForceSpace(offset - 1, i, forceSpaces);
439
// int ForceSpacesBefore (AstNode n, bool forceSpaces)
441
// if (n == null || n.IsNull)
443
// AstLocation location = n.StartLocation;
445
// int offset = data.LocationToOffset (location.Line, location.Column);
446
// int i = offset - 1;
448
// while (i >= 0 && IsSpacing (data.GetCharAt (i))) {
451
// ForceSpace (i, offset, forceSpaces);
455
int ForceSpacesBefore(AstNode n, bool forceSpaces)
457
if (n == null || n.IsNull) {
460
TextLocation location = n.StartLocation;
461
// respect manual line breaks.
462
if (location.Column <= 1 || GetIndentation(location.Line).Length == location.Column - 1) {
466
int offset = document.GetOffset(location);
468
while (i >= 0 && IsSpacing (document.GetCharAt (i))) {
471
ForceSpace(i, offset, forceSpaces);
475
int ForceSpacesBeforeRemoveNewLines(AstNode n, bool forceSpace = true)
477
if (n == null || n.IsNull) {
480
int offset = document.GetOffset(n.StartLocation);
483
char ch = document.GetCharAt(i);
484
if (!IsSpacing(ch) && ch != '\r' && ch != '\n')
488
var length = System.Math.Max(0, (offset - 1) - i);
489
AddChange(i + 1, length, forceSpace ? " " : "");
493
public override void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
495
FormatAttributedNode(propertyDeclaration);
496
bool oneLine = false;
497
switch (policy.PropertyFormatting) {
498
case PropertyFormatting.AllowOneLine:
499
bool isSimple = IsSimpleAccessor(propertyDeclaration.Getter) && IsSimpleAccessor(propertyDeclaration.Setter);
500
int accessorLine = propertyDeclaration.RBraceToken.StartLocation.Line;
501
if (!propertyDeclaration.Getter.IsNull && propertyDeclaration.Setter.IsNull) {
502
accessorLine = propertyDeclaration.Getter.StartLocation.Line;
503
} else if (propertyDeclaration.Getter.IsNull && !propertyDeclaration.Setter.IsNull) {
504
accessorLine = propertyDeclaration.Setter.StartLocation.Line;
506
var acc = propertyDeclaration.Getter.StartLocation < propertyDeclaration.Setter.StartLocation ?
507
propertyDeclaration.Getter : propertyDeclaration.Setter;
508
accessorLine = acc.StartLocation.Line;
510
if (!isSimple || propertyDeclaration.LBraceToken.StartLocation.Line != accessorLine) {
511
EnforceBraceStyle(policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken);
513
ForceSpacesBefore(propertyDeclaration.Getter, true);
514
ForceSpacesBefore(propertyDeclaration.Setter, true);
515
ForceSpacesBeforeRemoveNewLines(propertyDeclaration.RBraceToken, true);
519
case PropertyFormatting.ForceNewLine:
520
EnforceBraceStyle(policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken);
522
case PropertyFormatting.ForceOneLine:
523
isSimple = IsSimpleAccessor(propertyDeclaration.Getter) && IsSimpleAccessor(propertyDeclaration.Setter);
525
int offset = this.document.GetOffset(propertyDeclaration.LBraceToken.StartLocation);
527
int start = SearchWhitespaceStart(offset);
528
int end = SearchWhitespaceEnd(offset);
529
AddChange(start, offset - start, " ");
530
AddChange(offset + 1, end - offset - 2, " ");
532
offset = this.document.GetOffset(propertyDeclaration.RBraceToken.StartLocation);
533
start = SearchWhitespaceStart(offset);
534
AddChange(start, offset - start, " ");
538
EnforceBraceStyle(policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken);
542
if (policy.IndentPropertyBody) {
543
curIndent.Push(IndentType.Block);
545
///System.Console.WriteLine ("one line: " + oneLine);
546
if (!propertyDeclaration.Getter.IsNull) {
548
if (!IsLineIsEmptyUpToEol(propertyDeclaration.Getter.StartLocation)) {
549
int offset = this.document.GetOffset(propertyDeclaration.Getter.StartLocation);
550
int start = SearchWhitespaceStart(offset);
551
string indentString = this.curIndent.IndentString;
552
AddChange(start, offset - start, this.options.EolMarker + indentString);
554
FixIndentation(propertyDeclaration.Getter.StartLocation);
557
int offset = this.document.GetOffset(propertyDeclaration.Getter.StartLocation);
558
int start = SearchWhitespaceStart(offset);
559
AddChange(start, offset - start, " ");
561
ForceSpacesBefore(propertyDeclaration.Getter.Body.LBraceToken, true);
562
ForceSpacesBefore(propertyDeclaration.Getter.Body.RBraceToken, true);
564
if (!propertyDeclaration.Getter.Body.IsNull) {
565
if (!policy.AllowPropertyGetBlockInline || propertyDeclaration.Getter.Body.LBraceToken.StartLocation.Line != propertyDeclaration.Getter.Body.RBraceToken.StartLocation.Line) {
566
EnforceBraceStyle(policy.PropertyGetBraceStyle, propertyDeclaration.Getter.Body.LBraceToken, propertyDeclaration.Getter.Body.RBraceToken);
568
nextStatementIndent = " ";
570
VisitBlockWithoutFixingBraces(propertyDeclaration.Getter.Body, policy.IndentBlocks);
574
if (!propertyDeclaration.Setter.IsNull) {
576
if (!IsLineIsEmptyUpToEol(propertyDeclaration.Setter.StartLocation)) {
577
int offset = this.document.GetOffset(propertyDeclaration.Setter.StartLocation);
578
int start = SearchWhitespaceStart(offset);
579
string indentString = this.curIndent.IndentString;
580
AddChange(start, offset - start, this.options.EolMarker + indentString);
582
FixIndentation(propertyDeclaration.Setter.StartLocation);
585
int offset = this.document.GetOffset(propertyDeclaration.Setter.StartLocation);
586
int start = SearchWhitespaceStart(offset);
587
AddChange(start, offset - start, " ");
589
ForceSpacesBefore(propertyDeclaration.Setter.Body.LBraceToken, true);
590
ForceSpacesBefore(propertyDeclaration.Setter.Body.RBraceToken, true);
592
if (!propertyDeclaration.Setter.Body.IsNull) {
593
if (!policy.AllowPropertySetBlockInline || propertyDeclaration.Setter.Body.LBraceToken.StartLocation.Line != propertyDeclaration.Setter.Body.RBraceToken.StartLocation.Line) {
594
EnforceBraceStyle(policy.PropertySetBraceStyle, propertyDeclaration.Setter.Body.LBraceToken, propertyDeclaration.Setter.Body.RBraceToken);
596
nextStatementIndent = " ";
598
VisitBlockWithoutFixingBraces(propertyDeclaration.Setter.Body, policy.IndentBlocks);
602
if (policy.IndentPropertyBody) {
605
if (IsMember(propertyDeclaration.NextSibling)) {
606
EnsureBlankLinesAfter(propertyDeclaration, policy.BlankLinesBetweenMembers);
610
public override void VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
612
ForceSpacesBefore(indexerDeclaration.LBracketToken, policy.SpaceBeforeIndexerDeclarationBracket);
613
ForceSpacesAfter(indexerDeclaration.LBracketToken, policy.SpaceWithinIndexerDeclarationBracket);
615
FormatParameters(indexerDeclaration);
617
FormatAttributedNode(indexerDeclaration);
618
EnforceBraceStyle(policy.PropertyBraceStyle, indexerDeclaration.LBraceToken, indexerDeclaration.RBraceToken);
619
if (policy.IndentPropertyBody) {
620
curIndent.Push(IndentType.Block);
623
if (!indexerDeclaration.Getter.IsNull) {
624
FixIndentation(indexerDeclaration.Getter.StartLocation);
625
if (!indexerDeclaration.Getter.Body.IsNull) {
626
if (!policy.AllowPropertyGetBlockInline || indexerDeclaration.Getter.Body.LBraceToken.StartLocation.Line != indexerDeclaration.Getter.Body.RBraceToken.StartLocation.Line) {
627
EnforceBraceStyle(policy.PropertyGetBraceStyle, indexerDeclaration.Getter.Body.LBraceToken, indexerDeclaration.Getter.Body.RBraceToken);
629
nextStatementIndent = " ";
631
VisitBlockWithoutFixingBraces(indexerDeclaration.Getter.Body, policy.IndentBlocks);
635
if (!indexerDeclaration.Setter.IsNull) {
636
FixIndentation(indexerDeclaration.Setter.StartLocation);
637
if (!indexerDeclaration.Setter.Body.IsNull) {
638
if (!policy.AllowPropertySetBlockInline || indexerDeclaration.Setter.Body.LBraceToken.StartLocation.Line != indexerDeclaration.Setter.Body.RBraceToken.StartLocation.Line) {
639
EnforceBraceStyle(policy.PropertySetBraceStyle, indexerDeclaration.Setter.Body.LBraceToken, indexerDeclaration.Setter.Body.RBraceToken);
641
nextStatementIndent = " ";
643
VisitBlockWithoutFixingBraces(indexerDeclaration.Setter.Body, policy.IndentBlocks);
646
if (policy.IndentPropertyBody) {
649
if (IsMember(indexerDeclaration.NextSibling)) {
650
EnsureBlankLinesAfter(indexerDeclaration, policy.BlankLinesBetweenMembers);
654
static bool IsSimpleEvent(AstNode node)
656
return node is EventDeclaration;
659
public override void VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration)
661
FormatAttributedNode(eventDeclaration);
662
EnforceBraceStyle(policy.EventBraceStyle, eventDeclaration.LBraceToken, eventDeclaration.RBraceToken);
663
if (policy.IndentEventBody) {
664
curIndent.Push(IndentType.Block);
667
if (!eventDeclaration.AddAccessor.IsNull) {
668
FixIndentation(eventDeclaration.AddAccessor.StartLocation);
669
if (!eventDeclaration.AddAccessor.Body.IsNull) {
670
if (!policy.AllowEventAddBlockInline || eventDeclaration.AddAccessor.Body.LBraceToken.StartLocation.Line != eventDeclaration.AddAccessor.Body.RBraceToken.StartLocation.Line) {
671
EnforceBraceStyle(policy.EventAddBraceStyle, eventDeclaration.AddAccessor.Body.LBraceToken, eventDeclaration.AddAccessor.Body.RBraceToken);
673
nextStatementIndent = " ";
676
VisitBlockWithoutFixingBraces(eventDeclaration.AddAccessor.Body, policy.IndentBlocks);
680
if (!eventDeclaration.RemoveAccessor.IsNull) {
681
FixIndentation(eventDeclaration.RemoveAccessor.StartLocation);
682
if (!eventDeclaration.RemoveAccessor.Body.IsNull) {
683
if (!policy.AllowEventRemoveBlockInline || eventDeclaration.RemoveAccessor.Body.LBraceToken.StartLocation.Line != eventDeclaration.RemoveAccessor.Body.RBraceToken.StartLocation.Line) {
684
EnforceBraceStyle(policy.EventRemoveBraceStyle, eventDeclaration.RemoveAccessor.Body.LBraceToken, eventDeclaration.RemoveAccessor.Body.RBraceToken);
686
nextStatementIndent = " ";
688
VisitBlockWithoutFixingBraces(eventDeclaration.RemoveAccessor.Body, policy.IndentBlocks);
692
if (policy.IndentEventBody) {
696
if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent(eventDeclaration) && IsSimpleEvent(eventDeclaration.NextSibling)) {
697
EnsureBlankLinesAfter(eventDeclaration, policy.BlankLinesBetweenEventFields);
698
} else if (IsMember(eventDeclaration.NextSibling)) {
699
EnsureBlankLinesAfter(eventDeclaration, policy.BlankLinesBetweenMembers);
703
public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
705
FormatAttributedNode(eventDeclaration);
706
if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent(eventDeclaration) && IsSimpleEvent(eventDeclaration.NextSibling)) {
707
EnsureBlankLinesAfter(eventDeclaration, policy.BlankLinesBetweenEventFields);
708
} else if (IsMember(eventDeclaration.NextSibling)) {
709
EnsureBlankLinesAfter(eventDeclaration, policy.BlankLinesBetweenMembers);
712
var lastLoc = eventDeclaration.StartLocation;
713
curIndent.Push(IndentType.Block);
714
foreach (var initializer in eventDeclaration.Variables) {
715
if (lastLoc.Line != initializer.StartLocation.Line) {
716
FixStatementIndentation(initializer.StartLocation);
717
lastLoc = initializer.StartLocation;
719
initializer.AcceptVisitor(this);
724
public override void VisitAccessor(Accessor accessor)
726
FixIndentationForceNewLine(accessor.StartLocation);
727
base.VisitAccessor(accessor);
730
public override void VisitFieldDeclaration(FieldDeclaration fieldDeclaration)
732
FormatAttributedNode(fieldDeclaration);
733
fieldDeclaration.ReturnType.AcceptVisitor(this);
734
FormatCommas(fieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma);
735
if (fieldDeclaration.NextSibling is FieldDeclaration || fieldDeclaration.NextSibling is FixedFieldDeclaration) {
736
EnsureBlankLinesAfter(fieldDeclaration, policy.BlankLinesBetweenFields);
737
} else if (IsMember(fieldDeclaration.NextSibling)) {
738
EnsureBlankLinesAfter(fieldDeclaration, policy.BlankLinesBetweenMembers);
741
var lastLoc = fieldDeclaration.StartLocation;
742
curIndent.Push(IndentType.Block);
743
foreach (var initializer in fieldDeclaration.Variables) {
744
if (lastLoc.Line != initializer.StartLocation.Line) {
745
FixStatementIndentation(initializer.StartLocation);
746
lastLoc = initializer.StartLocation;
748
initializer.AcceptVisitor(this);
753
public override void VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration)
755
FormatAttributedNode(fixedFieldDeclaration);
756
FormatCommas(fixedFieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma);
757
if (fixedFieldDeclaration.NextSibling is FieldDeclaration || fixedFieldDeclaration.NextSibling is FixedFieldDeclaration) {
758
EnsureBlankLinesAfter(fixedFieldDeclaration, policy.BlankLinesBetweenFields);
759
} else if (IsMember(fixedFieldDeclaration.NextSibling)) {
760
EnsureBlankLinesAfter(fixedFieldDeclaration, policy.BlankLinesBetweenMembers);
763
var lastLoc = fixedFieldDeclaration.StartLocation;
764
curIndent.Push(IndentType.Block);
765
foreach (var initializer in fixedFieldDeclaration.Variables) {
766
if (lastLoc.Line != initializer.StartLocation.Line) {
767
FixStatementIndentation(initializer.StartLocation);
768
lastLoc = initializer.StartLocation;
770
initializer.AcceptVisitor(this);
775
public override void VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration)
777
FormatAttributedNode(enumMemberDeclaration);
778
base.VisitEnumMemberDeclaration(enumMemberDeclaration);
781
public override void VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
783
FormatAttributedNode(delegateDeclaration);
785
ForceSpacesBefore(delegateDeclaration.LParToken, policy.SpaceBeforeDelegateDeclarationParentheses);
786
if (delegateDeclaration.Parameters.Any()) {
787
ForceSpacesAfter(delegateDeclaration.LParToken, policy.SpaceWithinDelegateDeclarationParentheses);
788
ForceSpacesBefore(delegateDeclaration.RParToken, policy.SpaceWithinDelegateDeclarationParentheses);
790
ForceSpacesAfter(delegateDeclaration.LParToken, policy.SpaceBetweenEmptyDelegateDeclarationParentheses);
791
ForceSpacesBefore(delegateDeclaration.RParToken, policy.SpaceBetweenEmptyDelegateDeclarationParentheses);
793
FormatCommas(delegateDeclaration, policy.SpaceBeforeDelegateDeclarationParameterComma, policy.SpaceAfterDelegateDeclarationParameterComma);
795
if (delegateDeclaration.NextSibling is TypeDeclaration || delegateDeclaration.NextSibling is DelegateDeclaration) {
796
EnsureBlankLinesAfter(delegateDeclaration, policy.BlankLinesBetweenTypes);
797
} else if (IsMember(delegateDeclaration.NextSibling)) {
798
EnsureBlankLinesAfter(delegateDeclaration, policy.BlankLinesBetweenMembers);
801
base.VisitDelegateDeclaration(delegateDeclaration);
804
static bool IsMember(AstNode nextSibling)
806
return nextSibling != null && nextSibling.NodeType == NodeType.Member;
809
void FormatAttributedNode(AstNode node)
814
AstNode child = node.FirstChild;
815
while (child != null && child is AttributeSection) {
816
FixIndentationForceNewLine(child.StartLocation);
817
child = child.NextSibling;
820
FixIndentationForceNewLine(child.StartLocation);
825
void FormatParameters(AstNode node)
827
Wrapping methodCallArgumentWrapping;
828
bool newLineAferMethodCallOpenParentheses;
829
bool methodClosingParenthesesOnNewLine;
830
bool spaceWithinMethodCallParentheses;
831
bool spaceAfterMethodCallParameterComma;
832
bool spaceBeforeMethodCallParameterComma;
834
CSharpTokenNode rParToken;
835
AstNodeCollection<ParameterDeclaration> parameters;
837
var constructorDeclaration = node as ConstructorDeclaration;
838
if (constructorDeclaration != null) {
839
methodCallArgumentWrapping = policy.MethodDeclarationParameterWrapping;
840
newLineAferMethodCallOpenParentheses = policy.NewLineAferMethodDeclarationOpenParentheses;
841
methodClosingParenthesesOnNewLine = policy.MethodDeclarationClosingParenthesesOnNewLine;
843
spaceWithinMethodCallParentheses = policy.SpaceWithinConstructorDeclarationParentheses;
844
spaceAfterMethodCallParameterComma = policy.SpaceAfterConstructorDeclarationParameterComma;
845
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeConstructorDeclarationParameterComma;
846
rParToken = constructorDeclaration.RParToken;
847
parameters = constructorDeclaration.Parameters;
848
} else if (node is IndexerDeclaration) {
849
var indexer = (IndexerDeclaration)node;
850
methodCallArgumentWrapping = policy.IndexerDeclarationParameterWrapping;
851
newLineAferMethodCallOpenParentheses = policy.NewLineAferIndexerDeclarationOpenBracket;
852
methodClosingParenthesesOnNewLine = policy.IndexerDeclarationClosingBracketOnNewLine;
854
spaceWithinMethodCallParentheses = policy.SpaceWithinIndexerDeclarationBracket;
855
spaceAfterMethodCallParameterComma = policy.SpaceAfterIndexerDeclarationParameterComma;
856
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeIndexerDeclarationParameterComma;
857
rParToken = indexer.RBracketToken;
858
parameters = indexer.Parameters;
859
} else if (node is OperatorDeclaration) {
860
var op = (OperatorDeclaration)node;
861
methodCallArgumentWrapping = policy.MethodDeclarationParameterWrapping;
862
newLineAferMethodCallOpenParentheses = policy.NewLineAferMethodDeclarationOpenParentheses;
863
methodClosingParenthesesOnNewLine = policy.MethodDeclarationClosingParenthesesOnNewLine;
864
spaceWithinMethodCallParentheses = policy.SpaceWithinMethodDeclarationParentheses;
865
spaceAfterMethodCallParameterComma = policy.SpaceAfterMethodDeclarationParameterComma;
866
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeMethodDeclarationParameterComma;
867
rParToken = op.RParToken;
868
parameters = op.Parameters;
870
var methodDeclaration = node as MethodDeclaration;
871
methodCallArgumentWrapping = policy.MethodDeclarationParameterWrapping;
872
newLineAferMethodCallOpenParentheses = policy.NewLineAferMethodDeclarationOpenParentheses;
873
methodClosingParenthesesOnNewLine = policy.MethodDeclarationClosingParenthesesOnNewLine;
874
spaceWithinMethodCallParentheses = policy.SpaceWithinMethodDeclarationParentheses;
875
spaceAfterMethodCallParameterComma = policy.SpaceAfterMethodDeclarationParameterComma;
876
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeMethodDeclarationParameterComma;
877
rParToken = methodDeclaration.RParToken;
878
parameters = methodDeclaration.Parameters;
880
if (FormattingMode == ICSharpCode.NRefactory.CSharp.FormattingMode.OnTheFly)
881
methodCallArgumentWrapping = Wrapping.DoNotChange;
883
bool wrapMethodCall = DoWrap(methodCallArgumentWrapping, rParToken, parameters.Count);
884
if (wrapMethodCall && parameters.Any()) {
885
if (newLineAferMethodCallOpenParentheses) {
886
curIndent.Push(IndentType.Continuation);
887
foreach (var arg in parameters) {
888
FixStatementIndentation(arg.StartLocation);
892
int extraSpaces = parameters.First().StartLocation.Column - 1 - curIndent.IndentString.Length;
893
curIndent.ExtraSpaces += extraSpaces;
894
foreach (var arg in parameters.Skip(1)) {
895
FixStatementIndentation(arg.StartLocation);
897
curIndent.ExtraSpaces -= extraSpaces;
899
if (!rParToken.IsNull) {
900
if (methodClosingParenthesesOnNewLine) {
901
FixStatementIndentation(rParToken.StartLocation);
903
ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses);
907
foreach (var arg in parameters) {
908
if (arg.PrevSibling != null) {
909
if (methodCallArgumentWrapping == Wrapping.DoNotWrap) {
910
ForceSpacesBeforeRemoveNewLines(arg, spaceAfterMethodCallParameterComma && arg.PrevSibling.Role == Roles.Comma);
912
ForceSpacesBefore(arg, spaceAfterMethodCallParameterComma && arg.PrevSibling.Role == Roles.Comma);
915
arg.AcceptVisitor(this);
917
if (!rParToken.IsNull) {
918
if (methodCallArgumentWrapping == Wrapping.DoNotWrap) {
919
ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses);
921
bool sameLine = rParToken.GetPrevNode().StartLocation.Line == rParToken.StartLocation.Line;
923
ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses);
925
FixStatementIndentation(rParToken.StartLocation);
930
if (!rParToken.IsNull) {
931
foreach (CSharpTokenNode comma in rParToken.Parent.Children.Where(n => n.Role == Roles.Comma)) {
932
ForceSpacesBefore(comma, spaceBeforeMethodCallParameterComma);
937
public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
939
FormatAttributedNode(methodDeclaration);
941
ForceSpacesBefore(methodDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses);
942
if (methodDeclaration.Parameters.Any()) {
943
ForceSpacesAfter(methodDeclaration.LParToken, policy.SpaceWithinMethodDeclarationParentheses);
944
FormatParameters(methodDeclaration);
946
ForceSpacesAfter(methodDeclaration.LParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses);
947
ForceSpacesBefore(methodDeclaration.RParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses);
950
if (!methodDeclaration.Body.IsNull) {
951
EnforceBraceStyle(policy.MethodBraceStyle, methodDeclaration.Body.LBraceToken, methodDeclaration.Body.RBraceToken);
952
VisitBlockWithoutFixingBraces(methodDeclaration.Body, policy.IndentMethodBody);
954
if (IsMember(methodDeclaration.NextSibling)) {
955
EnsureBlankLinesAfter(methodDeclaration, policy.BlankLinesBetweenMembers);
959
public override void VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration)
961
FormatAttributedNode(operatorDeclaration);
963
ForceSpacesBefore(operatorDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses);
964
if (operatorDeclaration.Parameters.Any()) {
965
ForceSpacesAfter(operatorDeclaration.LParToken, policy.SpaceWithinMethodDeclarationParentheses);
966
FormatParameters(operatorDeclaration);
968
ForceSpacesAfter(operatorDeclaration.LParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses);
969
ForceSpacesBefore(operatorDeclaration.RParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses);
972
if (!operatorDeclaration.Body.IsNull) {
973
EnforceBraceStyle(policy.MethodBraceStyle, operatorDeclaration.Body.LBraceToken, operatorDeclaration.Body.RBraceToken);
974
VisitBlockWithoutFixingBraces(operatorDeclaration.Body, policy.IndentMethodBody);
976
if (IsMember(operatorDeclaration.NextSibling)) {
977
EnsureBlankLinesAfter(operatorDeclaration, policy.BlankLinesBetweenMembers);
981
public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
983
FormatAttributedNode(constructorDeclaration);
985
ForceSpacesBefore(constructorDeclaration.LParToken, policy.SpaceBeforeConstructorDeclarationParentheses);
986
if (constructorDeclaration.Parameters.Any()) {
987
ForceSpacesAfter(constructorDeclaration.LParToken, policy.SpaceWithinConstructorDeclarationParentheses);
988
FormatParameters(constructorDeclaration);
990
ForceSpacesAfter(constructorDeclaration.LParToken, policy.SpaceBetweenEmptyConstructorDeclarationParentheses);
991
ForceSpacesBefore(constructorDeclaration.RParToken, policy.SpaceBetweenEmptyConstructorDeclarationParentheses);
994
if (!constructorDeclaration.Body.IsNull) {
995
EnforceBraceStyle(policy.ConstructorBraceStyle, constructorDeclaration.Body.LBraceToken, constructorDeclaration.Body.RBraceToken);
996
VisitBlockWithoutFixingBraces(constructorDeclaration.Body, policy.IndentMethodBody);
998
if (IsMember(constructorDeclaration.NextSibling)) {
999
EnsureBlankLinesAfter(constructorDeclaration, policy.BlankLinesBetweenMembers);
1003
public override void VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration)
1005
FormatAttributedNode(destructorDeclaration);
1007
CSharpTokenNode lParen = destructorDeclaration.LParToken;
1008
int offset = this.document.GetOffset(lParen.StartLocation);
1009
ForceSpaceBefore(offset, policy.SpaceBeforeConstructorDeclarationParentheses);
1011
if (!destructorDeclaration.Body.IsNull) {
1012
EnforceBraceStyle(policy.DestructorBraceStyle, destructorDeclaration.Body.LBraceToken, destructorDeclaration.Body.RBraceToken);
1013
VisitBlockWithoutFixingBraces(destructorDeclaration.Body, policy.IndentMethodBody);
1015
if (IsMember(destructorDeclaration.NextSibling)) {
1016
EnsureBlankLinesAfter(destructorDeclaration, policy.BlankLinesBetweenMembers);
1021
public override void VisitExpressionStatement(ExpressionStatement expressionStatement)
1023
base.VisitExpressionStatement(expressionStatement);
1024
FixSemicolon(expressionStatement.SemicolonToken);
1027
void VisitBlockWithoutFixingBraces(BlockStatement blockStatement, bool indent)
1030
curIndent.Push(IndentType.Block);
1032
foreach (var child in blockStatement.Children) {
1033
if (child.Role == Roles.LBrace || child.Role == Roles.RBrace) {
1036
if (child is Statement) {
1037
FixStatementIndentation(child.StartLocation);
1038
child.AcceptVisitor(this);
1039
} else if (child is Comment) {
1040
child.AcceptVisitor(this);
1042
// pre processor directives at line start, if they are there.
1043
if (child.StartLocation.Column > 1)
1044
FixStatementIndentation(child.StartLocation);
1052
public override void VisitBlockStatement(BlockStatement blockStatement)
1054
FixIndentation(blockStatement.StartLocation);
1055
VisitBlockWithoutFixingBraces(blockStatement, policy.IndentBlocks);
1056
FixIndentation(blockStatement.EndLocation, -1);
1059
public override void VisitComment(Comment comment)
1061
if (comment.StartsLine && !HadErrors && (!policy.KeepCommentsAtFirstColumn || comment.StartLocation.Column > 1)) {
1062
FixIndentation(comment.StartLocation);
1066
public override void VisitBreakStatement(BreakStatement breakStatement)
1068
FixSemicolon(breakStatement.SemicolonToken);
1071
public override void VisitCheckedStatement(CheckedStatement checkedStatement)
1073
FixEmbeddedStatment(policy.StatementBraceStyle, policy.FixedBraceForcement, checkedStatement.Body);
1076
public override void VisitContinueStatement(ContinueStatement continueStatement)
1078
FixSemicolon(continueStatement.SemicolonToken);
1081
public override void VisitEmptyStatement(EmptyStatement emptyStatement)
1086
public override void VisitFixedStatement(FixedStatement fixedStatement)
1088
FixEmbeddedStatment(policy.StatementBraceStyle, policy.FixedBraceForcement, fixedStatement.EmbeddedStatement);
1091
public override void VisitForeachStatement(ForeachStatement foreachStatement)
1093
ForceSpacesBefore(foreachStatement.LParToken, policy.SpaceBeforeForeachParentheses);
1095
ForceSpacesAfter(foreachStatement.LParToken, policy.SpacesWithinForeachParentheses);
1096
ForceSpacesBefore(foreachStatement.RParToken, policy.SpacesWithinForeachParentheses);
1098
FixEmbeddedStatment(policy.StatementBraceStyle, policy.ForEachBraceForcement, foreachStatement.EmbeddedStatement);
1101
void FixEmbeddedStatment(BraceStyle braceStyle, BraceForcement braceForcement, AstNode node)
1103
FixEmbeddedStatment(braceStyle, braceForcement, null, false, node);
1106
void FixEmbeddedStatment(BraceStyle braceStyle, BraceForcement braceForcement, CSharpTokenNode token, bool allowInLine, AstNode node, bool statementAlreadyIndented = false)
1111
bool isBlock = node is BlockStatement;
1112
TextReplaceAction beginBraceAction = null;
1113
TextReplaceAction endBraceAction = null;
1115
switch (braceForcement) {
1116
case BraceForcement.DoNotChange:
1119
case BraceForcement.AddBraces:
1121
AstNode n = node.Parent.GetCSharpNodeBefore(node);
1122
int start = document.GetOffset(n.EndLocation);
1123
string startBrace = "";
1124
switch (braceStyle) {
1125
case BraceStyle.EndOfLineWithoutSpace:
1128
case BraceStyle.BannerStyle:
1129
case BraceStyle.EndOfLine:
1132
case BraceStyle.NextLine:
1133
startBrace = this.options.EolMarker + curIndent.IndentString + "{";
1135
case BraceStyle.NextLineShifted2:
1136
case BraceStyle.NextLineShifted:
1137
curIndent.Push(IndentType.Block);
1138
startBrace = this.options.EolMarker + curIndent.IndentString + "{";
1142
beginBraceAction = AddChange(start, 0, startBrace);
1145
case BraceForcement.RemoveBraces:
1147
BlockStatement block = node as BlockStatement;
1148
if (block.Statements.Count() == 1) {
1149
int offset1 = document.GetOffset(node.StartLocation);
1150
int start = SearchWhitespaceStart(offset1);
1152
int offset2 = document.GetOffset(node.EndLocation);
1153
int end = SearchWhitespaceStart(offset2 - 1);
1155
beginBraceAction = AddChange(start, offset1 - start + 1, null);
1156
endBraceAction = AddChange(end + 1, offset2 - end, null);
1157
node = block.FirstChild;
1164
BlockStatement block = node as BlockStatement;
1165
if (allowInLine && block.StartLocation.Line == block.EndLocation.Line && block.Statements.Count() <= 1) {
1166
if (block.Statements.Count() == 1) {
1167
nextStatementIndent = " ";
1170
if (!statementAlreadyIndented) {
1171
EnforceBraceStyle(braceStyle, block.LBraceToken, block.RBraceToken);
1174
if (braceStyle == BraceStyle.NextLineShifted2) {
1175
curIndent.Push(IndentType.Block);
1178
if (allowInLine && token.StartLocation.Line == node.EndLocation.Line) {
1179
nextStatementIndent = " ";
1182
if (policy.IndentBlocks && !(policy.AlignEmbeddedIfStatements && node is IfElseStatement && node.Parent is IfElseStatement || policy.AlignEmbeddedUsingStatements && node is UsingStatement && node.Parent is UsingStatement)) {
1183
curIndent.Push(IndentType.Block);
1186
VisitBlockWithoutFixingBraces((BlockStatement)node, false);
1188
if (!statementAlreadyIndented) {
1189
FixStatementIndentation(node.StartLocation);
1191
node.AcceptVisitor(this);
1193
if (policy.IndentBlocks && !(policy.AlignEmbeddedIfStatements && node is IfElseStatement && node.Parent is IfElseStatement || policy.AlignEmbeddedUsingStatements && node is UsingStatement && node.Parent is UsingStatement)) {
1196
switch (braceForcement) {
1197
case BraceForcement.DoNotChange:
1199
case BraceForcement.AddBraces:
1201
int offset = document.GetOffset(node.EndLocation);
1202
if (!char.IsWhiteSpace(document.GetCharAt(offset))) {
1205
string startBrace = "";
1206
switch (braceStyle) {
1207
case BraceStyle.DoNotChange:
1210
case BraceStyle.EndOfLineWithoutSpace:
1211
startBrace = this.options.EolMarker + curIndent.IndentString + "}";
1213
case BraceStyle.EndOfLine:
1214
startBrace = this.options.EolMarker + curIndent.IndentString + "}";
1216
case BraceStyle.NextLine:
1217
startBrace = this.options.EolMarker + curIndent.IndentString + "}";
1219
case BraceStyle.BannerStyle:
1220
case BraceStyle.NextLineShifted2:
1221
case BraceStyle.NextLineShifted:
1222
curIndent.Push(IndentType.Block);
1223
startBrace = this.options.EolMarker + curIndent.IndentString + "}";
1228
if (startBrace != null) {
1229
endBraceAction = AddChange(offset, 0, startBrace);
1234
if (beginBraceAction != null && endBraceAction != null) {
1235
beginBraceAction.DependsOn = endBraceAction;
1236
endBraceAction.DependsOn = beginBraceAction;
1240
void EnforceBraceStyle(BraceStyle braceStyle, AstNode lbrace, AstNode rbrace)
1242
if (lbrace.IsNull || rbrace.IsNull) {
1246
// LineSegment lbraceLineSegment = data.Document.GetLine (lbrace.StartLocation.Line);
1247
int lbraceOffset = document.GetOffset(lbrace.StartLocation);
1249
// LineSegment rbraceLineSegment = data.Document.GetLine (rbrace.StartLocation.Line);
1250
int rbraceOffset = document.GetOffset(rbrace.StartLocation);
1251
int whitespaceStart = SearchWhitespaceStart(lbraceOffset);
1252
int whitespaceEnd = SearchWhitespaceLineStart(rbraceOffset);
1253
string startIndent = "";
1254
string endIndent = "";
1255
switch (braceStyle) {
1256
case BraceStyle.DoNotChange:
1257
startIndent = endIndent = null;
1259
case BraceStyle.EndOfLineWithoutSpace:
1261
endIndent = IsLineIsEmptyUpToEol(rbraceOffset) ? curIndent.IndentString : this.options.EolMarker + curIndent.IndentString;
1263
case BraceStyle.BannerStyle:
1264
var prevNode = lbrace.GetPrevNode();
1265
if (prevNode is Comment) {
1266
// delete old bracket
1267
AddChange(whitespaceStart, lbraceOffset - whitespaceStart + 1, "");
1269
while (prevNode is Comment) {
1270
prevNode = prevNode.GetPrevNode();
1272
whitespaceStart = document.GetOffset(prevNode.EndLocation);
1273
lbraceOffset = whitespaceStart;
1278
curIndent.Push(IndentType.Block);
1279
endIndent = IsLineIsEmptyUpToEol(rbraceOffset) ? curIndent.IndentString : this.options.EolMarker + curIndent.IndentString;
1282
case BraceStyle.EndOfLine:
1283
prevNode = lbrace.GetPrevNode();
1284
if (prevNode is Comment) {
1285
// delete old bracket
1286
AddChange(whitespaceStart, lbraceOffset - whitespaceStart + 1, "");
1288
while (prevNode is Comment) {
1289
prevNode = prevNode.GetPrevNode();
1291
whitespaceStart = document.GetOffset(prevNode.EndLocation);
1292
lbraceOffset = whitespaceStart;
1297
endIndent = IsLineIsEmptyUpToEol(rbraceOffset) ? curIndent.IndentString : this.options.EolMarker + curIndent.IndentString;
1299
case BraceStyle.NextLine:
1300
startIndent = this.options.EolMarker + curIndent.IndentString;
1301
endIndent = IsLineIsEmptyUpToEol(rbraceOffset) ? curIndent.IndentString : this.options.EolMarker + curIndent.IndentString;
1303
case BraceStyle.NextLineShifted2:
1304
case BraceStyle.NextLineShifted:
1305
curIndent.Push(IndentType.Block);
1306
startIndent = this.options.EolMarker + curIndent.IndentString;
1307
endIndent = IsLineIsEmptyUpToEol(rbraceOffset) ? curIndent.IndentString : this.options.EolMarker + curIndent.IndentString;
1312
if (lbraceOffset > 0 && startIndent != null) {
1313
AddChange(whitespaceStart, lbraceOffset - whitespaceStart, startIndent);
1315
if (rbraceOffset > 0 && endIndent != null) {
1316
AddChange(whitespaceEnd, rbraceOffset - whitespaceEnd, endIndent);
1320
TextReplaceAction AddChange(int offset, int removedChars, string insertedText)
1322
if (removedChars == 0 && string.IsNullOrEmpty (insertedText))
1324
var action = new TextReplaceAction (offset, removedChars, insertedText);
1325
changes.Add(action);
1329
public bool IsLineIsEmptyUpToEol(TextLocation startLocation)
1331
return IsLineIsEmptyUpToEol(document.GetOffset(startLocation) - 1);
1334
bool IsLineIsEmptyUpToEol(int startOffset)
1336
for (int offset = startOffset - 1; offset >= 0; offset--) {
1337
char ch = document.GetCharAt(offset);
1338
if (ch != ' ' && ch != '\t') {
1339
return ch == '\n' || ch == '\r';
1345
int SearchWhitespaceStart(int startOffset)
1347
if (startOffset < 0) {
1348
throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset);
1350
for (int offset = startOffset - 1; offset >= 0; offset--) {
1351
char ch = document.GetCharAt(offset);
1352
if (!Char.IsWhiteSpace(ch)) {
1359
int SearchWhitespaceEnd(int startOffset)
1361
if (startOffset > document.TextLength) {
1362
throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset);
1364
for (int offset = startOffset + 1; offset < document.TextLength; offset++) {
1365
char ch = document.GetCharAt(offset);
1366
if (!Char.IsWhiteSpace(ch)) {
1370
return document.TextLength - 1;
1373
int SearchWhitespaceLineStart(int startOffset)
1375
if (startOffset < 0) {
1376
throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset);
1378
for (int offset = startOffset - 1; offset >= 0; offset--) {
1379
char ch = document.GetCharAt(offset);
1380
if (ch != ' ' && ch != '\t') {
1387
public override void VisitForStatement(ForStatement forStatement)
1389
foreach (AstNode node in forStatement.Children) {
1390
if (node.Role == Roles.Semicolon) {
1391
if (node.NextSibling is CSharpTokenNode || node.NextSibling is EmptyStatement) {
1394
ForceSpacesBefore(node, policy.SpaceBeforeForSemicolon);
1395
ForceSpacesAfter(node, policy.SpaceAfterForSemicolon);
1399
ForceSpacesBefore(forStatement.LParToken, policy.SpaceBeforeForParentheses);
1401
ForceSpacesAfter(forStatement.LParToken, policy.SpacesWithinForParentheses);
1402
ForceSpacesBefore(forStatement.RParToken, policy.SpacesWithinForParentheses);
1404
FixEmbeddedStatment(policy.StatementBraceStyle, policy.ForBraceForcement, forStatement.EmbeddedStatement);
1407
public override void VisitGotoStatement(GotoStatement gotoStatement)
1409
VisitChildren(gotoStatement);
1410
FixSemicolon(gotoStatement.SemicolonToken);
1413
public override void VisitIfElseStatement(IfElseStatement ifElseStatement)
1415
ForceSpacesBefore(ifElseStatement.LParToken, policy.SpaceBeforeIfParentheses);
1417
ForceSpacesAfter(ifElseStatement.LParToken, policy.SpacesWithinIfParentheses);
1418
ForceSpacesBefore(ifElseStatement.RParToken, policy.SpacesWithinIfParentheses);
1420
if (!(ifElseStatement.Parent is IfElseStatement && ((IfElseStatement)ifElseStatement.Parent).FalseStatement == ifElseStatement)) {
1421
FixStatementIndentation(ifElseStatement.StartLocation);
1424
if (!ifElseStatement.Condition.IsNull) {
1425
ifElseStatement.Condition.AcceptVisitor(this);
1428
if (!ifElseStatement.TrueStatement.IsNull) {
1429
FixEmbeddedStatment(policy.StatementBraceStyle, policy.IfElseBraceForcement, ifElseStatement.IfToken, policy.AllowIfBlockInline, ifElseStatement.TrueStatement);
1432
if (!ifElseStatement.FalseStatement.IsNull) {
1433
var placeElseOnNewLine = policy.ElseNewLinePlacement;
1434
if (!(ifElseStatement.TrueStatement is BlockStatement) && policy.IfElseBraceForcement != BraceForcement.AddBraces)
1435
placeElseOnNewLine = NewLinePlacement.NewLine;
1436
PlaceOnNewLine(placeElseOnNewLine, ifElseStatement.ElseToken);
1437
var forcement = policy.IfElseBraceForcement;
1438
if (ifElseStatement.FalseStatement is IfElseStatement) {
1439
forcement = BraceForcement.DoNotChange;
1440
PlaceOnNewLine(policy.ElseIfNewLinePlacement, ((IfElseStatement)ifElseStatement.FalseStatement).IfToken);
1442
FixEmbeddedStatment(policy.StatementBraceStyle, forcement, ifElseStatement.ElseToken, policy.AllowIfBlockInline, ifElseStatement.FalseStatement, ifElseStatement.FalseStatement is IfElseStatement);
1446
public override void VisitLabelStatement(LabelStatement labelStatement)
1449
VisitChildren(labelStatement);
1452
public override void VisitLockStatement(LockStatement lockStatement)
1454
ForceSpacesBefore(lockStatement.LParToken, policy.SpaceBeforeLockParentheses);
1456
ForceSpacesAfter(lockStatement.LParToken, policy.SpacesWithinLockParentheses);
1457
ForceSpacesBefore(lockStatement.RParToken, policy.SpacesWithinLockParentheses);
1459
FixEmbeddedStatment(policy.StatementBraceStyle, policy.FixedBraceForcement, lockStatement.EmbeddedStatement);
1462
public override void VisitReturnStatement(ReturnStatement returnStatement)
1464
VisitChildren(returnStatement);
1465
FixSemicolon(returnStatement.SemicolonToken);
1468
public override void VisitSwitchStatement(SwitchStatement switchStatement)
1470
ForceSpacesBefore(switchStatement.LParToken, policy.SpaceBeforeSwitchParentheses);
1472
ForceSpacesAfter(switchStatement.LParToken, policy.SpacesWithinSwitchParentheses);
1473
ForceSpacesBefore(switchStatement.RParToken, policy.SpacesWithinSwitchParentheses);
1475
EnforceBraceStyle(policy.StatementBraceStyle, switchStatement.LBraceToken, switchStatement.RBraceToken);
1476
VisitChildren(switchStatement);
1479
public override void VisitSwitchSection(SwitchSection switchSection)
1481
if (policy.IndentSwitchBody) {
1482
curIndent.Push(IndentType.Block);
1485
foreach (CaseLabel label in switchSection.CaseLabels) {
1486
FixStatementIndentation(label.StartLocation);
1487
label.AcceptVisitor(this);
1489
if (policy.IndentCaseBody) {
1490
curIndent.Push(IndentType.Block);
1493
foreach (var stmt in switchSection.Statements) {
1494
if (stmt is BreakStatement && !policy.IndentBreakStatements && policy.IndentCaseBody) {
1496
FixStatementIndentation(stmt.StartLocation);
1497
stmt.AcceptVisitor(this);
1498
curIndent.Push(IndentType.Block);
1501
FixStatementIndentation(stmt.StartLocation);
1502
stmt.AcceptVisitor(this);
1504
if (policy.IndentCaseBody) {
1508
if (policy.IndentSwitchBody) {
1513
public override void VisitCaseLabel(CaseLabel caseLabel)
1515
FixSemicolon(caseLabel.ColonToken);
1518
public override void VisitThrowStatement(ThrowStatement throwStatement)
1520
VisitChildren(throwStatement);
1521
FixSemicolon(throwStatement.SemicolonToken);
1524
public override void VisitTryCatchStatement(TryCatchStatement tryCatchStatement)
1526
if (!tryCatchStatement.TryBlock.IsNull) {
1527
FixEmbeddedStatment(policy.StatementBraceStyle, BraceForcement.DoNotChange, tryCatchStatement.TryBlock);
1530
foreach (CatchClause clause in tryCatchStatement.CatchClauses) {
1531
PlaceOnNewLine(policy.CatchNewLinePlacement, clause.CatchToken);
1532
if (!clause.LParToken.IsNull) {
1533
ForceSpacesBefore(clause.LParToken, policy.SpaceBeforeCatchParentheses);
1535
ForceSpacesAfter(clause.LParToken, policy.SpacesWithinCatchParentheses);
1536
ForceSpacesBefore(clause.RParToken, policy.SpacesWithinCatchParentheses);
1538
FixEmbeddedStatment(policy.StatementBraceStyle, BraceForcement.DoNotChange, clause.Body);
1541
if (!tryCatchStatement.FinallyBlock.IsNull) {
1542
PlaceOnNewLine(policy.FinallyNewLinePlacement, tryCatchStatement.FinallyToken);
1544
FixEmbeddedStatment(policy.StatementBraceStyle, BraceForcement.DoNotChange, tryCatchStatement.FinallyBlock);
1549
public override void VisitCatchClause(CatchClause catchClause)
1551
// Handled in TryCatchStatement
1554
public override void VisitUncheckedStatement(UncheckedStatement uncheckedStatement)
1556
FixEmbeddedStatment(policy.StatementBraceStyle, policy.FixedBraceForcement, uncheckedStatement.Body);
1559
public override void VisitUnsafeStatement(UnsafeStatement unsafeStatement)
1561
FixEmbeddedStatment(policy.StatementBraceStyle, BraceForcement.DoNotChange, unsafeStatement.Body);
1564
public override void VisitUsingStatement(UsingStatement usingStatement)
1566
ForceSpacesBefore(usingStatement.LParToken, policy.SpaceBeforeUsingParentheses);
1568
ForceSpacesAfter(usingStatement.LParToken, policy.SpacesWithinUsingParentheses);
1569
ForceSpacesBefore(usingStatement.RParToken, policy.SpacesWithinUsingParentheses);
1571
FixEmbeddedStatment(policy.StatementBraceStyle, policy.UsingBraceForcement, usingStatement.EmbeddedStatement);
1574
public override void VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement)
1576
if ((variableDeclarationStatement.Modifiers & Modifiers.Const) == Modifiers.Const) {
1577
ForceSpacesAround(variableDeclarationStatement.Type, true);
1579
ForceSpacesAfter(variableDeclarationStatement.Type, true);
1581
var lastLoc = variableDeclarationStatement.StartLocation;
1582
foreach (var initializer in variableDeclarationStatement.Variables) {
1583
if (lastLoc.Line != initializer.StartLocation.Line) {
1584
FixStatementIndentation(initializer.StartLocation);
1585
lastLoc = initializer.StartLocation;
1587
initializer.AcceptVisitor(this);
1590
FormatCommas(variableDeclarationStatement, policy.SpaceBeforeLocalVariableDeclarationComma, policy.SpaceAfterLocalVariableDeclarationComma);
1591
FixSemicolon(variableDeclarationStatement.SemicolonToken);
1594
public override void VisitDoWhileStatement(DoWhileStatement doWhileStatement)
1596
PlaceOnNewLine(policy.WhileNewLinePlacement, doWhileStatement.WhileToken);
1597
FixEmbeddedStatment(policy.StatementBraceStyle, policy.WhileBraceForcement, doWhileStatement.EmbeddedStatement);
1600
public override void VisitWhileStatement(WhileStatement whileStatement)
1602
ForceSpacesBefore(whileStatement.LParToken, policy.SpaceBeforeWhileParentheses);
1604
ForceSpacesAfter(whileStatement.LParToken, policy.SpacesWithinWhileParentheses);
1605
ForceSpacesBefore(whileStatement.RParToken, policy.SpacesWithinWhileParentheses);
1607
FixEmbeddedStatment(policy.StatementBraceStyle, policy.WhileBraceForcement, whileStatement.EmbeddedStatement);
1610
public override void VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement)
1612
FixSemicolon(yieldBreakStatement.SemicolonToken);
1615
public override void VisitYieldReturnStatement(YieldReturnStatement yieldStatement)
1617
yieldStatement.Expression.AcceptVisitor(this);
1618
FixSemicolon(yieldStatement.SemicolonToken);
1621
public override void VisitVariableInitializer(VariableInitializer variableInitializer)
1623
if (!variableInitializer.AssignToken.IsNull) {
1624
ForceSpacesAround(variableInitializer.AssignToken, policy.SpaceAroundAssignment);
1626
if (!variableInitializer.Initializer.IsNull) {
1627
variableInitializer.Initializer.AcceptVisitor(this);
1634
public override void VisitComposedType(ComposedType composedType)
1636
var spec = composedType.ArraySpecifiers.FirstOrDefault();
1638
ForceSpacesBefore(spec.LBracketToken, policy.SpaceBeforeArrayDeclarationBrackets);
1641
base.VisitComposedType(composedType);
1644
public override void VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
1646
if (!anonymousMethodExpression.Body.IsNull) {
1647
EnforceBraceStyle(policy.AnonymousMethodBraceStyle, anonymousMethodExpression.Body.LBraceToken, anonymousMethodExpression.Body.RBraceToken);
1649
base.VisitAnonymousMethodExpression(anonymousMethodExpression);
1652
public override void VisitAssignmentExpression(AssignmentExpression assignmentExpression)
1654
ForceSpacesAround(assignmentExpression.OperatorToken, policy.SpaceAroundAssignment);
1655
base.VisitAssignmentExpression(assignmentExpression);
1658
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
1660
bool forceSpaces = false;
1661
switch (binaryOperatorExpression.Operator) {
1662
case BinaryOperatorType.Equality:
1663
case BinaryOperatorType.InEquality:
1664
forceSpaces = policy.SpaceAroundEqualityOperator;
1666
case BinaryOperatorType.GreaterThan:
1667
case BinaryOperatorType.GreaterThanOrEqual:
1668
case BinaryOperatorType.LessThan:
1669
case BinaryOperatorType.LessThanOrEqual:
1670
forceSpaces = policy.SpaceAroundRelationalOperator;
1672
case BinaryOperatorType.ConditionalAnd:
1673
case BinaryOperatorType.ConditionalOr:
1674
forceSpaces = policy.SpaceAroundLogicalOperator;
1676
case BinaryOperatorType.BitwiseAnd:
1677
case BinaryOperatorType.BitwiseOr:
1678
case BinaryOperatorType.ExclusiveOr:
1679
forceSpaces = policy.SpaceAroundBitwiseOperator;
1681
case BinaryOperatorType.Add:
1682
case BinaryOperatorType.Subtract:
1683
forceSpaces = policy.SpaceAroundAdditiveOperator;
1685
case BinaryOperatorType.Multiply:
1686
case BinaryOperatorType.Divide:
1687
case BinaryOperatorType.Modulus:
1688
forceSpaces = policy.SpaceAroundMultiplicativeOperator;
1690
case BinaryOperatorType.ShiftLeft:
1691
case BinaryOperatorType.ShiftRight:
1692
forceSpaces = policy.SpaceAroundShiftOperator;
1694
case BinaryOperatorType.NullCoalescing:
1695
forceSpaces = policy.SpaceAroundNullCoalescingOperator;
1698
ForceSpacesAround(binaryOperatorExpression.OperatorToken, forceSpaces);
1700
base.VisitBinaryOperatorExpression(binaryOperatorExpression);
1701
// Handle line breaks in binary opeartor expression.
1702
if (binaryOperatorExpression.Left.EndLocation.Line != binaryOperatorExpression.Right.StartLocation.Line) {
1703
curIndent.Push(IndentType.Block);
1704
if (binaryOperatorExpression.OperatorToken.StartLocation.Line == binaryOperatorExpression.Right.StartLocation.Line) {
1705
FixStatementIndentation(binaryOperatorExpression.OperatorToken.StartLocation);
1707
FixStatementIndentation(binaryOperatorExpression.Right.StartLocation);
1713
public override void VisitConditionalExpression(ConditionalExpression conditionalExpression)
1715
ForceSpacesBefore(conditionalExpression.QuestionMarkToken, policy.SpaceBeforeConditionalOperatorCondition);
1716
ForceSpacesAfter(conditionalExpression.QuestionMarkToken, policy.SpaceAfterConditionalOperatorCondition);
1717
ForceSpacesBefore(conditionalExpression.ColonToken, policy.SpaceBeforeConditionalOperatorSeparator);
1718
ForceSpacesAfter(conditionalExpression.ColonToken, policy.SpaceAfterConditionalOperatorSeparator);
1719
base.VisitConditionalExpression(conditionalExpression);
1722
public override void VisitCastExpression(CastExpression castExpression)
1724
if (castExpression.RParToken != null) {
1725
ForceSpacesAfter(castExpression.LParToken, policy.SpacesWithinCastParentheses);
1726
ForceSpacesBefore(castExpression.RParToken, policy.SpacesWithinCastParentheses);
1728
ForceSpacesAfter(castExpression.RParToken, policy.SpaceAfterTypecast);
1730
base.VisitCastExpression(castExpression);
1733
void ForceSpacesAround(AstNode node, bool forceSpaces)
1738
ForceSpacesBefore(node, forceSpaces);
1739
ForceSpacesAfter(node, forceSpaces);
1742
void FormatCommas(AstNode parent, bool before, bool after)
1744
if (parent.IsNull) {
1747
foreach (CSharpTokenNode comma in parent.Children.Where (node => node.Role == Roles.Comma)) {
1748
ForceSpacesAfter(comma, after);
1749
ForceSpacesBefore(comma, before);
1753
bool DoWrap (Wrapping wrapping, AstNode wrapNode, int argumentCount)
1755
return wrapping == Wrapping.WrapAlways ||
1756
options.WrapLineLength > 0 && argumentCount > 1 && wrapping == Wrapping.WrapIfTooLong && wrapNode.StartLocation.Column >= options.WrapLineLength;
1759
void FormatArguments(AstNode node)
1761
Wrapping methodCallArgumentWrapping;
1762
bool newLineAferMethodCallOpenParentheses;
1763
bool methodClosingParenthesesOnNewLine;
1764
bool spaceWithinMethodCallParentheses;
1765
bool spaceAfterMethodCallParameterComma;
1766
bool spaceBeforeMethodCallParameterComma;
1768
CSharpTokenNode rParToken;
1769
AstNodeCollection<Expression> arguments;
1770
var indexer = node as IndexerExpression;
1771
if (indexer != null) {
1772
methodCallArgumentWrapping = policy.IndexerArgumentWrapping;
1773
newLineAferMethodCallOpenParentheses = policy.NewLineAferIndexerOpenBracket;
1774
methodClosingParenthesesOnNewLine = policy.IndexerClosingBracketOnNewLine;
1775
spaceWithinMethodCallParentheses = policy.SpacesWithinBrackets;
1776
spaceAfterMethodCallParameterComma = policy.SpaceAfterBracketComma;
1777
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeBracketComma;
1779
rParToken = indexer.RBracketToken;
1780
arguments = indexer.Arguments;
1781
} else if (node is ObjectCreateExpression) {
1782
var oce = node as ObjectCreateExpression;
1783
methodCallArgumentWrapping = policy.MethodCallArgumentWrapping;
1784
newLineAferMethodCallOpenParentheses = policy.NewLineAferMethodCallOpenParentheses;
1785
methodClosingParenthesesOnNewLine = policy.MethodCallClosingParenthesesOnNewLine;
1786
spaceWithinMethodCallParentheses = policy.SpacesWithinNewParentheses;
1787
spaceAfterMethodCallParameterComma = policy.SpaceAfterNewParameterComma;
1788
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeNewParameterComma;
1790
rParToken = oce.RParToken;
1791
arguments = oce.Arguments;
1793
InvocationExpression invocationExpression = node as InvocationExpression;
1794
methodCallArgumentWrapping = policy.MethodCallArgumentWrapping;
1795
newLineAferMethodCallOpenParentheses = policy.NewLineAferMethodCallOpenParentheses;
1796
methodClosingParenthesesOnNewLine = policy.MethodCallClosingParenthesesOnNewLine;
1797
spaceWithinMethodCallParentheses = policy.SpaceWithinMethodCallParentheses;
1798
spaceAfterMethodCallParameterComma = policy.SpaceAfterMethodCallParameterComma;
1799
spaceBeforeMethodCallParameterComma = policy.SpaceBeforeMethodCallParameterComma;
1801
rParToken = invocationExpression.RParToken;
1802
arguments = invocationExpression.Arguments;
1805
if (FormattingMode == ICSharpCode.NRefactory.CSharp.FormattingMode.OnTheFly)
1806
methodCallArgumentWrapping = Wrapping.DoNotChange;
1808
bool wrapMethodCall = DoWrap(methodCallArgumentWrapping, rParToken, arguments.Count);
1809
if (wrapMethodCall && arguments.Any()) {
1810
if (newLineAferMethodCallOpenParentheses) {
1811
curIndent.Push(IndentType.Continuation);
1812
foreach (var arg in arguments) {
1813
FixStatementIndentation(arg.StartLocation);
1817
int extraSpaces = arguments.First().StartLocation.Column - 1 - curIndent.IndentString.Length;
1818
curIndent.ExtraSpaces += extraSpaces;
1819
foreach (var arg in arguments.Skip(1)) {
1820
FixStatementIndentation(arg.StartLocation);
1822
curIndent.ExtraSpaces -= extraSpaces;
1824
if (!rParToken.IsNull) {
1825
if (methodClosingParenthesesOnNewLine) {
1826
FixStatementIndentation(rParToken.StartLocation);
1828
ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses);
1832
foreach (var arg in arguments) {
1833
if (arg.PrevSibling != null) {
1834
if (methodCallArgumentWrapping == Wrapping.DoNotWrap) {
1835
ForceSpacesBeforeRemoveNewLines(arg, spaceAfterMethodCallParameterComma && arg.PrevSibling.Role == Roles.Comma);
1837
ForceSpacesBefore(arg, spaceAfterMethodCallParameterComma && arg.PrevSibling.Role == Roles.Comma);
1840
arg.AcceptVisitor(this);
1842
if (!rParToken.IsNull) {
1843
if (methodCallArgumentWrapping == Wrapping.DoNotWrap) {
1844
ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses);
1846
bool sameLine = rParToken.GetPrevNode().StartLocation.Line == rParToken.StartLocation.Line;
1848
ForceSpacesBeforeRemoveNewLines(rParToken, spaceWithinMethodCallParentheses);
1850
FixStatementIndentation(rParToken.StartLocation);
1855
if (!rParToken.IsNull) {
1856
foreach (CSharpTokenNode comma in rParToken.Parent.Children.Where(n => n.Role == Roles.Comma)) {
1857
ForceSpacesBefore(comma, spaceBeforeMethodCallParameterComma);
1862
public override void VisitInvocationExpression(InvocationExpression invocationExpression)
1864
ForceSpacesBefore(invocationExpression.LParToken, policy.SpaceBeforeMethodCallParentheses);
1865
if (invocationExpression.Arguments.Any()) {
1866
ForceSpacesAfter(invocationExpression.LParToken, policy.SpaceWithinMethodCallParentheses);
1868
ForceSpacesAfter(invocationExpression.LParToken, policy.SpaceBetweenEmptyMethodCallParentheses);
1869
ForceSpacesBefore(invocationExpression.RParToken, policy.SpaceBetweenEmptyMethodCallParentheses);
1872
if (!invocationExpression.Target.IsNull)
1873
invocationExpression.Target.AcceptVisitor(this);
1875
if (invocationExpression.Target is MemberReferenceExpression) {
1876
var mt = (MemberReferenceExpression)invocationExpression.Target;
1877
if (mt.Target is InvocationExpression) {
1878
if (DoWrap(policy.ChainedMethodCallWrapping, mt.DotToken, 2)) {
1879
curIndent.Push(IndentType.Continuation);
1880
FixStatementIndentation(mt.DotToken.StartLocation);
1883
if (policy.ChainedMethodCallWrapping == Wrapping.DoNotWrap)
1884
ForceSpacesBeforeRemoveNewLines(mt.DotToken, false);
1888
FormatArguments(invocationExpression);
1891
public override void VisitIndexerExpression(IndexerExpression indexerExpression)
1893
ForceSpacesBefore(indexerExpression.LBracketToken, policy.SpacesBeforeBrackets);
1894
ForceSpacesAfter(indexerExpression.LBracketToken, policy.SpacesWithinBrackets);
1896
if (!indexerExpression.Target.IsNull)
1897
indexerExpression.Target.AcceptVisitor(this);
1899
FormatArguments(indexerExpression);
1905
public override void VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression)
1907
ForceSpacesAfter(parenthesizedExpression.LParToken, policy.SpacesWithinParentheses);
1908
ForceSpacesBefore(parenthesizedExpression.RParToken, policy.SpacesWithinParentheses);
1909
base.VisitParenthesizedExpression(parenthesizedExpression);
1912
public override void VisitSizeOfExpression(SizeOfExpression sizeOfExpression)
1914
ForceSpacesBefore(sizeOfExpression.LParToken, policy.SpaceBeforeSizeOfParentheses);
1915
ForceSpacesAfter(sizeOfExpression.LParToken, policy.SpacesWithinSizeOfParentheses);
1916
ForceSpacesBefore(sizeOfExpression.RParToken, policy.SpacesWithinSizeOfParentheses);
1917
base.VisitSizeOfExpression(sizeOfExpression);
1920
public override void VisitTypeOfExpression(TypeOfExpression typeOfExpression)
1922
ForceSpacesBefore(typeOfExpression.LParToken, policy.SpaceBeforeTypeOfParentheses);
1923
ForceSpacesAfter(typeOfExpression.LParToken, policy.SpacesWithinTypeOfParentheses);
1924
ForceSpacesBefore(typeOfExpression.RParToken, policy.SpacesWithinTypeOfParentheses);
1925
base.VisitTypeOfExpression(typeOfExpression);
1928
public override void VisitCheckedExpression(CheckedExpression checkedExpression)
1930
ForceSpacesAfter(checkedExpression.LParToken, policy.SpacesWithinCheckedExpressionParantheses);
1931
ForceSpacesBefore(checkedExpression.RParToken, policy.SpacesWithinCheckedExpressionParantheses);
1932
base.VisitCheckedExpression(checkedExpression);
1935
public override void VisitUncheckedExpression(UncheckedExpression uncheckedExpression)
1937
ForceSpacesAfter(uncheckedExpression.LParToken, policy.SpacesWithinCheckedExpressionParantheses);
1938
ForceSpacesBefore(uncheckedExpression.RParToken, policy.SpacesWithinCheckedExpressionParantheses);
1939
base.VisitUncheckedExpression(uncheckedExpression);
1942
public override void VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression)
1944
ForceSpacesBefore(objectCreateExpression.LParToken, policy.SpaceBeforeNewParentheses);
1946
if (objectCreateExpression.Arguments.Any()) {
1947
if (!objectCreateExpression.LParToken.IsNull)
1948
ForceSpacesAfter(objectCreateExpression.LParToken, policy.SpacesWithinNewParentheses);
1950
if (!objectCreateExpression.LParToken.IsNull)
1951
ForceSpacesAfter(objectCreateExpression.LParToken, policy.SpacesBetweenEmptyNewParentheses);
1954
if (!objectCreateExpression.Type.IsNull)
1955
objectCreateExpression.Type.AcceptVisitor(this);
1957
FormatArguments(objectCreateExpression);
1961
public override void VisitArrayCreateExpression(ArrayCreateExpression arrayObjectCreateExpression)
1963
FormatCommas(arrayObjectCreateExpression, policy.SpaceBeforeMethodCallParameterComma, policy.SpaceAfterMethodCallParameterComma);
1964
base.VisitArrayCreateExpression(arrayObjectCreateExpression);
1967
public override void VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression)
1969
if (DoWrap(policy.ArrayInitializerWrapping, arrayInitializerExpression.RBraceToken, arrayInitializerExpression.Elements.Count)) {
1970
EnforceBraceStyle(policy.ArrayInitializerBraceStyle, arrayInitializerExpression.LBraceToken, arrayInitializerExpression.RBraceToken);
1971
curIndent.Push(IndentType.Block);
1972
foreach (var init in arrayInitializerExpression.Elements) {
1973
FixStatementIndentation(init.StartLocation);
1974
init.AcceptVisitor(this);
1977
} else if (policy.ArrayInitializerWrapping == Wrapping.DoNotWrap) {
1978
ForceSpacesBeforeRemoveNewLines(arrayInitializerExpression.LBraceToken);
1979
ForceSpacesBeforeRemoveNewLines(arrayInitializerExpression.RBraceToken);
1980
foreach (var init in arrayInitializerExpression.Elements) {
1981
ForceSpacesBeforeRemoveNewLines(init);
1982
init.AcceptVisitor(this);
1985
base.VisitArrayInitializerExpression(arrayInitializerExpression);
1989
public override void VisitLambdaExpression(LambdaExpression lambdaExpression)
1991
ForceSpacesAfter(lambdaExpression.ArrowToken, true);
1992
ForceSpacesBefore(lambdaExpression.ArrowToken, true);
1994
base.VisitLambdaExpression(lambdaExpression);
1997
public override void VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression)
1999
ForceSpacesAfter(namedArgumentExpression.ColonToken, policy.SpaceInNamedArgumentAfterDoubleColon);
2000
base.VisitNamedArgumentExpression(namedArgumentExpression);
2003
public override void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
2005
ForceSpacesAfter(memberReferenceExpression.DotToken, false);
2006
base.VisitMemberReferenceExpression(memberReferenceExpression);
2011
void ForceSpaceBefore(int offset, bool forceSpace)
2013
bool insertedSpace = false;
2015
char ch = document.GetCharAt(offset);
2016
//Console.WriteLine (ch);
2017
if (!IsSpacing(ch) && (insertedSpace || !forceSpace)) {
2020
if (ch == ' ' && forceSpace) {
2021
if (insertedSpace) {
2022
AddChange(offset, 1, null);
2024
insertedSpace = true;
2026
} else if (forceSpace) {
2027
if (!insertedSpace) {
2028
AddChange(offset, IsSpacing(ch) ? 1 : 0, " ");
2029
insertedSpace = true;
2030
} else if (IsSpacing(ch)) {
2031
AddChange(offset, 1, null);
2036
} while (offset >= 0);
2042
int GetLastNonWsChar (LineSegment line, int lastColumn)
2045
bool inComment = false;
2046
for (int i = 0; i < lastColumn; i++) {
2047
char ch = data.GetCharAt (line.Offset + i);
2048
if (Char.IsWhiteSpace (ch))
2050
if (ch == '/' && i + 1 < line.EditableLength && data.GetCharAt (line.Offset + i + 1) == '/')
2052
if (ch == '/' && i + 1 < line.EditableLength && data.GetCharAt (line.Offset + i + 1) == '*') {
2057
if (inComment && ch == '*' && i + 1 < line.EditableLength && data.GetCharAt (line.Offset + i + 1) == '/') {
2070
public void FixSemicolon(CSharpTokenNode semicolon)
2072
if (semicolon.IsNull) {
2075
int endOffset = document.GetOffset(semicolon.StartLocation);
2076
int offset = endOffset;
2077
while (offset - 1 > 0 && char.IsWhiteSpace (document.GetCharAt (offset - 1))) {
2080
if (offset < endOffset) {
2081
AddChange(offset, endOffset - offset, null);
2085
void PlaceOnNewLine(NewLinePlacement newLine, AstNode keywordNode)
2087
if (keywordNode == null || newLine == NewLinePlacement.DoNotCare) {
2091
var prev = keywordNode.GetPrevNode ();
2092
if (prev is Comment || prev is PreProcessorDirective)
2095
int offset = document.GetOffset(keywordNode.StartLocation);
2097
int whitespaceStart = SearchWhitespaceStart(offset);
2098
string indentString = newLine == NewLinePlacement.NewLine ? this.options.EolMarker + this.curIndent.IndentString : " ";
2099
AddChange(whitespaceStart, offset - whitespaceStart, indentString);
2102
string nextStatementIndent = null;
2104
void FixStatementIndentation(TextLocation location)
2106
int offset = document.GetOffset(location);
2108
Console.WriteLine("possible wrong offset");
2109
Console.WriteLine(Environment.StackTrace);
2112
bool isEmpty = IsLineIsEmptyUpToEol(offset);
2113
int lineStart = SearchWhitespaceLineStart(offset);
2114
string indentString = nextStatementIndent == null ? (isEmpty ? "" : this.options.EolMarker) + this.curIndent.IndentString : nextStatementIndent;
2115
nextStatementIndent = null;
2116
AddChange(lineStart, offset - lineStart, indentString);
2119
void FixIndentation(TextLocation location)
2121
FixIndentation(location, 0);
2124
void FixIndentation(TextLocation location, int relOffset)
2126
if (location.Line < 1 || location.Line > document.LineCount) {
2127
Console.WriteLine("Invalid location " + location);
2128
Console.WriteLine(Environment.StackTrace);
2132
string lineIndent = GetIndentation(location.Line);
2133
string indentString = this.curIndent.IndentString;
2134
if (indentString != lineIndent && location.Column - 1 + relOffset == lineIndent.Length) {
2135
AddChange(document.GetOffset(location.Line, 1), lineIndent.Length, indentString);
2139
void FixIndentationForceNewLine(TextLocation location)
2141
string lineIndent = GetIndentation(location.Line);
2142
string indentString = this.curIndent.IndentString;
2143
if (location.Column - 1 == lineIndent.Length) {
2144
AddChange(document.GetOffset(location.Line, 1), lineIndent.Length, indentString);
2146
int offset = document.GetOffset(location);
2147
int start = SearchWhitespaceLineStart(offset);
2149
char ch = document.GetCharAt(start - 1);
2152
if (start > 1 && document.GetCharAt(start - 1) == '\r') {
2155
} else if (ch == '\r') {
2158
AddChange(start, offset - start, this.options.EolMarker + indentString);
2163
string GetIndentation(int lineNumber)
2165
IDocumentLine line = document.GetLineByNumber(lineNumber);
2166
StringBuilder b = new StringBuilder ();
2167
int endOffset = line.EndOffset;
2168
for (int i = line.Offset; i < endOffset; i++) {
2169
char c = document.GetCharAt(i);
2170
if (!IsSpacing(c)) {
2175
return b.ToString();