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

« back to all changes in this revision

Viewing changes to external/nrefactory/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) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
 
2
// 
 
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
 
4
// software and associated documentation files (the "Software"), to deal in the Software
 
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
 
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
 
7
// to whom the Software is furnished to do so, subject to the following conditions:
 
8
// 
 
9
// The above copyright notice and this permission notice shall be included in all copies or
 
10
// substantial portions of the Software.
 
11
// 
 
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
17
// DEALINGS IN THE SOFTWARE.
 
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
                public static string PrintPrimitiveValue(object val)
 
1011
                {
 
1012
                        StringWriter writer = new StringWriter();
 
1013
                        CSharpOutputVisitor visitor = new CSharpOutputVisitor(writer, new CSharpFormattingOptions());
 
1014
                        visitor.WritePrimitiveValue(val);
 
1015
                        return writer.ToString();
 
1016
                }
 
1017
                
 
1018
                void WritePrimitiveValue(object val)
 
1019
                {
 
1020
                        if (val == null) {
 
1021
                                // usually NullReferenceExpression should be used for this, but we'll handle it anyways
 
1022
                                WriteKeyword("null");
 
1023
                                return;
 
1024
                        }
 
1025
                        
 
1026
                        if (val is bool) {
 
1027
                                if ((bool)val) {
 
1028
                                        WriteKeyword("true");
 
1029
                                } else {
 
1030
                                        WriteKeyword("false");
 
1031
                                }
 
1032
                                return;
 
1033
                        }
 
1034
                        
 
1035
                        if (val is string) {
 
1036
                                formatter.WriteToken("\"" + ConvertString(val.ToString()) + "\"");
 
1037
                                lastWritten = LastWritten.Other;
 
1038
                        } else if (val is char) {
 
1039
                                formatter.WriteToken("'" + ConvertCharLiteral((char)val) + "'");
 
1040
                                lastWritten = LastWritten.Other;
 
1041
                        } else if (val is decimal) {
 
1042
                                formatter.WriteToken(((decimal)val).ToString(NumberFormatInfo.InvariantInfo) + "m");
 
1043
                                lastWritten = LastWritten.Other;
 
1044
                        } else if (val is float) {
 
1045
                                float f = (float)val;
 
1046
                                if (float.IsInfinity(f) || float.IsNaN(f)) {
 
1047
                                        // Strictly speaking, these aren't PrimitiveExpressions;
 
1048
                                        // but we still support writing these to make life easier for code generators.
 
1049
                                        WriteKeyword("float");
 
1050
                                        WriteToken(Roles.Dot);
 
1051
                                        if (float.IsPositiveInfinity(f)) {
 
1052
                                                WriteIdentifier("PositiveInfinity");
 
1053
                                        } else if (float.IsNegativeInfinity(f)) {
 
1054
                                                WriteIdentifier("NegativeInfinity");
 
1055
                                        } else {
 
1056
                                                WriteIdentifier("NaN");
 
1057
                                        }
 
1058
                                        return;
 
1059
                                }
 
1060
                                if (f == 0 && 1 / f == float.NegativeInfinity) {
 
1061
                                        // negative zero is a special case
 
1062
                                        // (again, not a primitive expression, but it's better to handle
 
1063
                                        // the special case here than to do it in all code generators)
 
1064
                                        formatter.WriteToken("-");
 
1065
                                }
 
1066
                                formatter.WriteToken(f.ToString("R", NumberFormatInfo.InvariantInfo) + "f");
 
1067
                                lastWritten = LastWritten.Other;
 
1068
                        } else if (val is double) {
 
1069
                                double f = (double)val;
 
1070
                                if (double.IsInfinity(f) || double.IsNaN(f)) {
 
1071
                                        // Strictly speaking, these aren't PrimitiveExpressions;
 
1072
                                        // but we still support writing these to make life easier for code generators.
 
1073
                                        WriteKeyword("double");
 
1074
                                        WriteToken(Roles.Dot);
 
1075
                                        if (double.IsPositiveInfinity(f)) {
 
1076
                                                WriteIdentifier("PositiveInfinity");
 
1077
                                        } else if (double.IsNegativeInfinity(f)) {
 
1078
                                                WriteIdentifier("NegativeInfinity");
 
1079
                                        } else {
 
1080
                                                WriteIdentifier("NaN");
 
1081
                                        }
 
1082
                                        return;
 
1083
                                }
 
1084
                                if (f == 0 && 1 / f == double.NegativeInfinity) {
 
1085
                                        // negative zero is a special case
 
1086
                                        // (again, not a primitive expression, but it's better to handle
 
1087
                                        // the special case here than to do it in all code generators)
 
1088
                                        formatter.WriteToken("-");
 
1089
                                }
 
1090
                                string number = f.ToString("R", NumberFormatInfo.InvariantInfo);
 
1091
                                if (number.IndexOf('.') < 0 && number.IndexOf('E') < 0) {
 
1092
                                        number += ".0";
 
1093
                                }
 
1094
                                formatter.WriteToken(number);
 
1095
                                // needs space if identifier follows number; this avoids mistaking the following identifier as type suffix
 
1096
                                lastWritten = LastWritten.KeywordOrIdentifier;
 
1097
                        } else if (val is IFormattable) {
 
1098
                                StringBuilder b = new StringBuilder ();
 
1099
                                //                              if (primitiveExpression.LiteralFormat == LiteralFormat.HexadecimalNumber) {
 
1100
                                //                                      b.Append("0x");
 
1101
                                //                                      b.Append(((IFormattable)val).ToString("x", NumberFormatInfo.InvariantInfo));
 
1102
                                //                              } else {
 
1103
                                b.Append(((IFormattable)val).ToString(null, NumberFormatInfo.InvariantInfo));
 
1104
                                //                              }
 
1105
                                if (val is uint || val is ulong) {
 
1106
                                        b.Append("u");
 
1107
                                }
 
1108
                                if (val is long || val is ulong) {
 
1109
                                        b.Append("L");
 
1110
                                }
 
1111
                                formatter.WriteToken(b.ToString());
 
1112
                                // needs space if identifier follows number; this avoids mistaking the following identifier as type suffix
 
1113
                                lastWritten = LastWritten.KeywordOrIdentifier;
 
1114
                        } else {
 
1115
                                formatter.WriteToken(val.ToString());
 
1116
                                lastWritten = LastWritten.Other;
 
1117
                        }
 
1118
                }
 
1119
                
 
1120
                static string ConvertCharLiteral(char ch)
 
1121
                {
 
1122
                        if (ch == '\'') {
 
1123
                                return "\\'";
 
1124
                        }
 
1125
                        return ConvertChar(ch);
 
1126
                }
 
1127
                
 
1128
                /// <summary>
 
1129
                /// Gets the escape sequence for the specified character.
 
1130
                /// </summary>
 
1131
                /// <remarks>This method does not convert ' or ".</remarks>
 
1132
                public static string ConvertChar(char ch)
 
1133
                {
 
1134
                        switch (ch) {
 
1135
                                case '\\':
 
1136
                                        return "\\\\";
 
1137
                                case '\0':
 
1138
                                        return "\\0";
 
1139
                                case '\a':
 
1140
                                        return "\\a";
 
1141
                                case '\b':
 
1142
                                        return "\\b";
 
1143
                                case '\f':
 
1144
                                        return "\\f";
 
1145
                                case '\n':
 
1146
                                        return "\\n";
 
1147
                                case '\r':
 
1148
                                        return "\\r";
 
1149
                                case '\t':
 
1150
                                        return "\\t";
 
1151
                                case '\v':
 
1152
                                        return "\\v";
 
1153
                                default:
 
1154
                                        if (char.IsControl(ch) || char.IsSurrogate(ch) ||
 
1155
                                        // print all uncommon white spaces as numbers
 
1156
                                                (char.IsWhiteSpace(ch) && ch != ' ')) {
 
1157
                                                return "\\u" + ((int)ch).ToString("x4");
 
1158
                                        } else {
 
1159
                                                return ch.ToString();
 
1160
                                        }
 
1161
                        }
 
1162
                }
 
1163
                
 
1164
                /// <summary>
 
1165
                /// Converts special characters to escape sequences within the given string.
 
1166
                /// </summary>
 
1167
                public static string ConvertString(string str)
 
1168
                {
 
1169
                        StringBuilder sb = new StringBuilder ();
 
1170
                        foreach (char ch in str) {
 
1171
                                if (ch == '"') {
 
1172
                                        sb.Append("\\\"");
 
1173
                                } else {
 
1174
                                        sb.Append(ConvertChar(ch));
 
1175
                                }
 
1176
                        }
 
1177
                        return sb.ToString();
 
1178
                }
 
1179
 
 
1180
                #endregion
 
1181
                
 
1182
                public void VisitSizeOfExpression(SizeOfExpression sizeOfExpression)
 
1183
                {
 
1184
                        StartNode(sizeOfExpression);
 
1185
                        
 
1186
                        WriteKeyword(SizeOfExpression.SizeofKeywordRole);
 
1187
                        LPar();
 
1188
                        Space(policy.SpacesWithinSizeOfParentheses);
 
1189
                        sizeOfExpression.Type.AcceptVisitor(this);
 
1190
                        Space(policy.SpacesWithinSizeOfParentheses);
 
1191
                        RPar();
 
1192
                        
 
1193
                        EndNode(sizeOfExpression);
 
1194
                }
 
1195
                
 
1196
                public void VisitStackAllocExpression(StackAllocExpression stackAllocExpression)
 
1197
                {
 
1198
                        StartNode(stackAllocExpression);
 
1199
                        WriteKeyword(StackAllocExpression.StackallocKeywordRole);
 
1200
                        stackAllocExpression.Type.AcceptVisitor(this);
 
1201
                        WriteCommaSeparatedListInBrackets(new[] { stackAllocExpression.CountExpression });
 
1202
                        EndNode(stackAllocExpression);
 
1203
                }
 
1204
                
 
1205
                public void VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression)
 
1206
                {
 
1207
                        StartNode(thisReferenceExpression);
 
1208
                        WriteKeyword("this", thisReferenceExpression.Role);
 
1209
                        EndNode(thisReferenceExpression);
 
1210
                }
 
1211
                
 
1212
                public void VisitTypeOfExpression(TypeOfExpression typeOfExpression)
 
