Free cookie consent management tool by TermsFeed Policy Generator

source: tags/3.3.13/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/OutputVisitor/CSharpOutputVisitor.cs

Last change on this file was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 75.1 KB
Line 
1// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18using System;
19using System.Collections.Generic;
20using System.Diagnostics;
21using System.Globalization;
22using System.IO;
23using System.Linq;
24using System.Text;
25using System.Threading.Tasks;
26using ICSharpCode.NRefactory.PatternMatching;
27using ICSharpCode.NRefactory.TypeSystem;
28using ICSharpCode.NRefactory.CSharp;
29
30namespace ICSharpCode.NRefactory.CSharp
31{
32  /// <summary>
33  /// Outputs the AST.
34  /// </summary>
35  public class CSharpOutputVisitor : IAstVisitor
36  {
37    readonly TokenWriter writer;
38    readonly CSharpFormattingOptions policy;
39    readonly Stack<AstNode> containerStack = new Stack<AstNode> ();
40   
41    public CSharpOutputVisitor (TextWriter textWriter, CSharpFormattingOptions formattingPolicy)
42    {
43      if (textWriter == null) {
44        throw new ArgumentNullException ("textWriter");
45      }
46      if (formattingPolicy == null) {
47        throw new ArgumentNullException ("formattingPolicy");
48      }
49      this.writer = TokenWriter.Create(textWriter);
50      this.policy = formattingPolicy;
51    }
52   
53    public CSharpOutputVisitor (TokenWriter writer, CSharpFormattingOptions formattingPolicy)
54    {
55      if (writer == null) {
56        throw new ArgumentNullException ("writer");
57      }
58      if (formattingPolicy == null) {
59        throw new ArgumentNullException ("formattingPolicy");
60      }
61      this.writer = new InsertSpecialsDecorator(new InsertRequiredSpacesDecorator(writer));
62      this.policy = formattingPolicy;
63    }
64   
65    #region StartNode/EndNode
66    void StartNode(AstNode node)
67    {
68      // Ensure that nodes are visited in the proper nested order.
69      // Jumps to different subtrees are allowed only for the child of a placeholder node.
70      Debug.Assert(containerStack.Count == 0 || node.Parent == containerStack.Peek() || containerStack.Peek().NodeType == NodeType.Pattern);
71      containerStack.Push(node);
72      writer.StartNode(node);
73    }
74   
75    void EndNode(AstNode node)
76    {
77      Debug.Assert(node == containerStack.Peek());
78      containerStack.Pop();
79      writer.EndNode(node);
80    }
81    #endregion
82   
83    #region Comma
84    /// <summary>
85    /// Writes a comma.
86    /// </summary>
87    /// <param name="nextNode">The next node after the comma.</param>
88    /// <param name="noSpaceAfterComma">When set prevents printing a space after comma.</param>
89    void Comma(AstNode nextNode, bool noSpaceAfterComma = false)
90    {
91      Space(policy.SpaceBeforeBracketComma);
92      // TODO: Comma policy has changed.
93      writer.WriteToken(Roles.Comma, ",");
94      Space(!noSpaceAfterComma && policy.SpaceAfterBracketComma);
95      // TODO: Comma policy has changed.
96    }
97   
98    /// <summary>
99    /// Writes an optional comma, e.g. at the end of an enum declaration or in an array initializer
100    /// </summary>
101    void OptionalComma(AstNode pos)
102    {
103      // Look if there's a comma after the current node, and insert it if it exists.
104      while (pos != null && pos.NodeType == NodeType.Whitespace) {
105        pos = pos.NextSibling;
106      }
107      if (pos != null && pos.Role == Roles.Comma) {
108        Comma(null, noSpaceAfterComma: true);
109      }
110    }
111   
112    /// <summary>
113    /// Writes an optional semicolon, e.g. at the end of a type or namespace declaration.
114    /// </summary>
115    void OptionalSemicolon(AstNode pos)
116    {
117      // Look if there's a semicolon after the current node, and insert it if it exists.
118      while (pos != null && pos.NodeType == NodeType.Whitespace) {
119        pos = pos.PrevSibling;
120      }
121      if (pos != null && pos.Role == Roles.Semicolon) {
122        Semicolon();
123      }
124    }
125   
126    void WriteCommaSeparatedList(IEnumerable<AstNode> list)
127    {
128      bool isFirst = true;
129      foreach (AstNode node in list) {
130        if (isFirst) {
131          isFirst = false;
132        } else {
133          Comma(node);
134        }
135        node.AcceptVisitor(this);
136      }
137    }
138   
139    void WriteCommaSeparatedListInParenthesis(IEnumerable<AstNode> list, bool spaceWithin)
140    {
141      LPar();
142      if (list.Any()) {
143        Space(spaceWithin);
144        WriteCommaSeparatedList(list);
145        Space(spaceWithin);
146      }
147      RPar();
148    }
149   
150    #if DOTNET35
151    void WriteCommaSeparatedList(IEnumerable<VariableInitializer> list)
152    {
153      WriteCommaSeparatedList(list.SafeCast<VariableInitializer, AstNode>());
154    }
155   
156    void WriteCommaSeparatedList(IEnumerable<AstType> list)
157    {
158      WriteCommaSeparatedList(list.SafeCast<AstType, AstNode>());
159    }
160   
161    void WriteCommaSeparatedListInParenthesis(IEnumerable<Expression> list, bool spaceWithin)
162    {
163      WriteCommaSeparatedListInParenthesis(list.SafeCast<Expression, AstNode>(), spaceWithin);
164    }
165   
166    void WriteCommaSeparatedListInParenthesis(IEnumerable<ParameterDeclaration> list, bool spaceWithin)
167    {
168      WriteCommaSeparatedListInParenthesis(list.SafeCast<ParameterDeclaration, AstNode>(), spaceWithin);
169    }
170
171    #endif
172
173    void WriteCommaSeparatedListInBrackets(IEnumerable<ParameterDeclaration> list, bool spaceWithin)
174    {
175      WriteToken(Roles.LBracket);
176      if (list.Any()) {
177        Space(spaceWithin);
178        WriteCommaSeparatedList(list);
179        Space(spaceWithin);
180      }
181      WriteToken(Roles.RBracket);
182    }
183
184    void WriteCommaSeparatedListInBrackets(IEnumerable<Expression> list)
185    {
186      WriteToken(Roles.LBracket);
187      if (list.Any()) {
188        Space(policy.SpacesWithinBrackets);
189        WriteCommaSeparatedList(list);
190        Space(policy.SpacesWithinBrackets);
191      }
192      WriteToken(Roles.RBracket);
193    }
194    #endregion
195   
196    #region Write tokens
197    bool isAtStartOfLine = true;
198   
199    /// <summary>
200    /// Writes a keyword, and all specials up to
201    /// </summary>
202    void WriteKeyword(TokenRole tokenRole)
203    {
204      WriteKeyword(tokenRole.Token, tokenRole);
205    }
206   
207    void WriteKeyword(string token, Role tokenRole = null)
208    {
209      writer.WriteKeyword(tokenRole, token);
210      isAtStartOfLine = false;
211    }
212   
213    void WriteIdentifier(Identifier identifier)
214    {
215      writer.WriteIdentifier(identifier);
216      isAtStartOfLine = false;
217    }
218   
219    void WriteIdentifier(string identifier)
220    {
221      AstType.Create(identifier).AcceptVisitor(this);
222      isAtStartOfLine = false;
223    }
224   
225    void WriteToken(TokenRole tokenRole)
226    {
227      WriteToken(tokenRole.Token, tokenRole);
228    }
229   
230    void WriteToken(string token, Role tokenRole)
231    {
232      writer.WriteToken(tokenRole, token);
233      isAtStartOfLine = false;
234    }
235   
236    void LPar()
237    {
238      WriteToken(Roles.LPar);
239    }
240   
241    void RPar()
242    {
243      WriteToken(Roles.RPar);
244    }
245   
246    /// <summary>
247    /// Marks the end of a statement
248    /// </summary>
249    void Semicolon()
250    {
251      Role role = containerStack.Peek().Role;
252      // get the role of the current node
253      if (!(role == ForStatement.InitializerRole || role == ForStatement.IteratorRole || role == UsingStatement.ResourceAcquisitionRole)) {
254        WriteToken(Roles.Semicolon);
255        NewLine();
256      }
257    }
258   
259    /// <summary>
260    /// Writes a space depending on policy.
261    /// </summary>
262    void Space(bool addSpace = true)
263    {
264      if (addSpace) {
265        writer.Space();
266      }
267    }
268   
269    void NewLine()
270    {
271      writer.NewLine();
272      isAtStartOfLine = true;
273    }
274   
275    void OpenBrace(BraceStyle style)
276    {
277      switch (style) {
278        case BraceStyle.DoNotChange:
279        case BraceStyle.EndOfLine:
280        case BraceStyle.BannerStyle:
281          if (!isAtStartOfLine)
282            writer.Space();
283          writer.WriteToken(Roles.LBrace, "{");
284          break;
285        case BraceStyle.EndOfLineWithoutSpace:
286          writer.WriteToken(Roles.LBrace, "{");
287          break;
288        case BraceStyle.NextLine:
289          if (!isAtStartOfLine)
290            NewLine();
291          writer.WriteToken(Roles.LBrace, "{");
292          break;
293        case BraceStyle.NextLineShifted:
294          NewLine();
295          writer.Indent();
296          writer.WriteToken(Roles.LBrace, "{");
297          NewLine();
298          return;
299        case BraceStyle.NextLineShifted2:
300          NewLine();
301          writer.Indent();
302          writer.WriteToken(Roles.LBrace, "{");
303          break;
304        default:
305          throw new ArgumentOutOfRangeException ();
306      }
307      writer.Indent();
308      NewLine();
309    }
310   
311    void CloseBrace(BraceStyle style)
312    {
313      switch (style) {
314        case BraceStyle.DoNotChange:
315        case BraceStyle.EndOfLine:
316        case BraceStyle.EndOfLineWithoutSpace:
317        case BraceStyle.NextLine:
318          writer.Unindent();
319          writer.WriteToken(Roles.RBrace, "}");
320          isAtStartOfLine = false;
321          break;
322        case BraceStyle.BannerStyle:
323        case BraceStyle.NextLineShifted:
324          writer.WriteToken(Roles.RBrace, "}");
325          isAtStartOfLine = false;
326          writer.Unindent();
327          break;
328        case BraceStyle.NextLineShifted2:
329          writer.Unindent();
330          writer.WriteToken(Roles.RBrace, "}");
331          isAtStartOfLine = false;
332          writer.Unindent();
333          break;
334        default:
335          throw new ArgumentOutOfRangeException();
336      }
337    }
338
339    #endregion
340   
341    #region IsKeyword Test
342    static readonly HashSet<string> unconditionalKeywords = new HashSet<string> {
343      "abstract", "as", "base", "bool", "break", "byte", "case", "catch",
344      "char", "checked", "class", "const", "continue", "decimal", "default", "delegate",
345      "do", "double", "else", "enum", "event", "explicit", "extern", "false",
346      "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit",
347      "in", "int", "interface", "internal", "is", "lock", "long", "namespace",
348      "new", "null", "object", "operator", "out", "override", "params", "private",
349      "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short",
350      "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw",
351      "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort",
352      "using", "virtual", "void", "volatile", "while"
353    };
354    static readonly HashSet<string> queryKeywords = new HashSet<string> {
355      "from", "where", "join", "on", "equals", "into", "let", "orderby",
356      "ascending", "descending", "select", "group", "by"
357    };
358   
359    /// <summary>
360    /// Determines whether the specified identifier is a keyword in the given context.
361    /// </summary>
362    public static bool IsKeyword(string identifier, AstNode context)
363    {
364      if (unconditionalKeywords.Contains(identifier)) {
365        return true;
366      }
367      foreach (AstNode ancestor in context.Ancestors) {
368        if (ancestor is QueryExpression && queryKeywords.Contains(identifier)) {
369          return true;
370        }
371        if (identifier == "await") {
372          // with lambdas/anonymous methods,
373          if (ancestor is LambdaExpression) {
374            return ((LambdaExpression)ancestor).IsAsync;
375          }
376          if (ancestor is AnonymousMethodExpression) {
377            return ((AnonymousMethodExpression)ancestor).IsAsync;
378          }
379          if (ancestor is EntityDeclaration) {
380            return (((EntityDeclaration)ancestor).Modifiers & Modifiers.Async) == Modifiers.Async;
381          }
382        }
383      }
384      return false;
385    }
386    #endregion
387   
388    #region Write constructs
389    void WriteTypeArguments(IEnumerable<AstType> typeArguments)
390    {
391      if (typeArguments.Any()) {
392        WriteToken(Roles.LChevron);
393        WriteCommaSeparatedList(typeArguments);
394        WriteToken(Roles.RChevron);
395      }
396    }
397   
398    public void WriteTypeParameters(IEnumerable<TypeParameterDeclaration> typeParameters)
399    {
400      if (typeParameters.Any()) {
401        WriteToken(Roles.LChevron);
402        WriteCommaSeparatedList(typeParameters);
403        WriteToken(Roles.RChevron);
404      }
405    }
406   
407    void WriteModifiers(IEnumerable<CSharpModifierToken> modifierTokens)
408    {
409      foreach (CSharpModifierToken modifier in modifierTokens) {
410        modifier.AcceptVisitor(this);
411      }
412    }
413   
414    void WriteQualifiedIdentifier(IEnumerable<Identifier> identifiers)
415    {
416      bool first = true;
417      foreach (Identifier ident in identifiers) {
418        if (first) {
419          first = false;
420        } else {
421          writer.WriteToken(Roles.Dot, ".");
422        }
423        writer.WriteIdentifier(ident);
424      }
425    }
426   
427    void WriteEmbeddedStatement(Statement embeddedStatement)
428    {
429      if (embeddedStatement.IsNull) {
430        NewLine();
431        return;
432      }
433      BlockStatement block = embeddedStatement as BlockStatement;
434      if (block != null) {
435        VisitBlockStatement(block);
436      } else {
437        NewLine();
438        writer.Indent();
439        embeddedStatement.AcceptVisitor(this);
440        writer.Unindent();
441      }
442    }
443   
444    void WriteMethodBody(BlockStatement body)
445    {
446      if (body.IsNull) {
447        Semicolon();
448      } else {
449        VisitBlockStatement(body);
450      }
451    }
452   
453    void WriteAttributes(IEnumerable<AttributeSection> attributes)
454    {
455      foreach (AttributeSection attr in attributes) {
456        attr.AcceptVisitor(this);
457      }
458    }
459   
460    void WritePrivateImplementationType(AstType privateImplementationType)
461    {
462      if (!privateImplementationType.IsNull) {
463        privateImplementationType.AcceptVisitor(this);
464        WriteToken(Roles.Dot);
465      }
466    }
467
468    #endregion
469   
470    #region Expressions
471    public void VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
472    {
473      StartNode(anonymousMethodExpression);
474      if (anonymousMethodExpression.IsAsync) {
475        WriteKeyword(AnonymousMethodExpression.AsyncModifierRole);
476        Space();
477      }
478      WriteKeyword(AnonymousMethodExpression.DelegateKeywordRole);
479      if (anonymousMethodExpression.HasParameterList) {
480        Space(policy.SpaceBeforeMethodDeclarationParentheses);
481        WriteCommaSeparatedListInParenthesis(anonymousMethodExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
482      }
483      anonymousMethodExpression.Body.AcceptVisitor(this);
484      EndNode(anonymousMethodExpression);
485    }
486   
487    public void VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression)
488    {
489      StartNode(undocumentedExpression);
490      switch (undocumentedExpression.UndocumentedExpressionType) {
491        case UndocumentedExpressionType.ArgList:
492        case UndocumentedExpressionType.ArgListAccess:
493          WriteKeyword(UndocumentedExpression.ArglistKeywordRole);
494          break;
495        case UndocumentedExpressionType.MakeRef:
496          WriteKeyword(UndocumentedExpression.MakerefKeywordRole);
497          break;
498        case UndocumentedExpressionType.RefType:
499          WriteKeyword(UndocumentedExpression.ReftypeKeywordRole);
500          break;
501        case UndocumentedExpressionType.RefValue:
502          WriteKeyword(UndocumentedExpression.RefvalueKeywordRole);
503          break;
504      }
505      if (undocumentedExpression.Arguments.Count > 0) {
506        Space(policy.SpaceBeforeMethodCallParentheses);
507        WriteCommaSeparatedListInParenthesis(undocumentedExpression.Arguments, policy.SpaceWithinMethodCallParentheses);
508      }
509      EndNode(undocumentedExpression);
510    }
511   
512    public void VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression)
513    {
514      StartNode(arrayCreateExpression);
515      WriteKeyword(ArrayCreateExpression.NewKeywordRole);
516      arrayCreateExpression.Type.AcceptVisitor(this);
517      if (arrayCreateExpression.Arguments.Count > 0) {
518        WriteCommaSeparatedListInBrackets(arrayCreateExpression.Arguments);
519      }
520      foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers) {
521        specifier.AcceptVisitor(this);
522      }
523      arrayCreateExpression.Initializer.AcceptVisitor(this);
524      EndNode(arrayCreateExpression);
525    }
526   
527    public void VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression)
528    {
529      StartNode(arrayInitializerExpression);
530      // "new List<int> { { 1 } }" and "new List<int> { 1 }" are the same semantically.
531      // We also use the same AST for both: we always use two nested ArrayInitializerExpressions
532      // for collection initializers, even if the user did not write nested brackets.
533      // The output visitor will output nested braces only if they are necessary,
534      // or if the braces tokens exist in the AST.
535      bool bracesAreOptional = arrayInitializerExpression.Elements.Count == 1
536        && IsObjectOrCollectionInitializer(arrayInitializerExpression.Parent)
537        && !CanBeConfusedWithObjectInitializer(arrayInitializerExpression.Elements.Single());
538      if (bracesAreOptional && arrayInitializerExpression.LBraceToken.IsNull) {
539        arrayInitializerExpression.Elements.Single().AcceptVisitor(this);
540      } else {
541        PrintInitializerElements(arrayInitializerExpression.Elements);
542      }
543      EndNode(arrayInitializerExpression);
544    }
545   
546    bool CanBeConfusedWithObjectInitializer(Expression expr)
547    {
548      // "int a; new List<int> { a = 1 };" is an object initalizers and invalid, but
549      // "int a; new List<int> { { a = 1 } };" is a valid collection initializer.
550      AssignmentExpression ae = expr as AssignmentExpression;
551      return ae != null && ae.Operator == AssignmentOperatorType.Assign;
552    }
553   
554    bool IsObjectOrCollectionInitializer(AstNode node)
555    {
556      if (!(node is ArrayInitializerExpression)) {
557        return false;
558      }
559      if (node.Parent is ObjectCreateExpression) {
560        return node.Role == ObjectCreateExpression.InitializerRole;
561      }
562      if (node.Parent is NamedExpression) {
563        return node.Role == Roles.Expression;
564      }
565      return false;
566    }
567   
568    void PrintInitializerElements(AstNodeCollection<Expression> elements)
569    {
570      BraceStyle style;
571      if (policy.ArrayInitializerWrapping == Wrapping.WrapAlways) {
572        style = BraceStyle.NextLine;
573      } else {
574        style = BraceStyle.EndOfLine;
575      }
576      OpenBrace(style);
577      bool isFirst = true;
578      AstNode last = null;
579      foreach (AstNode node in elements) {
580        if (isFirst) {
581          isFirst = false;
582        } else {
583          Comma(node, noSpaceAfterComma: true);
584          NewLine();
585        }
586        last = node;
587        node.AcceptVisitor(this);
588      }
589      if (last != null)
590        OptionalComma(last.NextSibling);
591      NewLine();
592      CloseBrace(style);
593    }
594   
595    public void VisitAsExpression(AsExpression asExpression)
596    {
597      StartNode(asExpression);
598      asExpression.Expression.AcceptVisitor(this);
599      Space();
600      WriteKeyword(AsExpression.AsKeywordRole);
601      Space();
602      asExpression.Type.AcceptVisitor(this);
603      EndNode(asExpression);
604    }
605   
606    public void VisitAssignmentExpression(AssignmentExpression assignmentExpression)
607    {
608      StartNode(assignmentExpression);
609      assignmentExpression.Left.AcceptVisitor(this);
610      Space(policy.SpaceAroundAssignment);
611      WriteToken(AssignmentExpression.GetOperatorRole(assignmentExpression.Operator));
612      Space(policy.SpaceAroundAssignment);
613      assignmentExpression.Right.AcceptVisitor(this);
614      EndNode(assignmentExpression);
615    }
616   
617    public void VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression)
618    {
619      StartNode(baseReferenceExpression);
620      WriteKeyword("base", baseReferenceExpression.Role);
621      EndNode(baseReferenceExpression);
622    }
623   
624    public void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
625    {
626      StartNode(binaryOperatorExpression);
627      binaryOperatorExpression.Left.AcceptVisitor(this);
628      bool spacePolicy;
629      switch (binaryOperatorExpression.Operator) {
630        case BinaryOperatorType.BitwiseAnd:
631        case BinaryOperatorType.BitwiseOr:
632        case BinaryOperatorType.ExclusiveOr:
633          spacePolicy = policy.SpaceAroundBitwiseOperator;
634          break;
635        case BinaryOperatorType.ConditionalAnd:
636        case BinaryOperatorType.ConditionalOr:
637          spacePolicy = policy.SpaceAroundLogicalOperator;
638          break;
639        case BinaryOperatorType.GreaterThan:
640        case BinaryOperatorType.GreaterThanOrEqual:
641        case BinaryOperatorType.LessThanOrEqual:
642        case BinaryOperatorType.LessThan:
643          spacePolicy = policy.SpaceAroundRelationalOperator;
644          break;
645        case BinaryOperatorType.Equality:
646        case BinaryOperatorType.InEquality:
647          spacePolicy = policy.SpaceAroundEqualityOperator;
648          break;
649        case BinaryOperatorType.Add:
650        case BinaryOperatorType.Subtract:
651          spacePolicy = policy.SpaceAroundAdditiveOperator;
652          break;
653        case BinaryOperatorType.Multiply:
654        case BinaryOperatorType.Divide:
655        case BinaryOperatorType.Modulus:
656          spacePolicy = policy.SpaceAroundMultiplicativeOperator;
657          break;
658        case BinaryOperatorType.ShiftLeft:
659        case BinaryOperatorType.ShiftRight:
660          spacePolicy = policy.SpaceAroundShiftOperator;
661          break;
662        case BinaryOperatorType.NullCoalescing:
663          spacePolicy = true;
664          break;
665        default:
666          throw new NotSupportedException ("Invalid value for BinaryOperatorType");
667      }
668      Space(spacePolicy);
669      WriteToken(BinaryOperatorExpression.GetOperatorRole(binaryOperatorExpression.Operator));
670      Space(spacePolicy);
671      binaryOperatorExpression.Right.AcceptVisitor(this);
672      EndNode(binaryOperatorExpression);
673    }
674   
675    public void VisitCastExpression(CastExpression castExpression)
676    {
677      StartNode(castExpression);
678      LPar();
679      Space(policy.SpacesWithinCastParentheses);
680      castExpression.Type.AcceptVisitor(this);
681      Space(policy.SpacesWithinCastParentheses);
682      RPar();
683      Space(policy.SpaceAfterTypecast);
684      castExpression.Expression.AcceptVisitor(this);
685      EndNode(castExpression);
686    }
687   
688    public void VisitCheckedExpression(CheckedExpression checkedExpression)
689    {
690      StartNode(checkedExpression);
691      WriteKeyword(CheckedExpression.CheckedKeywordRole);
692      LPar();
693      Space(policy.SpacesWithinCheckedExpressionParantheses);
694      checkedExpression.Expression.AcceptVisitor(this);
695      Space(policy.SpacesWithinCheckedExpressionParantheses);
696      RPar();
697      EndNode(checkedExpression);
698    }
699   
700    public void VisitConditionalExpression(ConditionalExpression conditionalExpression)
701    {
702      StartNode(conditionalExpression);
703      conditionalExpression.Condition.AcceptVisitor(this);
704     
705      Space(policy.SpaceBeforeConditionalOperatorCondition);
706      WriteToken(ConditionalExpression.QuestionMarkRole);
707      Space(policy.SpaceAfterConditionalOperatorCondition);
708     
709      conditionalExpression.TrueExpression.AcceptVisitor(this);
710     
711      Space(policy.SpaceBeforeConditionalOperatorSeparator);
712      WriteToken(ConditionalExpression.ColonRole);
713      Space(policy.SpaceAfterConditionalOperatorSeparator);
714     
715      conditionalExpression.FalseExpression.AcceptVisitor(this);
716     
717      EndNode(conditionalExpression);
718    }
719   
720    public void VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression)
721    {
722      StartNode(defaultValueExpression);
723     
724      WriteKeyword(DefaultValueExpression.DefaultKeywordRole);
725      LPar();
726      Space(policy.SpacesWithinTypeOfParentheses);
727      defaultValueExpression.Type.AcceptVisitor(this);
728      Space(policy.SpacesWithinTypeOfParentheses);
729      RPar();
730     
731      EndNode(defaultValueExpression);
732    }
733   
734    public void VisitDirectionExpression(DirectionExpression directionExpression)
735    {
736      StartNode(directionExpression);
737     
738      switch (directionExpression.FieldDirection) {
739        case FieldDirection.Out:
740          WriteKeyword(DirectionExpression.OutKeywordRole);
741          break;
742        case FieldDirection.Ref:
743          WriteKeyword(DirectionExpression.RefKeywordRole);
744          break;
745        default:
746          throw new NotSupportedException ("Invalid value for FieldDirection");
747      }
748      Space();
749      directionExpression.Expression.AcceptVisitor(this);
750     
751      EndNode(directionExpression);
752    }
753   
754    public void VisitIdentifierExpression(IdentifierExpression identifierExpression)
755    {
756      StartNode(identifierExpression);
757      WriteIdentifier(identifierExpression.IdentifierToken);
758      WriteTypeArguments(identifierExpression.TypeArguments);
759      EndNode(identifierExpression);
760    }
761   
762    public void VisitIndexerExpression(IndexerExpression indexerExpression)
763    {
764      StartNode(indexerExpression);
765      indexerExpression.Target.AcceptVisitor(this);
766      Space(policy.SpaceBeforeMethodCallParentheses);
767      WriteCommaSeparatedListInBrackets(indexerExpression.Arguments);
768      EndNode(indexerExpression);
769    }
770   
771    public void VisitInvocationExpression(InvocationExpression invocationExpression)
772    {
773      StartNode(invocationExpression);
774      invocationExpression.Target.AcceptVisitor(this);
775      Space(policy.SpaceBeforeMethodCallParentheses);
776      WriteCommaSeparatedListInParenthesis(invocationExpression.Arguments, policy.SpaceWithinMethodCallParentheses);
777      EndNode(invocationExpression);
778    }
779   
780    public void VisitIsExpression(IsExpression isExpression)
781    {
782      StartNode(isExpression);
783      isExpression.Expression.AcceptVisitor(this);
784      Space();
785      WriteKeyword(IsExpression.IsKeywordRole);
786      isExpression.Type.AcceptVisitor(this);
787      EndNode(isExpression);
788    }
789   
790    public void VisitLambdaExpression(LambdaExpression lambdaExpression)
791    {
792      StartNode(lambdaExpression);
793      if (lambdaExpression.IsAsync) {
794        WriteKeyword(LambdaExpression.AsyncModifierRole);
795        Space();
796      }
797      if (LambdaNeedsParenthesis(lambdaExpression)) {
798        WriteCommaSeparatedListInParenthesis(lambdaExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
799      } else {
800        lambdaExpression.Parameters.Single().AcceptVisitor(this);
801      }
802      Space();
803      WriteToken(LambdaExpression.ArrowRole);
804      Space();
805      lambdaExpression.Body.AcceptVisitor(this);
806      EndNode(lambdaExpression);
807    }
808   
809    bool LambdaNeedsParenthesis(LambdaExpression lambdaExpression)
810    {
811      if (lambdaExpression.Parameters.Count != 1) {
812        return true;
813      }
814      var p = lambdaExpression.Parameters.Single();
815      return !(p.Type.IsNull && p.ParameterModifier == ParameterModifier.None);
816    }
817   
818    public void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
819    {
820      StartNode(memberReferenceExpression);
821      memberReferenceExpression.Target.AcceptVisitor(this);
822      WriteToken(Roles.Dot);
823      WriteIdentifier(memberReferenceExpression.MemberNameToken);
824      WriteTypeArguments(memberReferenceExpression.TypeArguments);
825      EndNode(memberReferenceExpression);
826    }
827   
828    public void VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression)
829    {
830      StartNode(namedArgumentExpression);
831      WriteIdentifier(namedArgumentExpression.NameToken);
832      WriteToken(Roles.Colon);
833      Space();
834      namedArgumentExpression.Expression.AcceptVisitor(this);
835      EndNode(namedArgumentExpression);
836    }
837   
838    public void VisitNamedExpression(NamedExpression namedExpression)
839    {
840      StartNode(namedExpression);
841      WriteIdentifier(namedExpression.NameToken);
842      Space();
843      WriteToken(Roles.Assign);
844      Space();
845      namedExpression.Expression.AcceptVisitor(this);
846      EndNode(namedExpression);
847    }
848   
849    public void VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression)
850    {
851      StartNode(nullReferenceExpression);
852      writer.WritePrimitiveValue(null);
853      EndNode(nullReferenceExpression);
854    }
855   
856    public void VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression)
857    {
858      StartNode(objectCreateExpression);
859      WriteKeyword(ObjectCreateExpression.NewKeywordRole);
860      objectCreateExpression.Type.AcceptVisitor(this);
861      bool useParenthesis = objectCreateExpression.Arguments.Any() || objectCreateExpression.Initializer.IsNull;
862      // also use parenthesis if there is an '(' token
863      if (!objectCreateExpression.LParToken.IsNull) {
864        useParenthesis = true;
865      }
866      if (useParenthesis) {
867        Space(policy.SpaceBeforeMethodCallParentheses);
868        WriteCommaSeparatedListInParenthesis(objectCreateExpression.Arguments, policy.SpaceWithinMethodCallParentheses);
869      }
870      objectCreateExpression.Initializer.AcceptVisitor(this);
871      EndNode(objectCreateExpression);
872    }
873   
874    public void VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression)
875    {
876      StartNode(anonymousTypeCreateExpression);
877      WriteKeyword(AnonymousTypeCreateExpression.NewKeywordRole);
878      PrintInitializerElements(anonymousTypeCreateExpression.Initializers);
879      EndNode(anonymousTypeCreateExpression);
880    }
881
882    public void VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression)
883    {
884      StartNode(parenthesizedExpression);
885      LPar();
886      Space(policy.SpacesWithinParentheses);
887      parenthesizedExpression.Expression.AcceptVisitor(this);
888      Space(policy.SpacesWithinParentheses);
889      RPar();
890      EndNode(parenthesizedExpression);
891    }
892   
893    public void VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression)
894    {
895      StartNode(pointerReferenceExpression);
896      pointerReferenceExpression.Target.AcceptVisitor(this);
897      WriteToken(PointerReferenceExpression.ArrowRole);
898      WriteIdentifier(pointerReferenceExpression.MemberNameToken);
899      WriteTypeArguments(pointerReferenceExpression.TypeArguments);
900      EndNode(pointerReferenceExpression);
901    }
902   
903    #region VisitPrimitiveExpression
904    public void VisitPrimitiveExpression(PrimitiveExpression primitiveExpression)
905    {
906      StartNode(primitiveExpression);
907      writer.WritePrimitiveValue(primitiveExpression.Value, primitiveExpression.UnsafeLiteralValue);
908      EndNode(primitiveExpression);
909    }
910    #endregion
911   
912    public void VisitSizeOfExpression(SizeOfExpression sizeOfExpression)
913    {
914      StartNode(sizeOfExpression);
915     
916      WriteKeyword(SizeOfExpression.SizeofKeywordRole);
917      LPar();
918      Space(policy.SpacesWithinSizeOfParentheses);
919      sizeOfExpression.Type.AcceptVisitor(this);
920      Space(policy.SpacesWithinSizeOfParentheses);
921      RPar();
922     
923      EndNode(sizeOfExpression);
924    }
925   
926    public void VisitStackAllocExpression(StackAllocExpression stackAllocExpression)
927    {
928      StartNode(stackAllocExpression);
929      WriteKeyword(StackAllocExpression.StackallocKeywordRole);
930      stackAllocExpression.Type.AcceptVisitor(this);
931      WriteCommaSeparatedListInBrackets(new[] { stackAllocExpression.CountExpression });
932      EndNode(stackAllocExpression);
933    }
934   
935    public void VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression)
936    {
937      StartNode(thisReferenceExpression);
938      WriteKeyword("this", thisReferenceExpression.Role);
939      EndNode(thisReferenceExpression);
940    }
941   
942    public void VisitTypeOfExpression(TypeOfExpression typeOfExpression)
943    {
944      StartNode(typeOfExpression);
945     
946      WriteKeyword(TypeOfExpression.TypeofKeywordRole);
947      LPar();
948      Space(policy.SpacesWithinTypeOfParentheses);
949      typeOfExpression.Type.AcceptVisitor(this);
950      Space(policy.SpacesWithinTypeOfParentheses);
951      RPar();
952     
953      EndNode(typeOfExpression);
954    }
955   
956    public void VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression)
957    {
958      StartNode(typeReferenceExpression);
959      typeReferenceExpression.Type.AcceptVisitor(this);
960      EndNode(typeReferenceExpression);
961    }
962   
963    public void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
964    {
965      StartNode(unaryOperatorExpression);
966      UnaryOperatorType opType = unaryOperatorExpression.Operator;
967      var opSymbol = UnaryOperatorExpression.GetOperatorRole(opType);
968      if (opType == UnaryOperatorType.Await) {
969        WriteKeyword(opSymbol);
970      } else if (!(opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)) {
971        WriteToken(opSymbol);
972      }
973      unaryOperatorExpression.Expression.AcceptVisitor(this);
974      if (opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement) {
975        WriteToken(opSymbol);
976      }
977      EndNode(unaryOperatorExpression);
978    }
979   
980    public void VisitUncheckedExpression(UncheckedExpression uncheckedExpression)
981    {
982      StartNode(uncheckedExpression);
983      WriteKeyword(UncheckedExpression.UncheckedKeywordRole);
984      LPar();
985      Space(policy.SpacesWithinCheckedExpressionParantheses);
986      uncheckedExpression.Expression.AcceptVisitor(this);
987      Space(policy.SpacesWithinCheckedExpressionParantheses);
988      RPar();
989      EndNode(uncheckedExpression);
990    }
991
992    #endregion
993   
994    #region Query Expressions
995    public void VisitQueryExpression(QueryExpression queryExpression)
996    {
997      StartNode(queryExpression);
998      bool indent = queryExpression.Parent is QueryClause && !(queryExpression.Parent is QueryContinuationClause);
999      if (indent) {
1000        writer.Indent();
1001        NewLine();
1002      }
1003      bool first = true;
1004      foreach (var clause in queryExpression.Clauses) {
1005        if (first) {
1006          first = false;
1007        } else {
1008          if (!(clause is QueryContinuationClause)) {
1009            NewLine();
1010          }
1011        }
1012        clause.AcceptVisitor(this);
1013      }
1014      if (indent) {
1015        writer.Unindent();
1016      }
1017      EndNode(queryExpression);
1018    }
1019   
1020    public void VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause)
1021    {
1022      StartNode(queryContinuationClause);
1023      queryContinuationClause.PrecedingQuery.AcceptVisitor(this);
1024      Space();
1025      WriteKeyword(QueryContinuationClause.IntoKeywordRole);
1026      Space();
1027      WriteIdentifier(queryContinuationClause.IdentifierToken);
1028      EndNode(queryContinuationClause);
1029    }
1030   
1031    public void VisitQueryFromClause(QueryFromClause queryFromClause)
1032    {
1033      StartNode(queryFromClause);
1034      WriteKeyword(QueryFromClause.FromKeywordRole);
1035      queryFromClause.Type.AcceptVisitor(this);
1036      Space();
1037      WriteIdentifier(queryFromClause.IdentifierToken);
1038      Space();
1039      WriteKeyword(QueryFromClause.InKeywordRole);
1040      Space();
1041      queryFromClause.Expression.AcceptVisitor(this);
1042      EndNode(queryFromClause);
1043    }
1044   
1045    public void VisitQueryLetClause(QueryLetClause queryLetClause)
1046    {
1047      StartNode(queryLetClause);
1048      WriteKeyword(QueryLetClause.LetKeywordRole);
1049      Space();
1050      WriteIdentifier(queryLetClause.IdentifierToken);
1051      Space(policy.SpaceAroundAssignment);
1052      WriteToken(Roles.Assign);
1053      Space(policy.SpaceAroundAssignment);
1054      queryLetClause.Expression.AcceptVisitor(this);
1055      EndNode(queryLetClause);
1056    }
1057   
1058    public void VisitQueryWhereClause(QueryWhereClause queryWhereClause)
1059    {
1060      StartNode(queryWhereClause);
1061      WriteKeyword(QueryWhereClause.WhereKeywordRole);
1062      Space();
1063      queryWhereClause.Condition.AcceptVisitor(this);
1064      EndNode(queryWhereClause);
1065    }
1066   
1067    public void VisitQueryJoinClause(QueryJoinClause queryJoinClause)
1068    {
1069      StartNode(queryJoinClause);
1070      WriteKeyword(QueryJoinClause.JoinKeywordRole);
1071      queryJoinClause.Type.AcceptVisitor(this);
1072      Space();
1073      WriteIdentifier(queryJoinClause.JoinIdentifierToken);
1074      Space();
1075      WriteKeyword(QueryJoinClause.InKeywordRole);
1076      Space();
1077      queryJoinClause.InExpression.AcceptVisitor(this);
1078      Space();
1079      WriteKeyword(QueryJoinClause.OnKeywordRole);
1080      Space();
1081      queryJoinClause.OnExpression.AcceptVisitor(this);
1082      Space();
1083      WriteKeyword(QueryJoinClause.EqualsKeywordRole);
1084      Space();
1085      queryJoinClause.EqualsExpression.AcceptVisitor(this);
1086      if (queryJoinClause.IsGroupJoin) {
1087        Space();
1088        WriteKeyword(QueryJoinClause.IntoKeywordRole);
1089        WriteIdentifier(queryJoinClause.IntoIdentifierToken);
1090      }
1091      EndNode(queryJoinClause);
1092    }
1093   
1094    public void VisitQueryOrderClause(QueryOrderClause queryOrderClause)
1095    {
1096      StartNode(queryOrderClause);
1097      WriteKeyword(QueryOrderClause.OrderbyKeywordRole);
1098      Space();
1099      WriteCommaSeparatedList(queryOrderClause.Orderings);
1100      EndNode(queryOrderClause);
1101    }
1102   
1103    public void VisitQueryOrdering(QueryOrdering queryOrdering)
1104    {
1105      StartNode(queryOrdering);
1106      queryOrdering.Expression.AcceptVisitor(this);
1107      switch (queryOrdering.Direction) {
1108        case QueryOrderingDirection.Ascending:
1109          Space();
1110          WriteKeyword(QueryOrdering.AscendingKeywordRole);
1111          break;
1112        case QueryOrderingDirection.Descending:
1113          Space();
1114          WriteKeyword(QueryOrdering.DescendingKeywordRole);
1115          break;
1116      }
1117      EndNode(queryOrdering);
1118    }
1119   
1120    public void VisitQuerySelectClause(QuerySelectClause querySelectClause)
1121    {
1122      StartNode(querySelectClause);
1123      WriteKeyword(QuerySelectClause.SelectKeywordRole);
1124      Space();
1125      querySelectClause.Expression.AcceptVisitor(this);
1126      EndNode(querySelectClause);
1127    }
1128   
1129    public void VisitQueryGroupClause(QueryGroupClause queryGroupClause)
1130    {
1131      StartNode(queryGroupClause);
1132      WriteKeyword(QueryGroupClause.GroupKeywordRole);
1133      Space();
1134      queryGroupClause.Projection.AcceptVisitor(this);
1135      Space();
1136      WriteKeyword(QueryGroupClause.ByKeywordRole);
1137      Space();
1138      queryGroupClause.Key.AcceptVisitor(this);
1139      EndNode(queryGroupClause);
1140    }
1141
1142    #endregion
1143   
1144    #region GeneralScope
1145    public void VisitAttribute(Attribute attribute)
1146    {
1147      StartNode(attribute);
1148      attribute.Type.AcceptVisitor(this);
1149      if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole(Roles.LPar).IsNull) {
1150        Space(policy.SpaceBeforeMethodCallParentheses);
1151        WriteCommaSeparatedListInParenthesis(attribute.Arguments, policy.SpaceWithinMethodCallParentheses);
1152      }
1153      EndNode(attribute);
1154    }
1155   
1156    public void VisitAttributeSection(AttributeSection attributeSection)
1157    {
1158      StartNode(attributeSection);
1159      WriteToken(Roles.LBracket);
1160      if (!string.IsNullOrEmpty(attributeSection.AttributeTarget)) {
1161        WriteIdentifier(attributeSection.AttributeTargetToken);
1162        WriteToken(Roles.Colon);
1163        Space();
1164      }
1165      WriteCommaSeparatedList(attributeSection.Attributes);
1166      WriteToken(Roles.RBracket);
1167      if (attributeSection.Parent is ParameterDeclaration || attributeSection.Parent is TypeParameterDeclaration) {
1168        Space();
1169      } else {
1170        NewLine();
1171      }
1172      EndNode(attributeSection);
1173    }
1174   
1175    public void VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
1176    {
1177      StartNode(delegateDeclaration);
1178      WriteAttributes(delegateDeclaration.Attributes);
1179      WriteModifiers(delegateDeclaration.ModifierTokens);
1180      WriteKeyword(Roles.DelegateKeyword);
1181      delegateDeclaration.ReturnType.AcceptVisitor(this);
1182      Space();
1183      WriteIdentifier(delegateDeclaration.NameToken);
1184      WriteTypeParameters(delegateDeclaration.TypeParameters);
1185      Space(policy.SpaceBeforeDelegateDeclarationParentheses);
1186      WriteCommaSeparatedListInParenthesis(delegateDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
1187      foreach (Constraint constraint in delegateDeclaration.Constraints) {
1188        constraint.AcceptVisitor(this);
1189      }
1190      Semicolon();
1191      EndNode(delegateDeclaration);
1192    }
1193   
1194    public void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
1195    {
1196      StartNode(namespaceDeclaration);
1197      WriteKeyword(Roles.NamespaceKeyword);
1198      namespaceDeclaration.NamespaceName.AcceptVisitor (this);
1199      OpenBrace(policy.NamespaceBraceStyle);
1200      foreach (var member in namespaceDeclaration.Members) {
1201        member.AcceptVisitor(this);
1202        MaybeNewLinesAfterUsings(member);
1203      }
1204      CloseBrace(policy.NamespaceBraceStyle);
1205      OptionalSemicolon(namespaceDeclaration.LastChild);
1206      NewLine();
1207      EndNode(namespaceDeclaration);
1208    }
1209   
1210    public void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
1211    {
1212      StartNode(typeDeclaration);
1213      WriteAttributes(typeDeclaration.Attributes);
1214      WriteModifiers(typeDeclaration.ModifierTokens);
1215      BraceStyle braceStyle;
1216      switch (typeDeclaration.ClassType) {
1217        case ClassType.Enum:
1218          WriteKeyword(Roles.EnumKeyword);
1219          braceStyle = policy.EnumBraceStyle;
1220          break;
1221        case ClassType.Interface:
1222          WriteKeyword(Roles.InterfaceKeyword);
1223          braceStyle = policy.InterfaceBraceStyle;
1224          break;
1225        case ClassType.Struct:
1226          WriteKeyword(Roles.StructKeyword);
1227          braceStyle = policy.StructBraceStyle;
1228          break;
1229        default:
1230          WriteKeyword(Roles.ClassKeyword);
1231          braceStyle = policy.ClassBraceStyle;
1232          break;
1233      }
1234      WriteIdentifier(typeDeclaration.NameToken);
1235      WriteTypeParameters(typeDeclaration.TypeParameters);
1236      if (typeDeclaration.BaseTypes.Any()) {
1237        Space();
1238        WriteToken(Roles.Colon);
1239        Space();
1240        WriteCommaSeparatedList(typeDeclaration.BaseTypes);
1241      }
1242      foreach (Constraint constraint in typeDeclaration.Constraints) {
1243        constraint.AcceptVisitor(this);
1244      }
1245      OpenBrace(braceStyle);
1246      if (typeDeclaration.ClassType == ClassType.Enum) {
1247        bool first = true;
1248        AstNode last = null;
1249        foreach (var member in typeDeclaration.Members) {
1250          if (first) {
1251            first = false;
1252          } else {
1253            Comma(member, noSpaceAfterComma: true);
1254            NewLine();
1255          }
1256          last = member;
1257          member.AcceptVisitor(this);
1258        }
1259        if (last != null)
1260          OptionalComma(last.NextSibling);
1261        NewLine();
1262      } else {
1263        bool first = true;
1264        foreach (var member in typeDeclaration.Members) {
1265          if (!first) {
1266            for (int i = 0; i < policy.MinimumBlankLinesBetweenMembers; i++)
1267              NewLine();
1268          }
1269          first = false;
1270          member.AcceptVisitor(this);
1271        }
1272      }
1273      CloseBrace(braceStyle);
1274      OptionalSemicolon(typeDeclaration.LastChild);
1275      NewLine();
1276      EndNode(typeDeclaration);
1277    }
1278   
1279    public void VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration)
1280    {
1281      StartNode(usingAliasDeclaration);
1282      WriteKeyword(UsingAliasDeclaration.UsingKeywordRole);
1283      WriteIdentifier(usingAliasDeclaration.GetChildByRole(UsingAliasDeclaration.AliasRole));
1284      Space(policy.SpaceAroundEqualityOperator);
1285      WriteToken(Roles.Assign);
1286      Space(policy.SpaceAroundEqualityOperator);
1287      usingAliasDeclaration.Import.AcceptVisitor(this);
1288      Semicolon();
1289      EndNode(usingAliasDeclaration);
1290    }
1291   
1292    public void VisitUsingDeclaration(UsingDeclaration usingDeclaration)
1293    {
1294      StartNode(usingDeclaration);
1295      WriteKeyword(UsingDeclaration.UsingKeywordRole);
1296      usingDeclaration.Import.AcceptVisitor(this);
1297      Semicolon();
1298      EndNode(usingDeclaration);
1299    }
1300   
1301    public void VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration)
1302    {
1303      StartNode(externAliasDeclaration);
1304      WriteKeyword(Roles.ExternKeyword);
1305      Space();
1306      WriteKeyword(Roles.AliasKeyword);
1307      Space();
1308      WriteIdentifier(externAliasDeclaration.NameToken);
1309      Semicolon();
1310      EndNode(externAliasDeclaration);
1311    }
1312
1313    #endregion
1314   
1315    #region Statements
1316    public void VisitBlockStatement(BlockStatement blockStatement)
1317    {
1318      StartNode(blockStatement);
1319      BraceStyle style;
1320      if (blockStatement.Parent is AnonymousMethodExpression || blockStatement.Parent is LambdaExpression) {
1321        style = policy.AnonymousMethodBraceStyle;
1322      } else if (blockStatement.Parent is ConstructorDeclaration) {
1323        style = policy.ConstructorBraceStyle;
1324      } else if (blockStatement.Parent is DestructorDeclaration) {
1325        style = policy.DestructorBraceStyle;
1326      } else if (blockStatement.Parent is MethodDeclaration) {
1327        style = policy.MethodBraceStyle;
1328      } else if (blockStatement.Parent is Accessor) {
1329        if (blockStatement.Parent.Role == PropertyDeclaration.GetterRole) {
1330          style = policy.PropertyGetBraceStyle;
1331        } else if (blockStatement.Parent.Role == PropertyDeclaration.SetterRole) {
1332          style = policy.PropertySetBraceStyle;
1333        } else if (blockStatement.Parent.Role == CustomEventDeclaration.AddAccessorRole) {
1334          style = policy.EventAddBraceStyle;
1335        } else if (blockStatement.Parent.Role == CustomEventDeclaration.RemoveAccessorRole) {
1336          style = policy.EventRemoveBraceStyle;
1337        } else {
1338          style = policy.StatementBraceStyle;
1339        }
1340      } else {
1341        style = policy.StatementBraceStyle;
1342      }
1343      OpenBrace(style);
1344      foreach (var node in blockStatement.Statements) {
1345        node.AcceptVisitor(this);
1346      }
1347      EndNode(blockStatement);
1348      CloseBrace(style);
1349      if (!(blockStatement.Parent is Expression))
1350        NewLine();
1351    }
1352   
1353    public void VisitBreakStatement(BreakStatement breakStatement)
1354    {
1355      StartNode(breakStatement);
1356      WriteKeyword("break", BreakStatement.BreakKeywordRole);
1357      Semicolon();
1358      EndNode(breakStatement);
1359    }
1360   
1361    public void VisitCheckedStatement(CheckedStatement checkedStatement)
1362    {
1363      StartNode(checkedStatement);
1364      WriteKeyword(CheckedStatement.CheckedKeywordRole);
1365      checkedStatement.Body.AcceptVisitor(this);
1366      EndNode(checkedStatement);
1367    }
1368   
1369    public void VisitContinueStatement(ContinueStatement continueStatement)
1370    {
1371      StartNode(continueStatement);
1372      WriteKeyword("continue", ContinueStatement.ContinueKeywordRole);
1373      Semicolon();
1374      EndNode(continueStatement);
1375    }
1376   
1377    public void VisitDoWhileStatement(DoWhileStatement doWhileStatement)
1378    {
1379      StartNode(doWhileStatement);
1380      WriteKeyword(DoWhileStatement.DoKeywordRole);
1381      WriteEmbeddedStatement(doWhileStatement.EmbeddedStatement);
1382      WriteKeyword(DoWhileStatement.WhileKeywordRole);
1383      Space(policy.SpaceBeforeWhileParentheses);
1384      LPar();
1385      Space(policy.SpacesWithinWhileParentheses);
1386      doWhileStatement.Condition.AcceptVisitor(this);
1387      Space(policy.SpacesWithinWhileParentheses);
1388      RPar();
1389      Semicolon();
1390      EndNode(doWhileStatement);
1391    }
1392   
1393    public void VisitEmptyStatement(EmptyStatement emptyStatement)
1394    {
1395      StartNode(emptyStatement);
1396      Semicolon();
1397      EndNode(emptyStatement);
1398    }
1399   
1400    public void VisitExpressionStatement(ExpressionStatement expressionStatement)
1401    {
1402      StartNode(expressionStatement);
1403      expressionStatement.Expression.AcceptVisitor(this);
1404      Semicolon();
1405      EndNode(expressionStatement);
1406    }
1407   
1408    public void VisitFixedStatement(FixedStatement fixedStatement)
1409    {
1410      StartNode(fixedStatement);
1411      WriteKeyword(FixedStatement.FixedKeywordRole);
1412      Space(policy.SpaceBeforeUsingParentheses);
1413      LPar();
1414      Space(policy.SpacesWithinUsingParentheses);
1415      fixedStatement.Type.AcceptVisitor(this);
1416      Space();
1417      WriteCommaSeparatedList(fixedStatement.Variables);
1418      Space(policy.SpacesWithinUsingParentheses);
1419      RPar();
1420      WriteEmbeddedStatement(fixedStatement.EmbeddedStatement);
1421      EndNode(fixedStatement);
1422    }
1423   
1424    public void VisitForeachStatement(ForeachStatement foreachStatement)
1425    {
1426      StartNode(foreachStatement);
1427      WriteKeyword(ForeachStatement.ForeachKeywordRole);
1428      Space(policy.SpaceBeforeForeachParentheses);
1429      LPar();
1430      Space(policy.SpacesWithinForeachParentheses);
1431      foreachStatement.VariableType.AcceptVisitor(this);
1432      Space();
1433      WriteIdentifier(foreachStatement.VariableNameToken);
1434      WriteKeyword(ForeachStatement.InKeywordRole);
1435      Space();
1436      foreachStatement.InExpression.AcceptVisitor(this);
1437      Space(policy.SpacesWithinForeachParentheses);
1438      RPar();
1439      WriteEmbeddedStatement(foreachStatement.EmbeddedStatement);
1440      EndNode(foreachStatement);
1441    }
1442   
1443    public void VisitForStatement(ForStatement forStatement)
1444    {
1445      StartNode(forStatement);
1446      WriteKeyword(ForStatement.ForKeywordRole);
1447      Space(policy.SpaceBeforeForParentheses);
1448      LPar();
1449      Space(policy.SpacesWithinForParentheses);
1450     
1451      WriteCommaSeparatedList(forStatement.Initializers);
1452      Space(policy.SpaceBeforeForSemicolon);
1453      WriteToken(Roles.Semicolon);
1454      Space(policy.SpaceAfterForSemicolon);
1455     
1456      forStatement.Condition.AcceptVisitor(this);
1457      Space(policy.SpaceBeforeForSemicolon);
1458      WriteToken(Roles.Semicolon);
1459      if (forStatement.Iterators.Any()) {
1460        Space(policy.SpaceAfterForSemicolon);
1461        WriteCommaSeparatedList(forStatement.Iterators);
1462      }
1463     
1464      Space(policy.SpacesWithinForParentheses);
1465      RPar();
1466      WriteEmbeddedStatement(forStatement.EmbeddedStatement);
1467      EndNode(forStatement);
1468    }
1469   
1470    public void VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement)
1471    {
1472      StartNode(gotoCaseStatement);
1473      WriteKeyword(GotoCaseStatement.GotoKeywordRole);
1474      WriteKeyword(GotoCaseStatement.CaseKeywordRole);
1475      Space();
1476      gotoCaseStatement.LabelExpression.AcceptVisitor(this);
1477      Semicolon();
1478      EndNode(gotoCaseStatement);
1479    }
1480   
1481    public void VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement)
1482    {
1483      StartNode(gotoDefaultStatement);
1484      WriteKeyword(GotoDefaultStatement.GotoKeywordRole);
1485      WriteKeyword(GotoDefaultStatement.DefaultKeywordRole);
1486      Semicolon();
1487      EndNode(gotoDefaultStatement);
1488    }
1489   
1490    public void VisitGotoStatement(GotoStatement gotoStatement)
1491    {
1492      StartNode(gotoStatement);
1493      WriteKeyword(GotoStatement.GotoKeywordRole);
1494      WriteIdentifier(gotoStatement.GetChildByRole(Roles.Identifier));
1495      Semicolon();
1496      EndNode(gotoStatement);
1497    }
1498   
1499    public void VisitIfElseStatement(IfElseStatement ifElseStatement)
1500    {
1501      StartNode(ifElseStatement);
1502      WriteKeyword(IfElseStatement.IfKeywordRole);
1503      Space(policy.SpaceBeforeIfParentheses);
1504      LPar();
1505      Space(policy.SpacesWithinIfParentheses);
1506      ifElseStatement.Condition.AcceptVisitor(this);
1507      Space(policy.SpacesWithinIfParentheses);
1508      RPar();
1509      WriteEmbeddedStatement(ifElseStatement.TrueStatement);
1510      if (!ifElseStatement.FalseStatement.IsNull) {
1511        WriteKeyword(IfElseStatement.ElseKeywordRole);
1512        WriteEmbeddedStatement(ifElseStatement.FalseStatement);
1513      }
1514      EndNode(ifElseStatement);
1515    }
1516   
1517    public void VisitLabelStatement(LabelStatement labelStatement)
1518    {
1519      StartNode(labelStatement);
1520      WriteIdentifier(labelStatement.GetChildByRole(Roles.Identifier));
1521      WriteToken(Roles.Colon);
1522      bool foundLabelledStatement = false;
1523      for (AstNode tmp = labelStatement.NextSibling; tmp != null; tmp = tmp.NextSibling) {
1524        if (tmp.Role == labelStatement.Role) {
1525          foundLabelledStatement = true;
1526        }
1527      }
1528      if (!foundLabelledStatement) {
1529        // introduce an EmptyStatement so that the output becomes syntactically valid
1530        WriteToken(Roles.Semicolon);
1531      }
1532      NewLine();
1533      EndNode(labelStatement);
1534    }
1535   
1536    public void VisitLockStatement(LockStatement lockStatement)
1537    {
1538      StartNode(lockStatement);
1539      WriteKeyword(LockStatement.LockKeywordRole);
1540      Space(policy.SpaceBeforeLockParentheses);
1541      LPar();
1542      Space(policy.SpacesWithinLockParentheses);
1543      lockStatement.Expression.AcceptVisitor(this);
1544      Space(policy.SpacesWithinLockParentheses);
1545      RPar();
1546      WriteEmbeddedStatement(lockStatement.EmbeddedStatement);
1547      EndNode(lockStatement);
1548    }
1549   
1550    public void VisitReturnStatement(ReturnStatement returnStatement)
1551    {
1552      StartNode(returnStatement);
1553      WriteKeyword(ReturnStatement.ReturnKeywordRole);
1554      if (!returnStatement.Expression.IsNull) {
1555        Space();
1556        returnStatement.Expression.AcceptVisitor(this);
1557      }
1558      Semicolon();
1559      EndNode(returnStatement);
1560    }
1561   
1562    public void VisitSwitchStatement(SwitchStatement switchStatement)
1563    {
1564      StartNode(switchStatement);
1565      WriteKeyword(SwitchStatement.SwitchKeywordRole);
1566      Space(policy.SpaceBeforeSwitchParentheses);
1567      LPar();
1568      Space(policy.SpacesWithinSwitchParentheses);
1569      switchStatement.Expression.AcceptVisitor(this);
1570      Space(policy.SpacesWithinSwitchParentheses);
1571      RPar();
1572      OpenBrace(policy.StatementBraceStyle);
1573      if (!policy.IndentSwitchBody) {
1574        writer.Unindent();
1575      }
1576     
1577      foreach (var section in switchStatement.SwitchSections) {
1578        section.AcceptVisitor(this);
1579      }
1580     
1581      if (!policy.IndentSwitchBody) {
1582        writer.Indent();
1583      }
1584      CloseBrace(policy.StatementBraceStyle);
1585      NewLine();
1586      EndNode(switchStatement);
1587    }
1588   
1589    public void VisitSwitchSection(SwitchSection switchSection)
1590    {
1591      StartNode(switchSection);
1592      bool first = true;
1593      foreach (var label in switchSection.CaseLabels) {
1594        if (!first) {
1595          NewLine();
1596        }
1597        label.AcceptVisitor(this);
1598        first = false;
1599      }
1600      bool isBlock = switchSection.Statements.Count == 1 && switchSection.Statements.Single() is BlockStatement;
1601      if (policy.IndentCaseBody && !isBlock) {
1602        writer.Indent();
1603      }
1604     
1605      if (!isBlock)
1606        NewLine();
1607     
1608      foreach (var statement in switchSection.Statements) {
1609        statement.AcceptVisitor(this);
1610      }
1611     
1612      if (policy.IndentCaseBody && !isBlock) {
1613        writer.Unindent();
1614      }
1615     
1616      EndNode(switchSection);
1617    }
1618   
1619    public void VisitCaseLabel(CaseLabel caseLabel)
1620    {
1621      StartNode(caseLabel);
1622      if (caseLabel.Expression.IsNull) {
1623        WriteKeyword(CaseLabel.DefaultKeywordRole);
1624      } else {
1625        WriteKeyword(CaseLabel.CaseKeywordRole);
1626        Space();
1627        caseLabel.Expression.AcceptVisitor(this);
1628      }
1629      WriteToken(Roles.Colon);
1630      EndNode(caseLabel);
1631    }
1632   
1633    public void VisitThrowStatement(ThrowStatement throwStatement)
1634    {
1635      StartNode(throwStatement);
1636      WriteKeyword(ThrowStatement.ThrowKeywordRole);
1637      if (!throwStatement.Expression.IsNull) {
1638        Space();
1639        throwStatement.Expression.AcceptVisitor(this);
1640      }
1641      Semicolon();
1642      EndNode(throwStatement);
1643    }
1644   
1645    public void VisitTryCatchStatement(TryCatchStatement tryCatchStatement)
1646    {
1647      StartNode(tryCatchStatement);
1648      WriteKeyword(TryCatchStatement.TryKeywordRole);
1649      tryCatchStatement.TryBlock.AcceptVisitor(this);
1650      foreach (var catchClause in tryCatchStatement.CatchClauses) {
1651        catchClause.AcceptVisitor(this);
1652      }
1653      if (!tryCatchStatement.FinallyBlock.IsNull) {
1654        WriteKeyword(TryCatchStatement.FinallyKeywordRole);
1655        tryCatchStatement.FinallyBlock.AcceptVisitor(this);
1656      }
1657      EndNode(tryCatchStatement);
1658    }
1659   
1660    public void VisitCatchClause(CatchClause catchClause)
1661    {
1662      StartNode(catchClause);
1663      WriteKeyword(CatchClause.CatchKeywordRole);
1664      if (!catchClause.Type.IsNull) {
1665        Space(policy.SpaceBeforeCatchParentheses);
1666        LPar();
1667        Space(policy.SpacesWithinCatchParentheses);
1668        catchClause.Type.AcceptVisitor(this);
1669        if (!string.IsNullOrEmpty(catchClause.VariableName)) {
1670          Space();
1671          WriteIdentifier(catchClause.VariableNameToken);
1672        }
1673        Space(policy.SpacesWithinCatchParentheses);
1674        RPar();
1675      }
1676      catchClause.Body.AcceptVisitor(this);
1677      EndNode(catchClause);
1678    }
1679   
1680    public void VisitUncheckedStatement(UncheckedStatement uncheckedStatement)
1681    {
1682      StartNode(uncheckedStatement);
1683      WriteKeyword(UncheckedStatement.UncheckedKeywordRole);
1684      uncheckedStatement.Body.AcceptVisitor(this);
1685      EndNode(uncheckedStatement);
1686    }
1687   
1688    public void VisitUnsafeStatement(UnsafeStatement unsafeStatement)
1689    {
1690      StartNode(unsafeStatement);
1691      WriteKeyword(UnsafeStatement.UnsafeKeywordRole);
1692      unsafeStatement.Body.AcceptVisitor(this);
1693      EndNode(unsafeStatement);
1694    }
1695   
1696    public void VisitUsingStatement(UsingStatement usingStatement)
1697    {
1698      StartNode(usingStatement);
1699      WriteKeyword(UsingStatement.UsingKeywordRole);
1700      Space(policy.SpaceBeforeUsingParentheses);
1701      LPar();
1702      Space(policy.SpacesWithinUsingParentheses);
1703     
1704      usingStatement.ResourceAcquisition.AcceptVisitor(this);
1705     
1706      Space(policy.SpacesWithinUsingParentheses);
1707      RPar();
1708     
1709      WriteEmbeddedStatement(usingStatement.EmbeddedStatement);
1710     
1711      EndNode(usingStatement);
1712    }
1713   
1714    public void VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement)
1715    {
1716      StartNode(variableDeclarationStatement);
1717      WriteModifiers(variableDeclarationStatement.GetChildrenByRole(VariableDeclarationStatement.ModifierRole));
1718      variableDeclarationStatement.Type.AcceptVisitor(this);
1719      Space();
1720      WriteCommaSeparatedList(variableDeclarationStatement.Variables);
1721      Semicolon();
1722      EndNode(variableDeclarationStatement);
1723    }
1724   
1725    public void VisitWhileStatement(WhileStatement whileStatement)
1726    {
1727      StartNode(whileStatement);
1728      WriteKeyword(WhileStatement.WhileKeywordRole);
1729      Space(policy.SpaceBeforeWhileParentheses);
1730      LPar();
1731      Space(policy.SpacesWithinWhileParentheses);
1732      whileStatement.Condition.AcceptVisitor(this);
1733      Space(policy.SpacesWithinWhileParentheses);
1734      RPar();
1735      WriteEmbeddedStatement(whileStatement.EmbeddedStatement);
1736      EndNode(whileStatement);
1737    }
1738   
1739    public void VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement)
1740    {
1741      StartNode(yieldBreakStatement);
1742      WriteKeyword(YieldBreakStatement.YieldKeywordRole);
1743      WriteKeyword(YieldBreakStatement.BreakKeywordRole);
1744      Semicolon();
1745      EndNode(yieldBreakStatement);
1746    }
1747   
1748    public void VisitYieldReturnStatement(YieldReturnStatement yieldReturnStatement)
1749    {
1750      StartNode(yieldReturnStatement);
1751      WriteKeyword(YieldReturnStatement.YieldKeywordRole);
1752      WriteKeyword(YieldReturnStatement.ReturnKeywordRole);
1753      Space();
1754      yieldReturnStatement.Expression.AcceptVisitor(this);
1755      Semicolon();
1756      EndNode(yieldReturnStatement);
1757    }
1758
1759    #endregion
1760   
1761    #region TypeMembers
1762    public void VisitAccessor(Accessor accessor)
1763    {
1764      StartNode(accessor);
1765      WriteAttributes(accessor.Attributes);
1766      WriteModifiers(accessor.ModifierTokens);
1767      if (accessor.Role == PropertyDeclaration.GetterRole) {
1768        WriteKeyword("get", PropertyDeclaration.GetKeywordRole);
1769      } else if (accessor.Role == PropertyDeclaration.SetterRole) {
1770        WriteKeyword("set", PropertyDeclaration.SetKeywordRole);
1771      } else if (accessor.Role == CustomEventDeclaration.AddAccessorRole) {
1772        WriteKeyword("add", CustomEventDeclaration.AddKeywordRole);
1773      } else if (accessor.Role == CustomEventDeclaration.RemoveAccessorRole) {
1774        WriteKeyword("remove", CustomEventDeclaration.RemoveKeywordRole);
1775      }
1776      WriteMethodBody(accessor.Body);
1777      EndNode(accessor);
1778    }
1779   
1780    public void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
1781    {
1782      StartNode(constructorDeclaration);
1783      WriteAttributes(constructorDeclaration.Attributes);
1784      WriteModifiers(constructorDeclaration.ModifierTokens);
1785      TypeDeclaration type = constructorDeclaration.Parent as TypeDeclaration;
1786      if (type != null && type.Name != constructorDeclaration.Name)
1787        WriteIdentifier((Identifier)type.NameToken.Clone());
1788      else
1789        WriteIdentifier(constructorDeclaration.NameToken);
1790      Space(policy.SpaceBeforeConstructorDeclarationParentheses);
1791      WriteCommaSeparatedListInParenthesis(constructorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
1792      if (!constructorDeclaration.Initializer.IsNull) {
1793        Space();
1794        constructorDeclaration.Initializer.AcceptVisitor(this);
1795      }
1796      WriteMethodBody(constructorDeclaration.Body);
1797      EndNode(constructorDeclaration);
1798    }
1799   
1800    public void VisitConstructorInitializer(ConstructorInitializer constructorInitializer)
1801    {
1802      StartNode(constructorInitializer);
1803      WriteToken(Roles.Colon);
1804      Space();
1805      if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.This) {
1806        WriteKeyword(ConstructorInitializer.ThisKeywordRole);
1807      } else {
1808        WriteKeyword(ConstructorInitializer.BaseKeywordRole);
1809      }
1810      Space(policy.SpaceBeforeMethodCallParentheses);
1811      WriteCommaSeparatedListInParenthesis(constructorInitializer.Arguments, policy.SpaceWithinMethodCallParentheses);
1812      EndNode(constructorInitializer);
1813    }
1814   
1815    public void VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration)
1816    {
1817      StartNode(destructorDeclaration);
1818      WriteAttributes(destructorDeclaration.Attributes);
1819      WriteModifiers(destructorDeclaration.ModifierTokens);
1820      WriteToken(DestructorDeclaration.TildeRole);
1821      TypeDeclaration type = destructorDeclaration.Parent as TypeDeclaration;
1822      if (type != null && type.Name != destructorDeclaration.Name)
1823        WriteIdentifier((Identifier)type.NameToken.Clone());
1824      else
1825        WriteIdentifier(destructorDeclaration.NameToken);
1826      Space(policy.SpaceBeforeConstructorDeclarationParentheses);
1827      LPar();
1828      RPar();
1829      WriteMethodBody(destructorDeclaration.Body);
1830      EndNode(destructorDeclaration);
1831    }
1832   
1833    public void VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration)
1834    {
1835      StartNode(enumMemberDeclaration);
1836      WriteAttributes(enumMemberDeclaration.Attributes);
1837      WriteModifiers(enumMemberDeclaration.ModifierTokens);
1838      WriteIdentifier(enumMemberDeclaration.NameToken);
1839      if (!enumMemberDeclaration.Initializer.IsNull) {
1840        Space(policy.SpaceAroundAssignment);
1841        WriteToken(Roles.Assign);
1842        Space(policy.SpaceAroundAssignment);
1843        enumMemberDeclaration.Initializer.AcceptVisitor(this);
1844      }
1845      EndNode(enumMemberDeclaration);
1846    }
1847   
1848    public void VisitEventDeclaration(EventDeclaration eventDeclaration)
1849    {
1850      StartNode(eventDeclaration);
1851      WriteAttributes(eventDeclaration.Attributes);
1852      WriteModifiers(eventDeclaration.ModifierTokens);
1853      WriteKeyword(EventDeclaration.EventKeywordRole);
1854      eventDeclaration.ReturnType.AcceptVisitor(this);
1855      Space();
1856      WriteCommaSeparatedList(eventDeclaration.Variables);
1857      Semicolon();
1858      EndNode(eventDeclaration);
1859    }
1860   
1861    public void VisitCustomEventDeclaration(CustomEventDeclaration customEventDeclaration)
1862    {
1863      StartNode(customEventDeclaration);
1864      WriteAttributes(customEventDeclaration.Attributes);
1865      WriteModifiers(customEventDeclaration.ModifierTokens);
1866      WriteKeyword(CustomEventDeclaration.EventKeywordRole);
1867      customEventDeclaration.ReturnType.AcceptVisitor(this);
1868      Space();
1869      WritePrivateImplementationType(customEventDeclaration.PrivateImplementationType);
1870      WriteIdentifier(customEventDeclaration.NameToken);
1871      OpenBrace(policy.EventBraceStyle);
1872      // output add/remove in their original order
1873      foreach (AstNode node in customEventDeclaration.Children) {
1874        if (node.Role == CustomEventDeclaration.AddAccessorRole || node.Role == CustomEventDeclaration.RemoveAccessorRole) {
1875          node.AcceptVisitor(this);
1876        }
1877      }
1878      CloseBrace(policy.EventBraceStyle);
1879      NewLine();
1880      EndNode(customEventDeclaration);
1881    }
1882   
1883    public void VisitFieldDeclaration(FieldDeclaration fieldDeclaration)
1884    {
1885      StartNode(fieldDeclaration);
1886      WriteAttributes(fieldDeclaration.Attributes);
1887      WriteModifiers(fieldDeclaration.ModifierTokens);
1888      fieldDeclaration.ReturnType.AcceptVisitor(this);
1889      Space();
1890      WriteCommaSeparatedList(fieldDeclaration.Variables);
1891      Semicolon();
1892      EndNode(fieldDeclaration);
1893    }
1894   
1895    public void VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration)
1896    {
1897      StartNode(fixedFieldDeclaration);
1898      WriteAttributes(fixedFieldDeclaration.Attributes);
1899      WriteModifiers(fixedFieldDeclaration.ModifierTokens);
1900      WriteKeyword(FixedFieldDeclaration.FixedKeywordRole);
1901      Space();
1902      fixedFieldDeclaration.ReturnType.AcceptVisitor(this);
1903      Space();
1904      WriteCommaSeparatedList(fixedFieldDeclaration.Variables);
1905      Semicolon();
1906      EndNode(fixedFieldDeclaration);
1907    }
1908   
1909    public void VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer)
1910    {
1911      StartNode(fixedVariableInitializer);
1912      WriteIdentifier(fixedVariableInitializer.NameToken);
1913      if (!fixedVariableInitializer.CountExpression.IsNull) {
1914        WriteToken(Roles.LBracket);
1915        Space(policy.SpacesWithinBrackets);
1916        fixedVariableInitializer.CountExpression.AcceptVisitor(this);
1917        Space(policy.SpacesWithinBrackets);
1918        WriteToken(Roles.RBracket);
1919      }
1920      EndNode(fixedVariableInitializer);
1921    }
1922   
1923    public void VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
1924    {
1925      StartNode(indexerDeclaration);
1926      WriteAttributes(indexerDeclaration.Attributes);
1927      WriteModifiers(indexerDeclaration.ModifierTokens);
1928      indexerDeclaration.ReturnType.AcceptVisitor(this);
1929      Space();
1930      WritePrivateImplementationType(indexerDeclaration.PrivateImplementationType);
1931      WriteKeyword(IndexerDeclaration.ThisKeywordRole);
1932      Space(policy.SpaceBeforeMethodDeclarationParentheses);
1933      WriteCommaSeparatedListInBrackets(indexerDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
1934      OpenBrace(policy.PropertyBraceStyle);
1935      // output get/set in their original order
1936      foreach (AstNode node in indexerDeclaration.Children) {
1937        if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) {
1938          node.AcceptVisitor(this);
1939        }
1940      }
1941      CloseBrace(policy.PropertyBraceStyle);
1942      NewLine();
1943      EndNode(indexerDeclaration);
1944    }
1945   
1946    public void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
1947    {
1948      StartNode(methodDeclaration);
1949      WriteAttributes(methodDeclaration.Attributes);
1950      WriteModifiers(methodDeclaration.ModifierTokens);
1951      methodDeclaration.ReturnType.AcceptVisitor(this);
1952      Space();
1953      WritePrivateImplementationType(methodDeclaration.PrivateImplementationType);
1954      WriteIdentifier(methodDeclaration.NameToken);
1955      WriteTypeParameters(methodDeclaration.TypeParameters);
1956      Space(policy.SpaceBeforeMethodDeclarationParentheses);
1957      WriteCommaSeparatedListInParenthesis(methodDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
1958      foreach (Constraint constraint in methodDeclaration.Constraints) {
1959        constraint.AcceptVisitor(this);
1960      }
1961      WriteMethodBody(methodDeclaration.Body);
1962      EndNode(methodDeclaration);
1963    }
1964   
1965    public void VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration)
1966    {
1967      StartNode(operatorDeclaration);
1968      WriteAttributes(operatorDeclaration.Attributes);
1969      WriteModifiers(operatorDeclaration.ModifierTokens);
1970      if (operatorDeclaration.OperatorType == OperatorType.Explicit) {
1971        WriteKeyword(OperatorDeclaration.ExplicitRole);
1972      } else if (operatorDeclaration.OperatorType == OperatorType.Implicit) {
1973        WriteKeyword(OperatorDeclaration.ImplicitRole);
1974      } else {
1975        operatorDeclaration.ReturnType.AcceptVisitor(this);
1976      }
1977      WriteKeyword(OperatorDeclaration.OperatorKeywordRole);
1978      Space();
1979      if (operatorDeclaration.OperatorType == OperatorType.Explicit
1980          || operatorDeclaration.OperatorType == OperatorType.Implicit) {
1981        operatorDeclaration.ReturnType.AcceptVisitor(this);
1982      } else {
1983        WriteToken(OperatorDeclaration.GetToken(operatorDeclaration.OperatorType), OperatorDeclaration.GetRole(operatorDeclaration.OperatorType));
1984      }
1985      Space(policy.SpaceBeforeMethodDeclarationParentheses);
1986      WriteCommaSeparatedListInParenthesis(operatorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
1987      WriteMethodBody(operatorDeclaration.Body);
1988      EndNode(operatorDeclaration);
1989    }
1990   
1991    public void VisitParameterDeclaration(ParameterDeclaration parameterDeclaration)
1992    {
1993      StartNode(parameterDeclaration);
1994      WriteAttributes(parameterDeclaration.Attributes);
1995      switch (parameterDeclaration.ParameterModifier) {
1996        case ParameterModifier.Ref:
1997          WriteKeyword(ParameterDeclaration.RefModifierRole);
1998          break;
1999        case ParameterModifier.Out:
2000          WriteKeyword(ParameterDeclaration.OutModifierRole);
2001          break;
2002        case ParameterModifier.Params:
2003          WriteKeyword(ParameterDeclaration.ParamsModifierRole);
2004          break;
2005        case ParameterModifier.This:
2006          WriteKeyword(ParameterDeclaration.ThisModifierRole);
2007          break;
2008      }
2009      parameterDeclaration.Type.AcceptVisitor(this);
2010      if (!parameterDeclaration.Type.IsNull && !string.IsNullOrEmpty(parameterDeclaration.Name)) {
2011        Space();
2012      }
2013      if (!string.IsNullOrEmpty(parameterDeclaration.Name)) {
2014        WriteIdentifier(parameterDeclaration.NameToken);
2015      }
2016      if (!parameterDeclaration.DefaultExpression.IsNull) {
2017        Space(policy.SpaceAroundAssignment);
2018        WriteToken(Roles.Assign);
2019        Space(policy.SpaceAroundAssignment);
2020        parameterDeclaration.DefaultExpression.AcceptVisitor(this);
2021      }
2022      EndNode(parameterDeclaration);
2023    }
2024   
2025    public void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
2026    {
2027      StartNode(propertyDeclaration);
2028      WriteAttributes(propertyDeclaration.Attributes);
2029      WriteModifiers(propertyDeclaration.ModifierTokens);
2030      propertyDeclaration.ReturnType.AcceptVisitor(this);
2031      Space();
2032      WritePrivateImplementationType(propertyDeclaration.PrivateImplementationType);
2033      WriteIdentifier(propertyDeclaration.NameToken);
2034      OpenBrace(policy.PropertyBraceStyle);
2035      // output get/set in their original order
2036      foreach (AstNode node in propertyDeclaration.Children) {
2037        if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) {
2038          node.AcceptVisitor(this);
2039        }
2040      }
2041      CloseBrace(policy.PropertyBraceStyle);
2042      NewLine();
2043      EndNode(propertyDeclaration);
2044    }
2045
2046    #endregion
2047   
2048    #region Other nodes
2049    public void VisitVariableInitializer(VariableInitializer variableInitializer)
2050    {
2051      StartNode(variableInitializer);
2052      WriteIdentifier(variableInitializer.NameToken);
2053      if (!variableInitializer.Initializer.IsNull) {
2054        Space(policy.SpaceAroundAssignment);
2055        WriteToken(Roles.Assign);
2056        Space(policy.SpaceAroundAssignment);
2057        variableInitializer.Initializer.AcceptVisitor(this);
2058      }
2059      EndNode(variableInitializer);
2060    }
2061
2062    void MaybeNewLinesAfterUsings(AstNode node)
2063    {
2064      var nextSibling = node.NextSibling;
2065      while (nextSibling is WhitespaceNode || nextSibling is NewLineNode)
2066        nextSibling = nextSibling.NextSibling;
2067
2068      if ((node is UsingDeclaration || node is UsingAliasDeclaration) && !(nextSibling is UsingDeclaration || nextSibling is UsingAliasDeclaration)) {
2069        for (int i = 0; i < policy.MinimumBlankLinesAfterUsings; i++)
2070          NewLine();
2071      }
2072    }
2073   
2074    public void VisitSyntaxTree(SyntaxTree syntaxTree)
2075    {
2076      // don't do node tracking as we visit all children directly
2077      foreach (AstNode node in syntaxTree.Children) {
2078        node.AcceptVisitor(this);
2079        MaybeNewLinesAfterUsings(node);
2080      }
2081    }
2082   
2083    public void VisitSimpleType(SimpleType simpleType)
2084    {
2085      StartNode(simpleType);
2086      WriteIdentifier(simpleType.IdentifierToken);
2087      WriteTypeArguments(simpleType.TypeArguments);
2088      EndNode(simpleType);
2089    }
2090   
2091    public void VisitMemberType(MemberType memberType)
2092    {
2093      StartNode(memberType);
2094      memberType.Target.AcceptVisitor(this);
2095      if (memberType.IsDoubleColon) {
2096        WriteToken(Roles.DoubleColon);
2097      } else {
2098        WriteToken(Roles.Dot);
2099      }
2100      WriteIdentifier(memberType.MemberNameToken);
2101      WriteTypeArguments(memberType.TypeArguments);
2102      EndNode(memberType);
2103    }
2104   
2105    public void VisitComposedType(ComposedType composedType)
2106    {
2107      StartNode(composedType);
2108      composedType.BaseType.AcceptVisitor(this);
2109      if (composedType.HasNullableSpecifier) {
2110        WriteToken(ComposedType.NullableRole);
2111      }
2112      for (int i = 0; i < composedType.PointerRank; i++) {
2113        WriteToken(ComposedType.PointerRole);
2114      }
2115      foreach (var node in composedType.ArraySpecifiers) {
2116        node.AcceptVisitor(this);
2117      }
2118      EndNode(composedType);
2119    }
2120   
2121    public void VisitArraySpecifier(ArraySpecifier arraySpecifier)
2122    {
2123      StartNode(arraySpecifier);
2124      WriteToken(Roles.LBracket);
2125      foreach (var comma in arraySpecifier.GetChildrenByRole(Roles.Comma)) {
2126        writer.WriteToken(Roles.Comma, ",");
2127      }
2128      WriteToken(Roles.RBracket);
2129      EndNode(arraySpecifier);
2130    }
2131   
2132    public void VisitPrimitiveType(PrimitiveType primitiveType)
2133    {
2134      StartNode(primitiveType);
2135      writer.WritePrimitiveType(primitiveType.Keyword);
2136      EndNode(primitiveType);
2137    }
2138   
2139    public void VisitComment(Comment comment)
2140    {
2141      writer.StartNode(comment);
2142      writer.WriteComment(comment.CommentType, comment.Content);
2143      writer.EndNode(comment);
2144    }
2145
2146    public void VisitNewLine(NewLineNode newLineNode)
2147    {
2148//      formatter.StartNode(newLineNode);
2149//      formatter.NewLine();
2150//      formatter.EndNode(newLineNode);
2151    }
2152
2153    public void VisitWhitespace(WhitespaceNode whitespaceNode)
2154    {
2155      // unused
2156    }
2157
2158    public void VisitText(TextNode textNode)
2159    {
2160      // unused
2161    }
2162
2163    public void VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective)
2164    {
2165      writer.StartNode(preProcessorDirective);
2166      writer.WritePreProcessorDirective(preProcessorDirective.Type, preProcessorDirective.Argument);
2167      writer.EndNode(preProcessorDirective);
2168    }
2169   
2170    public void VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration)
2171    {
2172      StartNode(typeParameterDeclaration);
2173      WriteAttributes(typeParameterDeclaration.Attributes);
2174      switch (typeParameterDeclaration.Variance) {
2175        case VarianceModifier.Invariant:
2176          break;
2177        case VarianceModifier.Covariant:
2178          WriteKeyword(TypeParameterDeclaration.OutVarianceKeywordRole);
2179          break;
2180        case VarianceModifier.Contravariant:
2181          WriteKeyword(TypeParameterDeclaration.InVarianceKeywordRole);
2182          break;
2183        default:
2184          throw new NotSupportedException ("Invalid value for VarianceModifier");
2185      }
2186      WriteIdentifier(typeParameterDeclaration.NameToken);
2187      EndNode(typeParameterDeclaration);
2188    }
2189   
2190    public void VisitConstraint(Constraint constraint)
2191    {
2192      StartNode(constraint);
2193      Space();
2194      WriteKeyword(Roles.WhereKeyword);
2195      constraint.TypeParameter.AcceptVisitor(this);
2196      Space();
2197      WriteToken(Roles.Colon);
2198      Space();
2199      WriteCommaSeparatedList(constraint.BaseTypes);
2200      EndNode(constraint);
2201    }
2202   
2203    public void VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode)
2204    {
2205      CSharpModifierToken mod = cSharpTokenNode as CSharpModifierToken;
2206      if (mod != null) {
2207        // ITokenWriter assumes that each node processed between a
2208        // StartNode(parentNode)-EndNode(parentNode)-pair is a child of parentNode.
2209        WriteKeyword(CSharpModifierToken.GetModifierName(mod.Modifier), cSharpTokenNode.Role);
2210      } else {
2211        throw new NotSupportedException ("Should never visit individual tokens");
2212      }
2213    }
2214   
2215    public void VisitIdentifier(Identifier identifier)
2216    {
2217      // Do not call StartNode and EndNode for Identifier, because they are handled by the ITokenWriter.
2218      // ITokenWriter assumes that each node processed between a
2219      // StartNode(parentNode)-EndNode(parentNode)-pair is a child of parentNode.
2220      WriteIdentifier(identifier);
2221    }
2222
2223    void IAstVisitor.VisitNullNode(AstNode nullNode)
2224    {
2225    }
2226
2227    void IAstVisitor.VisitErrorNode(AstNode errorNode)
2228    {
2229      StartNode(errorNode);
2230      EndNode(errorNode);
2231    }
2232    #endregion
2233
2234    #region Pattern Nodes
2235    public void VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern)
2236    {
2237      StartNode(placeholder);
2238      VisitNodeInPattern(pattern);
2239      EndNode(placeholder);
2240    }
2241   
2242    void VisitAnyNode(AnyNode anyNode)
2243    {
2244      if (!string.IsNullOrEmpty(anyNode.GroupName)) {
2245        WriteIdentifier(anyNode.GroupName);
2246        WriteToken(Roles.Colon);
2247      }
2248    }
2249   
2250    void VisitBackreference(Backreference backreference)
2251    {
2252      WriteKeyword("backreference");
2253      LPar();
2254      WriteIdentifier(backreference.ReferencedGroupName);
2255      RPar();
2256    }
2257   
2258    void VisitIdentifierExpressionBackreference(IdentifierExpressionBackreference identifierExpressionBackreference)
2259    {
2260      WriteKeyword("identifierBackreference");
2261      LPar();
2262      WriteIdentifier(identifierExpressionBackreference.ReferencedGroupName);
2263      RPar();
2264    }
2265   
2266    void VisitChoice(Choice choice)
2267    {
2268      WriteKeyword("choice");
2269      Space();
2270      LPar();
2271      NewLine();
2272      writer.Indent();
2273      foreach (INode alternative in choice) {
2274        VisitNodeInPattern(alternative);
2275        if (alternative != choice.Last()) {
2276          WriteToken(Roles.Comma);
2277        }
2278        NewLine();
2279      }
2280      writer.Unindent();
2281      RPar();
2282    }
2283   
2284    void VisitNamedNode(NamedNode namedNode)
2285    {
2286      if (!string.IsNullOrEmpty(namedNode.GroupName)) {
2287        WriteIdentifier(namedNode.GroupName);
2288        WriteToken(Roles.Colon);
2289      }
2290      VisitNodeInPattern(namedNode.ChildNode);
2291    }
2292   
2293    void VisitRepeat(Repeat repeat)
2294    {
2295      WriteKeyword("repeat");
2296      LPar();
2297      if (repeat.MinCount != 0 || repeat.MaxCount != int.MaxValue) {
2298        WriteIdentifier(repeat.MinCount.ToString());
2299        WriteToken(Roles.Comma);
2300        WriteIdentifier(repeat.MaxCount.ToString());
2301        WriteToken(Roles.Comma);
2302      }
2303      VisitNodeInPattern(repeat.ChildNode);
2304      RPar();
2305    }
2306   
2307    void VisitOptionalNode(OptionalNode optionalNode)
2308    {
2309      WriteKeyword("optional");
2310      LPar();
2311      VisitNodeInPattern(optionalNode.ChildNode);
2312      RPar();
2313    }
2314   
2315    void VisitNodeInPattern(INode childNode)
2316    {
2317      if (childNode is AstNode) {
2318        ((AstNode)childNode).AcceptVisitor(this);
2319      } else if (childNode is IdentifierExpressionBackreference) {
2320        VisitIdentifierExpressionBackreference((IdentifierExpressionBackreference)childNode);
2321      } else if (childNode is Choice) {
2322        VisitChoice((Choice)childNode);
2323      } else if (childNode is AnyNode) {
2324        VisitAnyNode((AnyNode)childNode);
2325      } else if (childNode is Backreference) {
2326        VisitBackreference((Backreference)childNode);
2327      } else if (childNode is NamedNode) {
2328        VisitNamedNode((NamedNode)childNode);
2329      } else if (childNode is OptionalNode) {
2330        VisitOptionalNode((OptionalNode)childNode);
2331      } else if (childNode is Repeat) {
2332        VisitRepeat((Repeat)childNode);
2333      } else {
2334        TextWriterTokenWriter.PrintPrimitiveValue(childNode);
2335      }
2336    }
2337    #endregion
2338   
2339    #region Documentation Reference
2340    public void VisitDocumentationReference(DocumentationReference documentationReference)
2341    {
2342      StartNode(documentationReference);
2343      if (!documentationReference.DeclaringType.IsNull) {
2344        documentationReference.DeclaringType.AcceptVisitor(this);
2345        if (documentationReference.SymbolKind != SymbolKind.TypeDefinition) {
2346          WriteToken(Roles.Dot);
2347        }
2348      }
2349      switch (documentationReference.SymbolKind) {
2350        case SymbolKind.TypeDefinition:
2351          // we already printed the DeclaringType
2352          break;
2353        case SymbolKind.Indexer:
2354          WriteKeyword(IndexerDeclaration.ThisKeywordRole);
2355          break;
2356        case SymbolKind.Operator:
2357          var opType = documentationReference.OperatorType;
2358          if (opType == OperatorType.Explicit) {
2359            WriteKeyword(OperatorDeclaration.ExplicitRole);
2360          } else if (opType == OperatorType.Implicit) {
2361            WriteKeyword(OperatorDeclaration.ImplicitRole);
2362          }
2363          WriteKeyword(OperatorDeclaration.OperatorKeywordRole);
2364          Space();
2365          if (opType == OperatorType.Explicit || opType == OperatorType.Implicit) {
2366            documentationReference.ConversionOperatorReturnType.AcceptVisitor(this);
2367          } else {
2368            WriteToken(OperatorDeclaration.GetToken(opType), OperatorDeclaration.GetRole(opType));
2369          }
2370          break;
2371        default:
2372          WriteIdentifier(documentationReference.GetChildByRole(Roles.Identifier));
2373          break;
2374      }
2375      WriteTypeArguments(documentationReference.TypeArguments);
2376      if (documentationReference.HasParameterList) {
2377        Space(policy.SpaceBeforeMethodDeclarationParentheses);
2378        if (documentationReference.SymbolKind == SymbolKind.Indexer) {
2379          WriteCommaSeparatedListInBrackets(documentationReference.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
2380        } else {
2381          WriteCommaSeparatedListInParenthesis(documentationReference.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
2382        }
2383      }
2384      EndNode(documentationReference);
2385    }
2386    #endregion
2387   
2388    /// <summary>
2389    /// Converts special characters to escape sequences within the given string.
2390    /// </summary>
2391    public static string ConvertString(string text)
2392    {
2393      return TextWriterTokenWriter.ConvertString(text);
2394    }
2395  }
2396}
Note: See TracBrowser for help on using the repository browser.