~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to contrib/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

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