1213
                {
 
1214
                        StartNode(typeOfExpression);
 
1215
                        
 
1216
                        WriteKeyword(TypeOfExpression.TypeofKeywordRole);
 
1217
                        LPar();
 
1218
                        Space(policy.SpacesWithinTypeOfParentheses);
 
1219
                        typeOfExpression.Type.AcceptVisitor(this);
 
1220
                        Space(policy.SpacesWithinTypeOfParentheses);
 
1221
                        RPar();
 
1222
                        
 
1223
                        EndNode(typeOfExpression);
 
1224
                }
 
1225
                
 
1226
                public void VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression)
 
1227
                {
 
1228
                        StartNode(typeReferenceExpression);
 
1229
                        typeReferenceExpression.Type.AcceptVisitor(this);
 
1230
                        EndNode(typeReferenceExpression);
 
1231
                }
 
1232
                
 
1233
                public void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
 
1234
                {
 
1235
                        StartNode(unaryOperatorExpression);
 
1236
                        UnaryOperatorType opType = unaryOperatorExpression.Operator;
 
1237
                        var opSymbol = UnaryOperatorExpression.GetOperatorRole(opType);
 
1238
                        if (opType == UnaryOperatorType.Await) {
 
1239
                                WriteKeyword(opSymbol);
 
1240
                        } else if (!(opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)) {
 
1241
                                WriteToken(opSymbol);
 
1242
                        }
 
1243
                        unaryOperatorExpression.Expression.AcceptVisitor(this);
 
1244
                        if (opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement) {
 
1245
                                WriteToken(opSymbol);
 
1246
                        }
 
1247
                        EndNode(unaryOperatorExpression);
 
1248
                }
 
1249
                
 
1250
                public void VisitUncheckedExpression(UncheckedExpression uncheckedExpression)
 
1251
                {
 
1252
                        StartNode(uncheckedExpression);
 
1253
                        WriteKeyword(UncheckedExpression.UncheckedKeywordRole);
 
1254
                        LPar();
 
1255
                        Space(policy.SpacesWithinCheckedExpressionParantheses);
 
1256
                        uncheckedExpression.Expression.AcceptVisitor(this);
 
1257
                        Space(policy.SpacesWithinCheckedExpressionParantheses);
 
1258
                        RPar();
 
1259
                        EndNode(uncheckedExpression);
 
1260
                }
 
1261
 
 
1262
                #endregion
 
1263
                
 
1264
                #region Query Expressions
 
1265
                public void VisitQueryExpression(QueryExpression queryExpression)
 
1266
                {
 
1267
                        StartNode(queryExpression);
 
1268
                        bool indent = !(queryExpression.Parent is QueryContinuationClause);
 
1269
                        if (indent) {
 
1270
                                formatter.Indent();
 
1271
                                NewLine();
 
1272
                        }
 
1273
                        bool first = true;
 
1274
                        foreach (var clause in queryExpression.Clauses) {
 
1275
                                if (first) {
 
1276
                                        first = false;
 
1277
                                } else {
 
1278
                                        if (!(clause is QueryContinuationClause)) {
 
1279
                                                NewLine();
 
1280
                                        }
 
1281
                                }
 
1282
                                clause.AcceptVisitor(this);
 
1283
                        }
 
1284
                        if (indent) {
 
1285
                                formatter.Unindent();
 
1286
                        }
 
1287
                        EndNode(queryExpression);
 
1288
                }
 
1289
                
 
1290
                public void VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause)
 
1291
                {
 
1292
                        StartNode(queryContinuationClause);
 
1293
                        queryContinuationClause.PrecedingQuery.AcceptVisitor(this);
 
1294
                        Space();
 
1295
                        WriteKeyword(QueryContinuationClause.IntoKeywordRole);
 
1296
                        Space();
 
1297
                        queryContinuationClause.IdentifierToken.AcceptVisitor(this);
 
1298
                        EndNode(queryContinuationClause);
 
1299
                }
 
1300
                
 
1301
                public void VisitQueryFromClause(QueryFromClause queryFromClause)
 
1302
                {
 
1303
                        StartNode(queryFromClause);
 
1304
                        WriteKeyword(QueryFromClause.FromKeywordRole);
 
1305
                        queryFromClause.Type.AcceptVisitor(this);
 
1306
                        Space();
 
1307
                        queryFromClause.IdentifierToken.AcceptVisitor(this);
 
1308
                        Space();
 
1309
                        WriteKeyword(QueryFromClause.InKeywordRole);
 
1310
                        Space();
 
1311
                        queryFromClause.Expression.AcceptVisitor(this);
 
1312
                        EndNode(queryFromClause);
 
1313
                }
 
1314
                
 
1315
                public void VisitQueryLetClause(QueryLetClause queryLetClause)
 
1316
                {
 
1317
                        StartNode(queryLetClause);
 
1318
                        WriteKeyword(QueryLetClause.LetKeywordRole);
 
1319
                        Space();
 
1320
                        queryLetClause.IdentifierToken.AcceptVisitor(this);
 
1321
                        Space(policy.SpaceAroundAssignment);
 
1322
                        WriteToken(Roles.Assign);
 
1323
                        Space(policy.SpaceAroundAssignment);
 
1324
                        queryLetClause.Expression.AcceptVisitor(this);
 
1325
                        EndNode(queryLetClause);
 
1326
                }
 
1327
                
 
1328
                public void VisitQueryWhereClause(QueryWhereClause queryWhereClause)
 
1329
                {
 
1330
                        StartNode(queryWhereClause);
 
1331
                        WriteKeyword(QueryWhereClause.WhereKeywordRole);
 
1332
                        Space();
 
1333
                        queryWhereClause.Condition.AcceptVisitor(this);
 
1334
                        EndNode(queryWhereClause);
 
1335
                }
 
1336
                
 
1337
                public void VisitQueryJoinClause(QueryJoinClause queryJoinClause)
 
1338
                {
 
1339
                        StartNode(queryJoinClause);
 
1340
                        WriteKeyword(QueryJoinClause.JoinKeywordRole);
 
1341
                        queryJoinClause.Type.AcceptVisitor(this);
 
1342
                        Space();
 
1343
                        WriteIdentifier(queryJoinClause.JoinIdentifier, QueryJoinClause.JoinIdentifierRole);
 
1344
                        Space();
 
1345
                        WriteKeyword(QueryJoinClause.InKeywordRole);
 
1346
                        Space();
 
1347
                        queryJoinClause.InExpression.AcceptVisitor(this);
 
1348
                        Space();
 
1349
                        WriteKeyword(QueryJoinClause.OnKeywordRole);
 
1350
                        Space();
 
1351
                        queryJoinClause.OnExpression.AcceptVisitor(this);
 
1352
                        Space();
 
1353
                        WriteKeyword(QueryJoinClause.EqualsKeywordRole);
 
1354
                        Space();
 
1355
                        queryJoinClause.EqualsExpression.AcceptVisitor(this);
 
1356
                        if (queryJoinClause.IsGroupJoin) {
 
1357
                                Space();
 
1358
                                WriteKeyword(QueryJoinClause.IntoKeywordRole);
 
1359
                                WriteIdentifier(queryJoinClause.IntoIdentifier, QueryJoinClause.IntoIdentifierRole);
 
1360
                        }
 
1361
                        EndNode(queryJoinClause);
 
1362
                }
 
1363
                
 
1364
                public void VisitQueryOrderClause(QueryOrderClause queryOrderClause)
 
1365
                {
 
1366
                        StartNode(queryOrderClause);
 
1367
                        WriteKeyword(QueryOrderClause.OrderbyKeywordRole);
 
1368
                        Space();
 
1369
                        WriteCommaSeparatedList(queryOrderClause.Orderings);
 
1370
                        EndNode(queryOrderClause);
 
1371
                }
 
1372
                
 
1373
                public void VisitQueryOrdering(QueryOrdering queryOrdering)
 
1374
                {
 
1375
                        StartNode(queryOrdering);
 
1376
                        queryOrdering.Expression.AcceptVisitor(this);
 
1377
                        switch (queryOrdering.Direction) {
 
1378
                                case QueryOrderingDirection.Ascending:
 
1379
                                        Space();
 
1380
                                        WriteKeyword(QueryOrdering.AscendingKeywordRole);
 
1381
                                        break;
 
1382
                                case QueryOrderingDirection.Descending:
 
1383
                                        Space();
 
1384
                                        WriteKeyword(QueryOrdering.DescendingKeywordRole);
 
1385
                                        break;
 
1386
                        }
 
1387
                        EndNode(queryOrdering);
 
1388
                }
 
1389
                
 
1390
                public void VisitQuerySelectClause(QuerySelectClause querySelectClause)
 
1391
                {
 
1392
                        StartNode(querySelectClause);
 
1393
                        WriteKeyword(QuerySelectClause.SelectKeywordRole);
 
1394
                        Space();
 
1395
                        querySelectClause.Expression.AcceptVisitor(this);
 
1396
                        EndNode(querySelectClause);
 
1397
                }
 
1398
                
 
1399
                public void VisitQueryGroupClause(QueryGroupClause queryGroupClause)
 
1400
                {
 
1401
                        StartNode(queryGroupClause);
 
1402
                        WriteKeyword(QueryGroupClause.GroupKeywordRole);
 
1403
                        Space();
 
1404
                        queryGroupClause.Projection.AcceptVisitor(this);
 
1405
                        Space();
 
1406
                        WriteKeyword(QueryGroupClause.ByKeywordRole);
 
1407
                        Space();
 
1408
                        queryGroupClause.Key.AcceptVisitor(this);
 
1409
                        EndNode(queryGroupClause);
 
1410
                }
 
1411
 
 
1412
                #endregion
 
1413
                
 
1414
                #region GeneralScope
 
1415
                public void VisitAttribute(Attribute attribute)
 
1416
                {
 
1417
                        StartNode(attribute);
 
1418
                        attribute.Type.AcceptVisitor(this);
 
1419
                        if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole(Roles.LPar).IsNull) {
 
1420
                                Space(policy.SpaceBeforeMethodCallParentheses);
 
1421
                                WriteCommaSeparatedListInParenthesis(attribute.Arguments, policy.SpaceWithinMethodCallParentheses);
 
1422
                        }
 
1423
                        EndNode(attribute);
 
1424
                }
 
1425
                
 
1426
                public void VisitAttributeSection(AttributeSection attributeSection)
 
1427
                {
 
1428
                        StartNode(attributeSection);
 
1429
                        WriteToken(Roles.LBracket);
 
1430
                        if (!string.IsNullOrEmpty(attributeSection.AttributeTarget)) {
 
1431
                                WriteToken(attributeSection.AttributeTarget, Roles.AttributeTargetRole);
 
1432
                                WriteToken(Roles.Colon);
 
1433
                                Space();
 
1434
                        }
 
1435
                        WriteCommaSeparatedList(attributeSection.Attributes);
 
1436
                        WriteToken(Roles.RBracket);
 
1437
                        if (attributeSection.Parent is ParameterDeclaration || attributeSection.Parent is TypeParameterDeclaration) {
 
1438
                                Space();
 
1439
                        } else {
 
1440
                                NewLine();
 
1441
                        }
 
1442
                        EndNode(attributeSection);
 
1443
                }
 
1444
                
 
1445
                public void VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
 
1446
                {
 
1447
                        StartNode(delegateDeclaration);
 
1448
                        WriteAttributes(delegateDeclaration.Attributes);
 
1449
                        WriteModifiers(delegateDeclaration.ModifierTokens);
 
1450
                        WriteKeyword(Roles.DelegateKeyword);
 
1451
                        delegateDeclaration.ReturnType.AcceptVisitor(this);
 
1452
                        Space();
 
1453
                        delegateDeclaration.NameToken.AcceptVisitor(this);
 
1454
                        WriteTypeParameters(delegateDeclaration.TypeParameters);
 
1455
                        Space(policy.SpaceBeforeDelegateDeclarationParentheses);
 
1456
                        WriteCommaSeparatedListInParenthesis(delegateDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
 
1457
                        foreach (Constraint constraint in delegateDeclaration.Constraints) {
 
1458
                                constraint.AcceptVisitor(this);
 
1459
                        }
 
1460
                        Semicolon();
 
1461
                        EndNode(delegateDeclaration);
 
1462
                }
 
1463
                
 
1464
                public void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
 
1465
                {
 
1466
                        StartNode(namespaceDeclaration);
 
1467
                        WriteKeyword(Roles.NamespaceKeyword);
 
1468
                        WriteQualifiedIdentifier(namespaceDeclaration.Identifiers);
 
1469
                        OpenBrace(policy.NamespaceBraceStyle);
 
1470
                        foreach (var member in namespaceDeclaration.Members) {
 
1471
                                member.AcceptVisitor(this);
 
1472
                        }
 
1473
                        CloseBrace(policy.NamespaceBraceStyle);
 
1474
                        OptionalSemicolon();
 
1475
                        NewLine();
 
1476
                        EndNode(namespaceDeclaration);
 
1477
                }
 
1478
                
 
1479
                public void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
 
1480
                {
 
1481
                        StartNode(typeDeclaration);
 
1482
                        WriteAttributes(typeDeclaration.Attributes);
 
1483
                        WriteModifiers(typeDeclaration.ModifierTokens);
 
1484
                        BraceStyle braceStyle;
 
1485
                        switch (typeDeclaration.ClassType) {
 
1486
                                case ClassType.Enum:
 
1487
                                        WriteKeyword(Roles.EnumKeyword);
 
1488
                                        braceStyle = policy.EnumBraceStyle;
 
1489
                                        break;
 
1490
                                case ClassType.Interface:
 
1491
                                        WriteKeyword(Roles.InterfaceKeyword);
 
1492
                                        braceStyle = policy.InterfaceBraceStyle;
 
1493
                                        break;
 
1494
                                case ClassType.Struct:
 
1495
                                        WriteKeyword(Roles.StructKeyword);
 
1496
                                        braceStyle = policy.StructBraceStyle;
 
1497
                                        break;
 
1498
                                default:
 
1499
                                        WriteKeyword(Roles.ClassKeyword);
 
1500
                                        braceStyle = policy.ClassBraceStyle;
 
1501
                                        break;
 
1502
                        }
 
1503
                        typeDeclaration.NameToken.AcceptVisitor(this);
 
1504
                        WriteTypeParameters(typeDeclaration.TypeParameters);
 
1505
                        if (typeDeclaration.BaseTypes.Any()) {
 
1506
                                Space();
 
1507
                                WriteToken(Roles.Colon);
 
1508
                                Space();
 
1509
                                WriteCommaSeparatedList(typeDeclaration.BaseTypes);
 
1510
                        }
 
1511
                        foreach (Constraint constraint in typeDeclaration.Constraints) {
 
1512
                                constraint.AcceptVisitor(this);
 
1513
                        }
 
1514
                        OpenBrace(braceStyle);
 
1515
                        if (typeDeclaration.ClassType == ClassType.Enum) {
 
1516
                                bool first = true;
 
1517
                                foreach (var member in typeDeclaration.Members) {
 
1518
                                        if (first) {
 
1519
                                                first = false;
 
1520
                                        } else {
 
1521
                                                Comma(member, noSpaceAfterComma: true);
 
1522
                                                NewLine();
 
1523
                                        }
 
1524
                                        member.AcceptVisitor(this);
 
1525
                                }
 
1526
                                OptionalComma();
 
1527
                                NewLine();
 
1528
                        } else {
 
1529
                                foreach (var member in typeDeclaration.Members) {
 
1530
                                        member.AcceptVisitor(this);
 
1531
                                }
 
1532
                        }
 
1533
                        CloseBrace(braceStyle);
 
1534
                        OptionalSemicolon();
 
1535
                        NewLine();
 
1536
                        EndNode(typeDeclaration);
 
1537
                }
 
1538
                
 
1539
                public void VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration)
 
1540
                {
 
1541
                        StartNode(usingAliasDeclaration);
 
1542
                        WriteKeyword(UsingAliasDeclaration.UsingKeywordRole);
 
1543
                        WriteIdentifier(usingAliasDeclaration.Alias, UsingAliasDeclaration.AliasRole);
 
1544
                        Space(policy.SpaceAroundEqualityOperator);
 
1545
                        WriteToken(Roles.Assign);
 
1546
                        Space(policy.SpaceAroundEqualityOperator);
 
1547
                        usingAliasDeclaration.Import.AcceptVisitor(this);
 
1548
                        Semicolon();
 
1549
                        EndNode(usingAliasDeclaration);
 
1550
                }
 
1551
                
 
1552
                public void VisitUsingDeclaration(UsingDeclaration usingDeclaration)
 
1553
                {
 
1554
                        StartNode(usingDeclaration);
 
1555
                        WriteKeyword(UsingDeclaration.UsingKeywordRole);
 
1556
                        usingDeclaration.Import.AcceptVisitor(this);
 
1557
                        Semicolon();
 
1558
                        EndNode(usingDeclaration);
 
1559
                }
 
1560
                
 
1561
                public void VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration)
 
1562
                {
 
1563
                        StartNode(externAliasDeclaration);
 
1564
                        WriteKeyword(Roles.ExternKeyword);
 
1565
                        Space();
 
1566
                        WriteKeyword(Roles.AliasKeyword);
 
1567
                        Space();
 
1568
                        externAliasDeclaration.NameToken.AcceptVisitor(this);
 
1569
                        Semicolon();
 
1570
                        EndNode(externAliasDeclaration);
 
1571
                }
 
1572
 
 
1573
                #endregion
 
1574
                
 
1575
                #region Statements
 
1576
                public void VisitBlockStatement(BlockStatement blockStatement)
 
1577
                {
 
1578
                        StartNode(blockStatement);
 
1579
                        BraceStyle style;
 
1580
                        if (blockStatement.Parent is AnonymousMethodExpression || blockStatement.Parent is LambdaExpression) {
 
1581
                                style = policy.AnonymousMethodBraceStyle;
 
1582
                        } else if (blockStatement.Parent is ConstructorDeclaration) {
 
1583
                                style = policy.ConstructorBraceStyle;
 
1584
                        } else if (blockStatement.Parent is DestructorDeclaration) {
 
1585
                                style = policy.DestructorBraceStyle;
 
1586
                        } else if (blockStatement.Parent is MethodDeclaration) {
 
1587
                                style = policy.MethodBraceStyle;
 
1588
                        } else if (blockStatement.Parent is Accessor) {
 
1589
                                if (blockStatement.Parent.Role == PropertyDeclaration.GetterRole) {
 
1590
                                        style = policy.PropertyGetBraceStyle;
 
1591
                                } else if (blockStatement.Parent.Role == PropertyDeclaration.SetterRole) {
 
1592
                                        style = policy.PropertySetBraceStyle;
 
1593
                                } else if (blockStatement.Parent.Role == CustomEventDeclaration.AddAccessorRole) {
 
1594
                                        style = policy.EventAddBraceStyle;
 
1595
                                } else if (blockStatement.Parent.Role == CustomEventDeclaration.RemoveAccessorRole) {
 
1596
                                        style = policy.EventRemoveBraceStyle;
 
1597
                                } else {
 
1598
                                        style = policy.StatementBraceStyle;
 
1599
                                }
 
1600
                        } else {
 
1601
                                style = policy.StatementBraceStyle;
 
1602
                        }
 
1603
                        OpenBrace(style);
 
1604
                        foreach (var node in blockStatement.Statements) {
 
1605
                                node.AcceptVisitor(this);
 
1606
                        }
 
1607
                        CloseBrace(style);
 
1608
                        if (!(blockStatement.Parent is Expression))
 
1609
                                NewLine();
 
1610
                        EndNode(blockStatement);
 
1611
                }
 
1612
                
 
1613
                public void VisitBreakStatement(BreakStatement breakStatement)
 
1614
                {
 
1615
                        StartNode(breakStatement);
 
1616
                        WriteKeyword("break");
 
1617
                        Semicolon();
 
1618
                        EndNode(breakStatement);
 
1619
                }
 
1620
                
 
1621
                public void VisitCheckedStatement(CheckedStatement checkedStatement)
 
1622
                {
 
1623
                        StartNode(checkedStatement);
 
1624
                        WriteKeyword(CheckedStatement.CheckedKeywordRole);
 
1625
                        checkedStatement.Body.AcceptVisitor(this);
 
1626
                        EndNode(checkedStatement);
 
1627
                }
 
1628
                
 
1629
                public void VisitContinueStatement(ContinueStatement continueStatement)
 
1630
                {
 
1631
                        StartNode(continueStatement);
 
1632
                        WriteKeyword("continue");
 
1633
                        Semicolon();
 
1634
                        EndNode(continueStatement);
 
1635
                }
 
1636
                
 
1637
                public void VisitDoWhileStatement(DoWhileStatement doWhileStatement)
 
1638
                {
 
1639
                        StartNode(doWhileStatement);
 
1640
                        WriteKeyword(DoWhileStatement.DoKeywordRole);
 
1641
                        WriteEmbeddedStatement(doWhileStatement.EmbeddedStatement);
 
1642
                        WriteKeyword(DoWhileStatement.WhileKeywordRole);
 
1643
                        Space(policy.SpaceBeforeWhileParentheses);
 
1644
                        LPar();
 
1645
                        Space(policy.SpacesWithinWhileParentheses);
 
1646
                        doWhileStatement.Condition.AcceptVisitor(this);
 
1647
                        Space(policy.SpacesWithinWhileParentheses);
 
1648
                        RPar();
 
1649
                        Semicolon();
 
1650
                        EndNode(doWhileStatement);
 
1651
                }
 
1652
                
 
1653
                public void VisitEmptyStatement(EmptyStatement emptyStatement)
 
1654
                {
 
1655
                        StartNode(emptyStatement);
 
1656
                        Semicolon();
 
1657
                        EndNode(emptyStatement);
 
1658
                }
 
1659
                
 
1660
                public void VisitExpressionStatement(ExpressionStatement expressionStatement)
 
1661
                {
 
1662
                        StartNode(expressionStatement);
 
1663
                        expressionStatement.Expression.AcceptVisitor(this);
 
1664
                        Semicolon();
 
1665
                        EndNode(expressionStatement);
 
1666
                }
 
1667
                
 
1668
                public void VisitFixedStatement(FixedStatement fixedStatement)
 
1669
                {
 
1670
                        StartNode(fixedStatement);
 
1671
                        WriteKeyword(FixedStatement.FixedKeywordRole);
 
1672
                        Space(policy.SpaceBeforeUsingParentheses);
 
1673
                        LPar();
 
1674
                        Space(policy.SpacesWithinUsingParentheses);
 
1675
                        fixedStatement.Type.AcceptVisitor(this);
 
1676
                        Space();
 
1677
                        WriteCommaSeparatedList(fixedStatement.Variables);
 
1678
                        Space(policy.SpacesWithinUsingParentheses);
 
1679
                        RPar();
 
1680
                        WriteEmbeddedStatement(fixedStatement.EmbeddedStatement);
 
1681
                        EndNode(fixedStatement);
 
1682
                }
 
1683
                
 
1684
                public void VisitForeachStatement(ForeachStatement foreachStatement)
 
1685
                {
 
1686
                        StartNode(foreachStatement);
 
1687
                        WriteKeyword(ForeachStatement.ForeachKeywordRole);
 
1688
                        Space(policy.SpaceBeforeForeachParentheses);
 
1689
                        LPar();
 
1690
                        Space(policy.SpacesWithinForeachParentheses);
 
1691
                        foreachStatement.VariableType.AcceptVisitor(this);
 
1692
                        Space();
 
1693
                        foreachStatement.VariableNameToken.AcceptVisitor(this);
 
1694
                        WriteKeyword(ForeachStatement.InKeywordRole);
 
1695
                        Space();
 
1696
                        foreachStatement.InExpression.AcceptVisitor(this);
 
1697
                        Space(policy.SpacesWithinForeachParentheses);
 
1698
                        RPar();
 
1699
                        WriteEmbeddedStatement(foreachStatement.EmbeddedStatement);
 
1700
                        EndNode(foreachStatement);
 
1701
                }
 
1702
                
 
1703
                public void VisitForStatement(ForStatement forStatement)
 
1704
                {
 
1705
                        StartNode(forStatement);
 
1706
                        WriteKeyword(ForStatement.ForKeywordRole);
 
1707
                        Space(policy.SpaceBeforeForParentheses);
 
1708
                        LPar();
 
1709
                        Space(policy.SpacesWithinForParentheses);
 
1710
                        
 
1711
                        WriteCommaSeparatedList(forStatement.Initializers);
 
1712
                        Space(policy.SpaceBeforeForSemicolon);
 
1713
                        WriteToken(Roles.Semicolon);
 
1714
                        Space(policy.SpaceAfterForSemicolon);
 
1715
                        
 
1716
                        forStatement.Condition.AcceptVisitor(this);
 
1717
                        Space(policy.SpaceBeforeForSemicolon);
 
1718
                        WriteToken(Roles.Semicolon);
 
1719
                        if (forStatement.Iterators.Any()) {
 
1720
                                Space(policy.SpaceAfterForSemicolon);
 
1721
                                WriteCommaSeparatedList(forStatement.Iterators);
 
1722
                        }
 
1723
                        
 
1724
                        Space(policy.SpacesWithinForParentheses);
 
1725
                        RPar();
 
1726
                        WriteEmbeddedStatement(forStatement.EmbeddedStatement);
 
1727
                        EndNode(forStatement);
 
1728
                }
 
1729
                
 
1730
                public void VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement)
 
1731
                {
 
1732
                        StartNode(gotoCaseStatement);
 
1733
                        WriteKeyword(GotoCaseStatement.GotoKeywordRole);
 
1734
                        WriteKeyword(GotoCaseStatement.CaseKeywordRole);
 
1735
                        Space();
 
1736
                        gotoCaseStatement.LabelExpression.AcceptVisitor(this);
 
1737
                        Semicolon();
 
1738
                        EndNode(gotoCaseStatement);
 
1739
                }
 
1740
                
 
1741
                public void VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement)
 
1742
                {
 
1743
                        StartNode(gotoDefaultStatement);
 
1744
                        WriteKeyword(GotoDefaultStatement.GotoKeywordRole);
 
1745
                        WriteKeyword(GotoDefaultStatement.DefaultKeywordRole);
 
1746
                        Semicolon();
 
1747
                        EndNode(gotoDefaultStatement);
 
1748
                }
 
1749
                
 
1750
                public void VisitGotoStatement(GotoStatement gotoStatement)
 
1751
                {
 
1752
                        StartNode(gotoStatement);
 
1753
                        WriteKeyword(GotoStatement.GotoKeywordRole);
 
1754
                        WriteIdentifier(gotoStatement.Label);
 
1755
                        Semicolon();
 
1756
                        EndNode(gotoStatement);
 
1757
                }
 
1758
                
 
1759
                public void VisitIfElseStatement(IfElseStatement ifElseStatement)
 
1760
                {
 
1761
                        StartNode(ifElseStatement);
 
1762
                        WriteKeyword(IfElseStatement.IfKeywordRole);
 
1763
                        Space(policy.SpaceBeforeIfParentheses);
 
1764
                        LPar();
 
1765
                        Space(policy.SpacesWithinIfParentheses);
 
1766
                        ifElseStatement.Condition.AcceptVisitor(this);
 
1767
                        Space(policy.SpacesWithinIfParentheses);
 
1768
                        RPar();
 
1769
                        WriteEmbeddedStatement(ifElseStatement.TrueStatement);
 
1770
                        if (!ifElseStatement.FalseStatement.IsNull) {
 
1771
                                WriteKeyword(IfElseStatement.ElseKeywordRole);
 
1772
                                WriteEmbeddedStatement(ifElseStatement.FalseStatement);
 
1773
                        }
 
1774
                        EndNode(ifElseStatement);
 
1775
                }
 
1776
                
 
1777
                public void VisitLabelStatement(LabelStatement labelStatement)
 
1778
                {
 
1779
                        StartNode(labelStatement);
 
1780
                        WriteIdentifier(labelStatement.Label);
 
1781
                        WriteToken(Roles.Colon);
 
1782
                        bool foundLabelledStatement = false;
 
1783
                        for (AstNode tmp = labelStatement.NextSibling; tmp != null; tmp = tmp.NextSibling) {
 
1784
                                if (tmp.Role == labelStatement.Role) {
 
1785
                                        foundLabelledStatement = true;
 
1786
                                }
 
1787
                        }
 
1788
                        if (!foundLabelledStatement) {
 
1789
                                // introduce an EmptyStatement so that the output becomes syntactically valid
 
1790
                                WriteToken(Roles.Semicolon);
 
1791
                        }
 
1792
                        NewLine();
 
1793
                        EndNode(labelStatement);
 
1794
                }
 
1795
                
 
1796
                public void VisitLockStatement(LockStatement lockStatement)
 
1797
                {
 
1798
                        StartNode(lockStatement);
 
1799
                        WriteKeyword(LockStatement.LockKeywordRole);
 
1800
                        Space(policy.SpaceBeforeLockParentheses);
 
1801
                        LPar();
 
1802
                        Space(policy.SpacesWithinLockParentheses);
 
1803
                        lockStatement.Expression.AcceptVisitor(this);
 
1804
                        Space(policy.SpacesWithinLockParentheses);
 
1805
                        RPar();
 
1806
                        WriteEmbeddedStatement(lockStatement.EmbeddedStatement);
 
1807
                        EndNode(lockStatement);
 
1808
                }
 
1809
                
 
1810
                public void VisitReturnStatement(ReturnStatement returnStatement)
 
1811
                {
 
1812
                        StartNode(returnStatement);
 
1813
                        WriteKeyword(ReturnStatement.ReturnKeywordRole);
 
1814
                        if (!returnStatement.Expression.IsNull) {
 
1815
                                Space();
 
1816
                                returnStatement.Expression.AcceptVisitor(this);
 
1817
                        }
 
1818
                        Semicolon();
 
1819
                        EndNode(returnStatement);
 
1820
                }
 
1821
                
 
1822
                public void VisitSwitchStatement(SwitchStatement switchStatement)
 
1823
                {
 
1824
                        StartNode(switchStatement);
 
1825
                        WriteKeyword(SwitchStatement.SwitchKeywordRole);
 
1826
                        Space(policy.SpaceBeforeSwitchParentheses);
 
1827
                        LPar();
 
1828
                        Space(policy.SpacesWithinSwitchParentheses);
 
1829
                        switchStatement.Expression.AcceptVisitor(this);
 
1830
                        Space(policy.SpacesWithinSwitchParentheses);
 
1831
                        RPar();
 
1832
                        OpenBrace(policy.StatementBraceStyle);
 
1833
                        if (!policy.IndentSwitchBody) {
 
1834
                                formatter.Unindent();
 
1835
                        }
 
1836
                        
 
1837
                        foreach (var section in switchStatement.SwitchSections) {
 
1838
                                section.AcceptVisitor(this);
 
1839
                        }
 
1840
                        
 
1841
                        if (!policy.IndentSwitchBody) {
 
1842
                                formatter.Indent();
 
1843
                        }
 
1844
                        CloseBrace(policy.StatementBraceStyle);
 
1845
                        NewLine();
 
1846
                        EndNode(switchStatement);
 
1847
                }
 
1848
                
 
1849
                public void VisitSwitchSection(SwitchSection switchSection)
 
1850
                {
 
1851
                        StartNode(switchSection);
 
1852
                        bool first = true;
 
1853
                        foreach (var label in switchSection.CaseLabels) {
 
1854
                                if (!first) {
 
1855
                                        NewLine();
 
1856
                                }
 
1857
                                label.AcceptVisitor(this);
 
1858
                                first = false;
 
1859
                        }
 
1860
                        bool isBlock = switchSection.Statements.Count == 1 && switchSection.Statements.Single() is BlockStatement;
 
1861
                        if (policy.IndentCaseBody && !isBlock) {
 
1862
                                formatter.Indent();
 
1863
                        }
 
1864
                        
 
1865
                        if (!isBlock)
 
1866
                                NewLine();
 
1867
                        
 
1868
                        foreach (var statement in switchSection.Statements) {
 
1869
                                statement.AcceptVisitor(this);
 
1870
                        }
 
1871
                        
 
1872
                        if (policy.IndentCaseBody && !isBlock) {
 
1873
                                formatter.Unindent();
 
1874
                        }
 
1875
                        
 
1876
                        EndNode(switchSection);
 
1877
                }
 
1878
                
 
1879
                public void VisitCaseLabel(CaseLabel caseLabel)
 
1880
                {
 
1881
                        StartNode(caseLabel);
 
1882
                        if (caseLabel.Expression.IsNull) {
 
1883
                                WriteKeyword(CaseLabel.DefaultKeywordRole);
 
1884
                        } else {
 
1885
                                WriteKeyword(CaseLabel.CaseKeywordRole);
 
1886
                                Space();
 
1887
                                caseLabel.Expression.AcceptVisitor(this);
 
1888
                        }
 
1889
                        WriteToken(Roles.Colon);
 
1890
                        EndNode(caseLabel);
 
1891
                }
 
1892
                
 
1893
                public void VisitThrowStatement(ThrowStatement throwStatement)
 
1894
                {
 
1895
                        StartNode(throwStatement);
 
1896
                        WriteKeyword(ThrowStatement.ThrowKeywordRole);
 
1897
                        if (!throwStatement.Expression.IsNull) {
 
1898
                                Space();
 
1899
                                throwStatement.Expression.AcceptVisitor(this);
 
1900
                        }
 
1901
                        Semicolon();
 
1902
                        EndNode(throwStatement);
 
1903
                }
 
1904
                
 
1905
                public void VisitTryCatchStatement(TryCatchStatement tryCatchStatement)
 
1906
                {
 
1907
                        StartNode(tryCatchStatement);
 
1908
                        WriteKeyword(TryCatchStatement.TryKeywordRole);
 
1909
                        tryCatchStatement.TryBlock.AcceptVisitor(this);
 
1910
                        foreach (var catchClause in tryCatchStatement.CatchClauses) {
 
1911
                                catchClause.AcceptVisitor(this);
 
1912
                        }
 
1913
                        if (!tryCatchStatement.FinallyBlock.IsNull) {
 
1914
                                WriteKeyword(TryCatchStatement.FinallyKeywordRole);
 
1915
                                tryCatchStatement.FinallyBlock.AcceptVisitor(this);
 
1916
                        }
 
1917
                        EndNode(tryCatchStatement);
 
1918
                }
 
1919
                
 
1920
                public void VisitCatchClause(CatchClause catchClause)
 
1921
                {
 
1922
                        StartNode(catchClause);
 
1923
                        WriteKeyword(CatchClause.CatchKeywordRole);
 
1924
                        if (!catchClause.Type.IsNull) {
 
1925
                                Space(policy.SpaceBeforeCatchParentheses);
 
1926
                                LPar();
 
1927
                                Space(policy.SpacesWithinCatchParentheses);
 
1928
                                catchClause.Type.AcceptVisitor(this);
 
1929
                                if (!string.IsNullOrEmpty(catchClause.VariableName)) {
 
1930
                                        Space();
 
1931
                                        catchClause.VariableNameToken.AcceptVisitor(this);
 
1932
                                }
 
1933
                                Space(policy.SpacesWithinCatchParentheses);
 
1934
                                RPar();
 
1935
                        }
 
1936
                        catchClause.Body.AcceptVisitor(this);
 
1937
                        EndNode(catchClause);
 
1938
                }
 
1939
                
 
1940
                public void VisitUncheckedStatement(UncheckedStatement uncheckedStatement)
 
1941
                {
 
1942
                        StartNode(uncheckedStatement);
 
1943
                        WriteKeyword(UncheckedStatement.UncheckedKeywordRole);
 
1944
                        uncheckedStatement.Body.AcceptVisitor(this);
 
1945
                        EndNode(uncheckedStatement);
 
1946
                }
 
1947
                
 
1948
                public void VisitUnsafeStatement(UnsafeStatement unsafeStatement)
 
1949
                {
 
1950
                        StartNode(unsafeStatement);
 
1951
                        WriteKeyword(UnsafeStatement.UnsafeKeywordRole);
 
1952
                        unsafeStatement.Body.AcceptVisitor(this);
 
1953
                        EndNode(unsafeStatement);
 
1954
                }
 
1955
                
 
1956
                public void VisitUsingStatement(UsingStatement usingStatement)
 
1957
                {
 
1958
                        StartNode(usingStatement);
 
1959
                        WriteKeyword(UsingStatement.UsingKeywordRole);
 
1960
                        Space(policy.SpaceBeforeUsingParentheses);
 
1961
                        LPar();
 
1962
                        Space(policy.SpacesWithinUsingParentheses);
 
1963
                        
 
1964
                        usingStatement.ResourceAcquisition.AcceptVisitor(this);
 
1965
                        
 
1966
                        Space(policy.SpacesWithinUsingParentheses);
 
1967
                        RPar();
 
1968
                        
 
1969
                        WriteEmbeddedStatement(usingStatement.EmbeddedStatement);
 
1970
                        
 
1971
                        EndNode(usingStatement);
 
1972
                }
 
1973
                
 
1974
                public void VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement)
 
1975
                {
 
1976
                        StartNode(variableDeclarationStatement);
 
1977
                        WriteModifiers(variableDeclarationStatement.GetChildrenByRole(VariableDeclarationStatement.ModifierRole));
 
1978
                        variableDeclarationStatement.Type.AcceptVisitor(this);
 
1979
                        Space();
 
1980
                        WriteCommaSeparatedList(variableDeclarationStatement.Variables);
 
1981
                        Semicolon();
 
1982
                        EndNode(variableDeclarationStatement);
 
1983
                }
 
1984
                
 
1985
                public void VisitWhileStatement(WhileStatement whileStatement)
 
1986
                {
 
1987
                        StartNode(whileStatement);
 
1988
                        WriteKeyword(WhileStatement.WhileKeywordRole);
 
1989
                        Space(policy.SpaceBeforeWhileParentheses);
 
1990
                        LPar();
 
1991
                        Space(policy.SpacesWithinWhileParentheses);
 
1992
                        whileStatement.Condition.AcceptVisitor(this);
 
1993
                        Space(policy.SpacesWithinWhileParentheses);
 
1994
                        RPar();
 
1995
                        WriteEmbeddedStatement(whileStatement.EmbeddedStatement);
 
1996
                        EndNode(whileStatement);
 
1997
                }
 
1998
                
 
1999
                public void VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement)
 
2000
                {
 
2001
                        StartNode(yieldBreakStatement);
 
2002
                        WriteKeyword(YieldBreakStatement.YieldKeywordRole);
 
2003
                        WriteKeyword(YieldBreakStatement.BreakKeywordRole);
 
2004
                        Semicolon();
 
2005
                        EndNode(yieldBreakStatement);
 
2006
                }
 
2007
                
 
2008
                public void VisitYieldReturnStatement(YieldReturnStatement yieldReturnStatement)
 
2009
                {
 
2010
                        StartNode(yieldReturnStatement);
 
2011
                        WriteKeyword(YieldReturnStatement.YieldKeywordRole);
 
2012
                        WriteKeyword(YieldReturnStatement.ReturnKeywordRole);
 
2013
                        Space();
 
2014
                        yieldReturnStatement.Expression.AcceptVisitor(this);
 
2015
                        Semicolon();
 
2016
                        EndNode(yieldReturnStatement);
 
2017
                }
 
2018
 
 
2019
                #endregion
 
2020
                
 
2021
                #region TypeMembers
 
2022
                public void VisitAccessor(Accessor accessor)
 
2023
                {
 
2024
                        StartNode(accessor);
 
2025
                        WriteAttributes(accessor.Attributes);
 
2026
                        WriteModifiers(accessor.ModifierTokens);
 
2027
                        if (accessor.Role == PropertyDeclaration.GetterRole) {
 
2028
                                WriteKeyword("get");
 
2029
                        } else if (accessor.Role == PropertyDeclaration.SetterRole) {
 
2030
                                WriteKeyword("set");
 
2031
                        } else if (accessor.Role == CustomEventDeclaration.AddAccessorRole) {
 
2032
                                WriteKeyword("add");
 
2033
                        } else if (accessor.Role == CustomEventDeclaration.RemoveAccessorRole) {
 
2034
                                WriteKeyword("remove");
 
2035
                        }
 
2036
                        WriteMethodBody(accessor.Body);
 
2037
                        EndNode(accessor);
 
2038
                }
 
2039
                
 
2040
                public void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
 
2041
                {
 
2042
                        StartNode(constructorDeclaration);
 
2043
                        WriteAttributes(constructorDeclaration.Attributes);
 
2044
                        WriteModifiers(constructorDeclaration.ModifierTokens);
 
2045
                        TypeDeclaration type = constructorDeclaration.Parent as TypeDeclaration;
 
2046
                        var nameToken = constructorDeclaration.NameToken;
 
2047
                        if (!nameToken.IsNull)
 
2048
                                StartNode(nameToken);
 
2049
                        WriteIdentifier(type != null ? type.Name : constructorDeclaration.Name);
 
2050
                        if (!nameToken.IsNull)
 
2051
                                EndNode(nameToken);
 
2052
                        Space(policy.SpaceBeforeConstructorDeclarationParentheses);
 
2053
                        WriteCommaSeparatedListInParenthesis(constructorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
 
2054
                        if (!constructorDeclaration.Initializer.IsNull) {
 
2055
                                Space();
 
2056
                                constructorDeclaration.Initializer.AcceptVisitor(this);
 
2057
                        }
 
2058
                        WriteMethodBody(constructorDeclaration.Body);
 
2059
                        EndNode(constructorDeclaration);
 
2060
                }
 
2061
                
 
2062
                public void VisitConstructorInitializer(ConstructorInitializer constructorInitializer)
 
2063
                {
 
2064
                        StartNode(constructorInitializer);
 
2065
                        WriteToken(Roles.Colon);
 
2066
                        Space();
 
2067
                        if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.This) {
 
2068
                                WriteKeyword(ConstructorInitializer.ThisKeywordRole);
 
2069
                        } else {
 
2070
                                WriteKeyword(ConstructorInitializer.BaseKeywordRole);
 
2071
                        }
 
2072
                        Space(policy.SpaceBeforeMethodCallParentheses);
 
2073
                        WriteCommaSeparatedListInParenthesis(constructorInitializer.Arguments, policy.SpaceWithinMethodCallParentheses);
 
2074
                        EndNode(constructorInitializer);
 
2075
                }
 
2076
                
 
2077
                public void VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration)
 
2078
                {
 
2079
                        StartNode(destructorDeclaration);
 
2080
                        WriteAttributes(destructorDeclaration.Attributes);
 
2081
                        WriteModifiers(destructorDeclaration.ModifierTokens);
 
2082
                        WriteToken(DestructorDeclaration.TildeRole);
 
2083
                        TypeDeclaration type = destructorDeclaration.Parent as TypeDeclaration;
 
2084
                        var nameToken = destructorDeclaration.NameToken;
 
2085
                        if (!nameToken.IsNull)
 
2086
                                StartNode(nameToken);
 
2087
                        WriteIdentifier(type != null ? type.Name : destructorDeclaration.Name);
 
2088
                        if (!nameToken.IsNull)
 
2089
                                EndNode(nameToken);
 
2090
                        Space(policy.SpaceBeforeConstructorDeclarationParentheses);
 
2091
                        LPar();
 
2092
                        RPar();
 
2093
                        WriteMethodBody(destructorDeclaration.Body);
 
2094
                        EndNode(destructorDeclaration);
 
2095
                }
 
2096
                
 
2097
                public void VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration)
 
2098
                {
 
2099
                        StartNode(enumMemberDeclaration);
 
2100
                        WriteAttributes(enumMemberDeclaration.Attributes);
 
2101
                        WriteModifiers(enumMemberDeclaration.ModifierTokens);
 
2102
                        enumMemberDeclaration.NameToken.AcceptVisitor(this);
 
2103
                        if (!enumMemberDeclaration.Initializer.IsNull) {
 
2104
                                Space(policy.SpaceAroundAssignment);
 
2105
                                WriteToken(Roles.Assign);
 
2106
                                Space(policy.SpaceAroundAssignment);
 
2107
                                enumMemberDeclaration.Initializer.AcceptVisitor(this);
 
2108
                        }
 
2109
                        EndNode(enumMemberDeclaration);
 
2110
                }
 
2111
                
 
2112
                public void VisitEventDeclaration(EventDeclaration eventDeclaration)
 
2113
                {
 
2114
                        StartNode(eventDeclaration);
 
2115
                        WriteAttributes(eventDeclaration.Attributes);
 
2116
                        WriteModifiers(eventDeclaration.ModifierTokens);
 
2117
                        WriteKeyword(EventDeclaration.EventKeywordRole);
 
2118
                        eventDeclaration.ReturnType.AcceptVisitor(this);
 
2119
                        Space();
 
2120
                        WriteCommaSeparatedList(eventDeclaration.Variables);
 
2121
                        Semicolon();
 
2122
                        EndNode(eventDeclaration);
 
2123
                }
 
2124
                
 
2125
                public void VisitCustomEventDeclaration(CustomEventDeclaration customEventDeclaration)
 
2126
                {
 
2127
                        StartNode(customEventDeclaration);
 
2128
                        WriteAttributes(customEventDeclaration.Attributes);
 
2129
                        WriteModifiers(customEventDeclaration.ModifierTokens);
 
2130
                        WriteKeyword(CustomEventDeclaration.EventKeywordRole);
 
2131
                        customEventDeclaration.ReturnType.AcceptVisitor(this);
 
2132
                        Space();
 
2133
                        WritePrivateImplementationType(customEventDeclaration.PrivateImplementationType);
 
2134
                        customEventDeclaration.NameToken.AcceptVisitor(this);
 
2135
                        OpenBrace(policy.EventBraceStyle);
 
2136
                        // output add/remove in their original order
 
2137
                        foreach (AstNode node in customEventDeclaration.Children) {
 
2138
                                if (node.Role == CustomEventDeclaration.AddAccessorRole || node.Role == CustomEventDeclaration.RemoveAccessorRole) {
 
2139
                                        node.AcceptVisitor(this);
 
2140
                                }
 
2141
                        }
 
2142
                        CloseBrace(policy.EventBraceStyle);
 
2143
                        NewLine();
 
2144
                        EndNode(customEventDeclaration);
 
2145
                }
 
2146
                
 
2147
                public void VisitFieldDeclaration(FieldDeclaration fieldDeclaration)
 
2148
                {
 
2149
                        StartNode(fieldDeclaration);
 
2150
                        WriteAttributes(fieldDeclaration.Attributes);
 
2151
                        WriteModifiers(fieldDeclaration.ModifierTokens);
 
2152
                        fieldDeclaration.ReturnType.AcceptVisitor(this);
 
2153
                        Space();
 
2154
                        WriteCommaSeparatedList(fieldDeclaration.Variables);
 
2155
                        Semicolon();
 
2156
                        EndNode(fieldDeclaration);
 
2157
                }
 
2158
                
 
2159
                public void VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration)
 
2160
                {
 
2161
                        StartNode(fixedFieldDeclaration);
 
2162
                        WriteAttributes(fixedFieldDeclaration.Attributes);
 
2163
                        WriteModifiers(fixedFieldDeclaration.ModifierTokens);
 
2164
                        WriteKeyword(FixedFieldDeclaration.FixedKeywordRole);
 
2165
                        Space();
 
2166
                        fixedFieldDeclaration.ReturnType.AcceptVisitor(this);
 
2167
                        Space();
 
2168
                        WriteCommaSeparatedList(fixedFieldDeclaration.Variables);
 
2169
                        Semicolon();
 
2170
                        EndNode(fixedFieldDeclaration);
 
2171
                }
 
2172
                
 
2173
                public void VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer)
 
2174
                {
 
2175
                        StartNode(fixedVariableInitializer);
 
2176
                        fixedVariableInitializer.NameToken.AcceptVisitor(this);
 
2177
                        if (!fixedVariableInitializer.CountExpression.IsNull) {
 
2178
                                WriteToken(Roles.LBracket);
 
2179
                                Space(policy.SpacesWithinBrackets);
 
2180
                                fixedVariableInitializer.CountExpression.AcceptVisitor(this);
 
2181
                                Space(policy.SpacesWithinBrackets);
 
2182
                                WriteToken(Roles.RBracket);
 
2183
                        }
 
2184
                        EndNode(fixedVariableInitializer);
 
2185
                }
 
2186
                
 
2187
                public void VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
 
2188
                {
 
2189
                        StartNode(indexerDeclaration);
 
2190
                        WriteAttributes(indexerDeclaration.Attributes);
 
2191
                        WriteModifiers(indexerDeclaration.ModifierTokens);
 
2192
                        indexerDeclaration.ReturnType.AcceptVisitor(this);
 
2193
                        Space();
 
2194
                        WritePrivateImplementationType(indexerDeclaration.PrivateImplementationType);
 
2195
                        WriteKeyword(IndexerDeclaration.ThisKeywordRole);
 
2196
                        Space(policy.SpaceBeforeMethodDeclarationParentheses);
 
2197
                        WriteCommaSeparatedListInBrackets(indexerDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
 
2198
                        OpenBrace(policy.PropertyBraceStyle);
 
2199
                        // output get/set in their original order
 
2200
                        foreach (AstNode node in indexerDeclaration.Children) {
 
2201
                                if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) {
 
2202
                                        node.AcceptVisitor(this);
 
2203
                                }
 
2204
                        }
 
2205
                        CloseBrace(policy.PropertyBraceStyle);
 
2206
                        NewLine();
 
2207
                        EndNode(indexerDeclaration);
 
2208
                }
 
2209
                
 
2210
                public void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
 
2211
                {
 
2212
                        StartNode(methodDeclaration);
 
2213
                        WriteAttributes(methodDeclaration.Attributes);
 
2214
                        WriteModifiers(methodDeclaration.ModifierTokens);
 
2215
                        methodDeclaration.ReturnType.AcceptVisitor(this);
 
2216
                        Space();
 
2217
                        WritePrivateImplementationType(methodDeclaration.PrivateImplementationType);
 
2218
                        methodDeclaration.NameToken.AcceptVisitor(this);
 
2219
                        WriteTypeParameters(methodDeclaration.TypeParameters);
 
2220
                        Space(policy.SpaceBeforeMethodDeclarationParentheses);
 
2221
                        WriteCommaSeparatedListInParenthesis(methodDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
 
2222
                        foreach (Constraint constraint in methodDeclaration.Constraints) {
 
2223
                                constraint.AcceptVisitor(this);
 
2224
                        }
 
2225
                        WriteMethodBody(methodDeclaration.Body);
 
2226
                        EndNode(methodDeclaration);
 
2227
                }
 
2228
                
 
2229
                public void VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration)
 
2230
                {
 
2231
                        StartNode(operatorDeclaration);
 
2232
                        WriteAttributes(operatorDeclaration.Attributes);
 
2233
                        WriteModifiers(operatorDeclaration.ModifierTokens);
 
2234
                        if (operatorDeclaration.OperatorType == OperatorType.Explicit) {
 
2235
                                WriteKeyword(OperatorDeclaration.ExplicitRole);
 
2236
                        } else if (operatorDeclaration.OperatorType == OperatorType.Implicit) {
 
2237
                                WriteKeyword(OperatorDeclaration.ImplicitRole);
 
2238
                        } else {
 
2239
                                operatorDeclaration.ReturnType.AcceptVisitor(this);
 
2240
                        }
 
2241
                        WriteKeyword(OperatorDeclaration.OperatorKeywordRole);
 
2242
                        Space();
 
2243
                        if (operatorDeclaration.OperatorType == OperatorType.Explicit
 
2244
                                || operatorDeclaration.OperatorType == OperatorType.Implicit) {
 
2245
                                operatorDeclaration.ReturnType.AcceptVisitor(this);
 
2246
                        } else {
 
2247
                                WriteToken(OperatorDeclaration.GetToken(operatorDeclaration.OperatorType), OperatorDeclaration.GetRole(operatorDeclaration.OperatorType));
 
2248
                        }
 
2249
                        Space(policy.SpaceBeforeMethodDeclarationParentheses);
 
2250
                        WriteCommaSeparatedListInParenthesis(operatorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
 
2251
                        WriteMethodBody(operatorDeclaration.Body);
 
2252
                        EndNode(operatorDeclaration);
 
2253
                }
 
2254
                
 
2255
                public void VisitParameterDeclaration(ParameterDeclaration parameterDeclaration)
 
2256
                {
 
2257
                        StartNode(parameterDeclaration);
 
2258
                        WriteAttributes(parameterDeclaration.Attributes);
 
2259
                        switch (parameterDeclaration.ParameterModifier) {
 
2260
                                case ParameterModifier.Ref:
 
2261
                                        WriteKeyword(ParameterDeclaration.RefModifierRole);
 
2262
                                        break;
 
2263
                                case ParameterModifier.Out:
 
2264
                                        WriteKeyword(ParameterDeclaration.OutModifierRole);
 
2265
                                        break;
 
2266
                                case ParameterModifier.Params:
 
2267
                                        WriteKeyword(ParameterDeclaration.ParamsModifierRole);
 
2268
                                        break;
 
2269
                                case ParameterModifier.This:
 
2270
                                        WriteKeyword(ParameterDeclaration.ThisModifierRole);
 
2271
                                        break;
 
2272
                        }
 
2273
                        parameterDeclaration.Type.AcceptVisitor(this);
 
2274
                        if (!parameterDeclaration.Type.IsNull && !string.IsNullOrEmpty(parameterDeclaration.Name)) {
 
2275
                                Space();
 
2276
                        }
 
2277
                        if (!string.IsNullOrEmpty(parameterDeclaration.Name)) {
 
2278
                                parameterDeclaration.NameToken.AcceptVisitor(this);
 
2279
                        }
 
2280
                        if (!parameterDeclaration.DefaultExpression.IsNull) {
 
2281
                                Space(policy.SpaceAroundAssignment);
 
2282
                                WriteToken(Roles.Assign);
 
2283
                                Space(policy.SpaceAroundAssignment);
 
2284
                                parameterDeclaration.DefaultExpression.AcceptVisitor(this);
 
2285
                        }
 
2286
                        EndNode(parameterDeclaration);
 
2287
                }
 
2288
                
 
2289
                public void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
 
2290
                {
 
2291
                        StartNode(propertyDeclaration);
 
2292
                        WriteAttributes(propertyDeclaration.Attributes);
 
2293
                        WriteModifiers(propertyDeclaration.ModifierTokens);
 
2294
                        propertyDeclaration.ReturnType.AcceptVisitor(this);
 
2295
                        Space();
 
2296
                        WritePrivateImplementationType(propertyDeclaration.PrivateImplementationType);
 
2297
                        propertyDeclaration.NameToken.AcceptVisitor(this);
 
2298
                        OpenBrace(policy.PropertyBraceStyle);
 
2299
                        // output get/set in their original order
 
2300
                        foreach (AstNode node in propertyDeclaration.Children) {
 
2301
                                if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) {
 
2302
                                        node.AcceptVisitor(this);
 
2303
                                }
 
2304
                        }
 
2305
                        CloseBrace(policy.PropertyBraceStyle);
 
2306
                        NewLine();
 
2307
                        EndNode(propertyDeclaration);
 
2308
                }
 
2309
 
 
2310
                #endregion
 
2311
                
 
2312
                #region Other nodes
 
2313
                public void VisitVariableInitializer(VariableInitializer variableInitializer)
 
2314
                {
 
2315
                        StartNode(variableInitializer);
 
2316
                        variableInitializer.NameToken.AcceptVisitor(this);
 
2317
                        if (!variableInitializer.Initializer.IsNull) {
 
2318
                                Space(policy.SpaceAroundAssignment);
 
2319
                                WriteToken(Roles.Assign);
 
2320
                                Space(policy.SpaceAroundAssignment);
 
2321
                                variableInitializer.Initializer.AcceptVisitor(this);
 
2322
                        }
 
2323
                        EndNode(variableInitializer);
 
2324
                }
 
2325
                
 
2326
                public void VisitSyntaxTree(SyntaxTree syntaxTree)
 
2327
                {
 
2328
                        // don't do node tracking as we visit all children directly
 
2329
                        foreach (AstNode node in syntaxTree.Children) {
 
2330
                                node.AcceptVisitor(this);
 
2331
                        }
 
2332
                }
 
2333
                
 
2334
                public void VisitSimpleType(SimpleType simpleType)
 
2335
                {
 
2336
                        StartNode(simpleType);
 
2337
                        WriteIdentifier(simpleType.Identifier);
 
2338
                        WriteTypeArguments(simpleType.TypeArguments);
 
2339
                        EndNode(simpleType);
 
2340
                }
 
2341
                
 
2342
                public void VisitMemberType(MemberType memberType)
 
2343
                {
 
2344
                        StartNode(memberType);
 
2345
                        memberType.Target.AcceptVisitor(this);
 
2346
                        if (memberType.IsDoubleColon) {
 
2347
                                WriteToken(Roles.DoubleColon);
 
2348
                        } else {
 
2349
                                WriteToken(Roles.Dot);
 
2350
                        }
 
2351
                        WriteIdentifier(memberType.MemberName);
 
2352
                        WriteTypeArguments(memberType.TypeArguments);
 
2353
                        EndNode(memberType);
 
2354
                }
 
2355
                
 
2356
                public void VisitComposedType(ComposedType composedType)
 
2357
                {
 
2358
                        StartNode(composedType);
 
2359
                        composedType.BaseType.AcceptVisitor(this);
 
2360
                        if (composedType.HasNullableSpecifier) {
 
2361
                                WriteToken(ComposedType.NullableRole);
 
2362
                        }
 
2363
                        for (int i = 0; i < composedType.PointerRank; i++) {
 
2364
                                WriteToken(ComposedType.PointerRole);
 
2365
                        }
 
2366
                        foreach (var node in composedType.ArraySpecifiers) {
 
2367
                                node.AcceptVisitor(this);
 
2368
                        }
 
2369
                        EndNode(composedType);
 
2370
                }
 
2371
                
 
2372
                public void VisitArraySpecifier(ArraySpecifier arraySpecifier)
 
2373
                {
 
2374
                        StartNode(arraySpecifier);
 
2375
                        WriteToken(Roles.LBracket);
 
2376
                        foreach (var comma in arraySpecifier.GetChildrenByRole(Roles.Comma)) {
 
2377
                                WriteSpecialsUpToNode(comma);
 
2378
                                formatter.WriteToken(",");
 
2379
                                lastWritten = LastWritten.Other;
 
2380
                        }
 
2381
                        WriteToken(Roles.RBracket);
 
2382
                        EndNode(arraySpecifier);
 
2383
                }
 
2384
                
 
2385
                public void VisitPrimitiveType(PrimitiveType primitiveType)
 
2386
                {
 
2387
                        StartNode(primitiveType);
 
2388
                        WriteKeyword(primitiveType.Keyword);
 
2389
                        if (primitiveType.Keyword == "new") {
 
2390
                                // new() constraint
 
2391
                                LPar();
 
2392
                                RPar();
 
2393
                        }
 
2394
                        EndNode(primitiveType);
 
2395
                }
 
2396
                
 
2397
                public void VisitComment(Comment comment)
 
2398
                {
 
2399
                        if (lastWritten == LastWritten.Division) {
 
2400
                                // When there's a comment starting after a division operator
 
2401
                                // "1.0 / /*comment*/a", then we need to insert a space in front of the comment.
 
2402
                                formatter.Space();
 
2403
                        }
 
2404
                        formatter.StartNode(comment);
 
2405
                        formatter.WriteComment(comment.CommentType, comment.Content);
 
2406
                        formatter.EndNode(comment);
 
2407
                        lastWritten = LastWritten.Whitespace;
 
2408
                }
 
2409
 
 
2410
                public void VisitNewLine(NewLineNode newLineNode)
 
2411
                {
 
2412
//                      formatter.StartNode(newLineNode);
 
2413
//                      formatter.NewLine();
 
2414
//                      formatter.EndNode(newLineNode);
 
2415
                }
 
2416
 
 
2417
                public void VisitWhitespace(WhitespaceNode whitespaceNode)
 
2418
                {
 
2419
                        // unused
 
2420
                }
 
2421
 
 
2422
                public void VisitText(TextNode textNode)
 
2423
                {
 
2424
                        // unused
 
2425
                }
 
2426
 
 
2427
                public void VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective)
 
2428
                {
 
2429
                        formatter.StartNode(preProcessorDirective);
 
2430
                        formatter.WritePreProcessorDirective(preProcessorDirective.Type, preProcessorDirective.Argument);
 
2431
                        formatter.EndNode(preProcessorDirective);
 
2432
                        lastWritten = LastWritten.Whitespace;
 
2433
                }
 
2434
                
 
2435
                public void VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration)
 
2436
                {
 
2437
                        StartNode(typeParameterDeclaration);
 
2438
                        WriteAttributes(typeParameterDeclaration.Attributes);
 
2439
                        switch (typeParameterDeclaration.Variance) {
 
2440
                                case VarianceModifier.Invariant:
 
2441
                                        break;
 
2442
                                case VarianceModifier.Covariant:
 
2443
                                        WriteKeyword(TypeParameterDeclaration.OutVarianceKeywordRole);
 
2444
                                        break;
 
2445
                                case VarianceModifier.Contravariant:
 
2446
                                        WriteKeyword(TypeParameterDeclaration.InVarianceKeywordRole);
 
2447
                                        break;
 
2448
                                default:
 
2449
                                        throw new NotSupportedException ("Invalid value for VarianceModifier");
 
2450
                        }
 
2451
                        typeParameterDeclaration.NameToken.AcceptVisitor(this);
 
2452
                        EndNode(typeParameterDeclaration);
 
2453
                }
 
2454
                
 
2455
                public void VisitConstraint(Constraint constraint)
 
2456
                {
 
2457
                        StartNode(constraint);
 
2458
                        Space();
 
2459
                        WriteKeyword(Roles.WhereKeyword);
 
2460
                        WriteIdentifier(constraint.TypeParameter.Identifier);
 
2461
                        Space();
 
2462
                        WriteToken(Roles.Colon);
 
2463
                        Space();
 
2464
                        WriteCommaSeparatedList(constraint.BaseTypes);
 
2465
                        EndNode(constraint);
 
2466
                }
 
2467
                
 
2468
                public void VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode)
 
2469
                {
 
2470
                        CSharpModifierToken mod = cSharpTokenNode as CSharpModifierToken;
 
2471
                        if (mod != null) {
 
2472
                                StartNode(mod);
 
2473
                                WriteKeyword(CSharpModifierToken.GetModifierName(mod.Modifier));
 
2474
                                EndNode(mod);
 
2475
                        } else {
 
2476
                                throw new NotSupportedException ("Should never visit individual tokens");
 
2477
                        }
 
2478
                }
 
2479
                
 
2480
                public void VisitIdentifier(Identifier identifier)
 
2481
                {
 
2482
                        StartNode(identifier);
 
2483
                        WriteIdentifier(identifier.Name);
 
2484
                        EndNode(identifier);
 
2485
                }
 
2486
 
 
2487
                #endregion
 
2488
                
 
2489
                #region Pattern Nodes
 
2490
                public void VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern)
 
2491
                {
 
2492
                        StartNode(placeholder);
 
2493
                        VisitNodeInPattern(pattern);
 
2494
                        EndNode(placeholder);
 
2495
                }
 
2496
                
 
2497
                void VisitAnyNode(AnyNode anyNode)
 
2498
                {
 
2499
                        if (!string.IsNullOrEmpty(anyNode.GroupName)) {
 
2500
                                WriteIdentifier(anyNode.GroupName);
 
2501
                                WriteToken(Roles.Colon);
 
2502
                        }
 
2503
                }
 
2504
                
 
2505
                void VisitBackreference(Backreference backreference)
 
2506
                {
 
2507
                        WriteKeyword("backreference");
 
2508
                        LPar();
 
2509
                        WriteIdentifier(backreference.ReferencedGroupName);
 
2510
                        RPar();
 
2511
                }
 
2512
                
 
2513
                void VisitIdentifierExpressionBackreference(IdentifierExpressionBackreference identifierExpressionBackreference)
 
2514
                {
 
2515
                        WriteKeyword("identifierBackreference");
 
2516
                        LPar();
 
2517
                        WriteIdentifier(identifierExpressionBackreference.ReferencedGroupName);
 
2518
                        RPar();
 
2519
                }
 
2520
                
 
2521
                void VisitChoice(Choice choice)
 
2522
                {
 
2523
                        WriteKeyword("choice");
 
2524
                        Space();
 
2525
                        LPar();
 
2526
                        NewLine();
 
2527
                        formatter.Indent();
 
2528
                        foreach (INode alternative in choice) {
 
2529
                                VisitNodeInPattern(alternative);
 
2530
                                if (alternative != choice.Last()) {
 
2531
                                        WriteToken(Roles.Comma);
 
2532
                                }
 
2533
                                NewLine();
 
2534
                        }
 
2535
                        formatter.Unindent();
 
2536
                        RPar();
 
2537
                }
 
2538
                
 
2539
                void VisitNamedNode(NamedNode namedNode)
 
2540
                {
 
2541
                        if (!string.IsNullOrEmpty(namedNode.GroupName)) {
 
2542
                                WriteIdentifier(namedNode.GroupName);
 
2543
                                WriteToken(Roles.Colon);
 
2544
                        }
 
2545
                        VisitNodeInPattern(namedNode.ChildNode);
 
2546
                }
 
2547
                
 
2548
                void VisitRepeat(Repeat repeat)
 
2549
                {
 
2550
                        WriteKeyword("repeat");
 
2551
                        LPar();
 
2552
                        if (repeat.MinCount != 0 || repeat.MaxCount != int.MaxValue) {
 
2553
                                WriteIdentifier(repeat.MinCount.ToString());
 
2554
                                WriteToken(Roles.Comma);
 
2555
                                WriteIdentifier(repeat.MaxCount.ToString());
 
2556
                                WriteToken(Roles.Comma);
 
2557
                        }
 
2558
                        VisitNodeInPattern(repeat.ChildNode);
 
2559
                        RPar();
 
2560
                }
 
2561
                
 
2562
                void VisitOptionalNode(OptionalNode optionalNode)
 
2563
                {
 
2564
                        WriteKeyword("optional");
 
2565
                        LPar();
 
2566
                        VisitNodeInPattern(optionalNode.ChildNode);
 
2567
                        RPar();
 
2568
                }
 
2569
                
 
2570
                void VisitNodeInPattern(INode childNode)
 
2571
                {
 
2572
                        if (childNode is AstNode) {
 
2573
                                ((AstNode)childNode).AcceptVisitor(this);
 
2574
                        } else if (childNode is IdentifierExpressionBackreference) {
 
2575
                                VisitIdentifierExpressionBackreference((IdentifierExpressionBackreference)childNode);
 
2576
                        } else if (childNode is Choice) {
 
2577
                                VisitChoice((Choice)childNode);
 
2578
                        } else if (childNode is AnyNode) {
 
2579
                                VisitAnyNode((AnyNode)childNode);
 
2580
                        } else if (childNode is Backreference) {
 
2581
                                VisitBackreference((Backreference)childNode);
 
2582
                        } else if (childNode is NamedNode) {
 
2583
                                VisitNamedNode((NamedNode)childNode);
 
2584
                        } else if (childNode is OptionalNode) {
 
2585
                                VisitOptionalNode((OptionalNode)childNode);
 
2586
                        } else if (childNode is Repeat) {
 
2587
                                VisitRepeat((Repeat)childNode);
 
2588
                        } else {
 
2589
                                WritePrimitiveValue(childNode);
 
2590
                        }
 
2591
                }
 
2592
                #endregion
 
2593
                
 
2594
                #region Documentation Reference
 
2595
                public void VisitDocumentationReference(DocumentationReference documentationReference)
 
2596
                {
 
2597
                        StartNode(documentationReference);
 
2598
                        if (!documentationReference.DeclaringType.IsNull) {
 
2599
                                documentationReference.DeclaringType.AcceptVisitor(this);
 
2600
                                if (documentationReference.EntityType != EntityType.TypeDefinition) {
 
2601
                                        WriteToken(Roles.Dot);
 
2602
                                }
 
2603
                        }
 
2604
                        switch (documentationReference.EntityType) {
 
2605
                                case EntityType.TypeDefinition:
 
2606
                                        // we already printed the DeclaringType
 
2607
                                        break;
 
2608
                                case EntityType.Indexer:
 
2609
                                        WriteKeyword(IndexerDeclaration.ThisKeywordRole);
 
2610
                                        break;
 
2611
                                case EntityType.Operator:
 
2612
                                        var opType = documentationReference.OperatorType;
 
2613
                                        if (opType == OperatorType.Explicit) {
 
2614
                                                WriteKeyword(OperatorDeclaration.ExplicitRole);
 
2615
                                        } else if (opType == OperatorType.Implicit) {
 
2616
                                                WriteKeyword(OperatorDeclaration.ImplicitRole);
 
2617
                                        }
 
2618
                                        WriteKeyword(OperatorDeclaration.OperatorKeywordRole);
 
2619
                                        Space();
 
2620
                                        if (opType == OperatorType.Explicit || opType == OperatorType.Implicit) {
 
2621
                                                documentationReference.ConversionOperatorReturnType.AcceptVisitor(this);
 
2622
                                        } else {
 
2623
                                                WriteToken(OperatorDeclaration.GetToken(opType), OperatorDeclaration.GetRole(opType));
 
2624
                                        }
 
2625
                                        break;
 
2626
                                default:
 
2627
                                        WriteIdentifier(documentationReference.MemberName);
 
2628
                                        break;
 
2629
                        }
 
2630
                        WriteTypeArguments(documentationReference.TypeArguments);
 
2631
                        if (documentationReference.HasParameterList) {
 
2632
                                Space(policy.SpaceBeforeMethodDeclarationParentheses);
 
2633
                                if (documentationReference.EntityType == EntityType.Indexer) {
 
2634
                                        WriteCommaSeparatedListInBrackets(documentationReference.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
 
2635
                                } else {
 
2636
                                        WriteCommaSeparatedListInParenthesis(documentationReference.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
 
2637
                                }
 
2638
                        }
 
2639
                        EndNode(documentationReference);
 
2640
                }
 
2641
                #endregion
 
2642
        }
 
2643
}