PageRenderTime 76ms CodeModel.GetById 20ms app.highlight 44ms RepoModel.GetById 2ms app.codeStats 0ms

/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs

http://github.com/icsharpcode/ILSpy
C# | 2401 lines | 2116 code | 206 blank | 79 comment | 303 complexity | ca4679c15229cbd6d703f5311952c450 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
   2// 
   3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
   4// software and associated documentation files (the "Software"), to deal in the Software
   5// without restriction, including without limitation the rights to use, copy, modify, merge,
   6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
   7// to whom the Software is furnished to do so, subject to the following conditions:
   8// 
   9// The above copyright notice and this permission notice shall be included in all copies or
  10// substantial portions of the Software.
  11// 
  12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
  15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  17// DEALINGS IN THE SOFTWARE.
  18using System;
  19using System.Collections.Generic;
  20using System.Diagnostics;
  21using System.Globalization;
  22using System.IO;
  23using System.Linq;
  24using System.Text;
  25using System.Threading.Tasks;
  26using ICSharpCode.NRefactory.PatternMatching;
  27using ICSharpCode.NRefactory.TypeSystem;
  28using ICSharpCode.NRefactory.CSharp;
  29
  30namespace ICSharpCode.NRefactory.CSharp
  31{
  32	/// <summary>
  33	/// Outputs the AST.
  34	/// </summary>
  35	public class CSharpOutputVisitor : IAstVisitor
  36	{
  37		readonly TokenWriter writer;
  38		readonly CSharpFormattingOptions policy;
  39		readonly Stack<AstNode> containerStack = new Stack<AstNode> ();
  40		
  41		public CSharpOutputVisitor (TextWriter textWriter, CSharpFormattingOptions formattingPolicy)
  42		{
  43			if (textWriter == null) {
  44				throw new ArgumentNullException ("textWriter");
  45			}
  46			if (formattingPolicy == null) {
  47				throw new ArgumentNullException ("formattingPolicy");
  48			}
  49			this.writer = TokenWriter.Create(textWriter);
  50			this.policy = formattingPolicy;
  51		}
  52		
  53		public CSharpOutputVisitor (TokenWriter writer, CSharpFormattingOptions formattingPolicy)
  54		{
  55			if (writer == null) {
  56				throw new ArgumentNullException ("writer");
  57			}
  58			if (formattingPolicy == null) {
  59				throw new ArgumentNullException ("formattingPolicy");
  60			}
  61			this.writer = new InsertSpecialsDecorator(new InsertRequiredSpacesDecorator(writer));
  62			this.policy = formattingPolicy;
  63		}
  64		
  65		#region StartNode/EndNode
  66		void StartNode(AstNode node)
  67		{
  68			// Ensure that nodes are visited in the proper nested order.
  69			// Jumps to different subtrees are allowed only for the child of a placeholder node.
  70			Debug.Assert(containerStack.Count == 0 || node.Parent == containerStack.Peek() || containerStack.Peek().NodeType == NodeType.Pattern);
  71			containerStack.Push(node);
  72			writer.StartNode(node);
  73		}
  74		
  75		void EndNode(AstNode node)
  76		{
  77			Debug.Assert(node == containerStack.Peek());
  78			containerStack.Pop();
  79			writer.EndNode(node);
  80		}
  81		#endregion
  82		
  83		#region Comma
  84		/// <summary>
  85		/// Writes a comma.
  86		/// </summary>
  87		/// <param name="nextNode">The next node after the comma.</param>
  88		/// <param name="noSpaceAfterComma">When set prevents printing a space after comma.</param>
  89		void Comma(AstNode nextNode, bool noSpaceAfterComma = false)
  90		{
  91			Space(policy.SpaceBeforeBracketComma);
  92			// TODO: Comma policy has changed.
  93			writer.WriteToken(Roles.Comma, ",");
  94			Space(!noSpaceAfterComma && policy.SpaceAfterBracketComma);
  95			// TODO: Comma policy has changed.
  96		}
  97		
  98		/// <summary>
  99		/// Writes an optional comma, e.g. at the end of an enum declaration or in an array initializer
 100		/// </summary>
 101		void OptionalComma(AstNode pos)
 102		{
 103			// Look if there's a comma after the current node, and insert it if it exists.
 104			while (pos != null && pos.NodeType == NodeType.Whitespace) {
 105				pos = pos.NextSibling;
 106			}
 107			if (pos != null && pos.Role == Roles.Comma) {
 108				Comma(null, noSpaceAfterComma: true);
 109			}
 110		}
 111		
 112		/// <summary>
 113		/// Writes an optional semicolon, e.g. at the end of a type or namespace declaration.
 114		/// </summary>
 115		void OptionalSemicolon(AstNode pos)
 116		{
 117			// Look if there's a semicolon after the current node, and insert it if it exists.
 118			while (pos != null && pos.NodeType == NodeType.Whitespace) {
 119				pos = pos.PrevSibling;
 120			}
 121			if (pos != null && pos.Role == Roles.Semicolon) {
 122				Semicolon();
 123			}
 124		}
 125		
 126		void WriteCommaSeparatedList(IEnumerable<AstNode> list)
 127		{
 128			bool isFirst = true;
 129			foreach (AstNode node in list) {
 130				if (isFirst) {
 131					isFirst = false;
 132				} else {
 133					Comma(node);
 134				}
 135				node.AcceptVisitor(this);
 136			}
 137		}
 138		
 139		void WriteCommaSeparatedListInParenthesis(IEnumerable<AstNode> list, bool spaceWithin)
 140		{
 141			LPar();
 142			if (list.Any()) {
 143				Space(spaceWithin);
 144				WriteCommaSeparatedList(list);
 145				Space(spaceWithin);
 146			}
 147			RPar();
 148		}
 149		
 150		#if DOTNET35
 151		void WriteCommaSeparatedList(IEnumerable<VariableInitializer> list)
 152		{
 153			WriteCommaSeparatedList(list.SafeCast<VariableInitializer, AstNode>());
 154		}
 155		
 156		void WriteCommaSeparatedList(IEnumerable<AstType> list)
 157		{
 158			WriteCommaSeparatedList(list.SafeCast<AstType, AstNode>());
 159		}
 160		
 161		void WriteCommaSeparatedListInParenthesis(IEnumerable<Expression> list, bool spaceWithin)
 162		{
 163			WriteCommaSeparatedListInParenthesis(list.SafeCast<Expression, AstNode>(), spaceWithin);
 164		}
 165		
 166		void WriteCommaSeparatedListInParenthesis(IEnumerable<ParameterDeclaration> list, bool spaceWithin)
 167		{
 168			WriteCommaSeparatedListInParenthesis(list.SafeCast<ParameterDeclaration, AstNode>(), spaceWithin);
 169		}
 170
 171		#endif
 172
 173		void WriteCommaSeparatedListInBrackets(IEnumerable<ParameterDeclaration> list, bool spaceWithin)
 174		{
 175			WriteToken(Roles.LBracket);
 176			if (list.Any()) {
 177				Space(spaceWithin);
 178				WriteCommaSeparatedList(list);
 179				Space(spaceWithin);
 180			}
 181			WriteToken(Roles.RBracket);
 182		}
 183
 184		void WriteCommaSeparatedListInBrackets(IEnumerable<Expression> list)
 185		{
 186			WriteToken(Roles.LBracket);
 187			if (list.Any()) {
 188				Space(policy.SpacesWithinBrackets);
 189				WriteCommaSeparatedList(list);
 190				Space(policy.SpacesWithinBrackets);
 191			}
 192			WriteToken(Roles.RBracket);
 193		}
 194		#endregion
 195		
 196		#region Write tokens
 197		bool isAtStartOfLine = true;
 198		
 199		/// <summary>
 200		/// Writes a keyword, and all specials up to
 201		/// </summary>
 202		void WriteKeyword(TokenRole tokenRole)
 203		{
 204			WriteKeyword(tokenRole.Token, tokenRole);
 205		}
 206		
 207		void WriteKeyword(string token, Role tokenRole = null)
 208		{
 209			writer.WriteKeyword(tokenRole, token);
 210			isAtStartOfLine = false;
 211		}
 212		
 213		void WriteIdentifier(Identifier identifier)
 214		{
 215			writer.WriteIdentifier(identifier);
 216			isAtStartOfLine = false;
 217		}
 218		
 219		void WriteIdentifier(string identifier)
 220		{
 221			AstType.Create(identifier).AcceptVisitor(this);
 222			isAtStartOfLine = false;
 223		}
 224		
 225		void WriteToken(TokenRole tokenRole)
 226		{
 227			WriteToken(tokenRole.Token, tokenRole);
 228		}
 229		
 230		void WriteToken(string token, Role tokenRole)
 231		{
 232			writer.WriteToken(tokenRole, token);
 233			isAtStartOfLine = false;
 234		}
 235		
 236		void LPar()
 237		{
 238			WriteToken(Roles.LPar);
 239		}
 240		
 241		void RPar()
 242		{
 243			WriteToken(Roles.RPar);
 244		}
 245		
 246		/// <summary>
 247		/// Marks the end of a statement
 248		/// </summary>
 249		void Semicolon()
 250		{
 251			Role role = containerStack.Peek().Role;
 252			// get the role of the current node
 253			if (!(role == ForStatement.InitializerRole || role == ForStatement.IteratorRole || role == UsingStatement.ResourceAcquisitionRole)) {
 254				WriteToken(Roles.Semicolon);
 255				NewLine();
 256			}
 257		}
 258		
 259		/// <summary>
 260		/// Writes a space depending on policy.
 261		/// </summary>
 262		void Space(bool addSpace = true)
 263		{
 264			if (addSpace) {
 265				writer.Space();
 266			}
 267		}
 268		
 269		void NewLine()
 270		{
 271			writer.NewLine();
 272			isAtStartOfLine = true;
 273		}
 274		
 275		void OpenBrace(BraceStyle style)
 276		{
 277			switch (style) {
 278				case BraceStyle.DoNotChange:
 279				case BraceStyle.EndOfLine:
 280				case BraceStyle.BannerStyle:
 281					if (!isAtStartOfLine)
 282						writer.Space();
 283					writer.WriteToken(Roles.LBrace, "{");
 284					break;
 285				case BraceStyle.EndOfLineWithoutSpace:
 286					writer.WriteToken(Roles.LBrace, "{");
 287					break;
 288				case BraceStyle.NextLine:
 289					if (!isAtStartOfLine)
 290						NewLine();
 291					writer.WriteToken(Roles.LBrace, "{");
 292					break;
 293				case BraceStyle.NextLineShifted:
 294					NewLine();
 295					writer.Indent();
 296					writer.WriteToken(Roles.LBrace, "{");
 297					NewLine();
 298					return;
 299				case BraceStyle.NextLineShifted2:
 300					NewLine();
 301					writer.Indent();
 302					writer.WriteToken(Roles.LBrace, "{");
 303					break;
 304				default:
 305					throw new ArgumentOutOfRangeException ();
 306			}
 307			writer.Indent();
 308			NewLine();
 309		}
 310		
 311		void CloseBrace(BraceStyle style)
 312		{
 313			switch (style) {
 314				case BraceStyle.DoNotChange:
 315				case BraceStyle.EndOfLine:
 316				case BraceStyle.EndOfLineWithoutSpace:
 317				case BraceStyle.NextLine:
 318					writer.Unindent();
 319					writer.WriteToken(Roles.RBrace, "}");
 320					isAtStartOfLine = false;
 321					break;
 322				case BraceStyle.BannerStyle:
 323				case BraceStyle.NextLineShifted:
 324					writer.WriteToken(Roles.RBrace, "}");
 325					isAtStartOfLine = false;
 326					writer.Unindent();
 327					break;
 328				case BraceStyle.NextLineShifted2:
 329					writer.Unindent();
 330					writer.WriteToken(Roles.RBrace, "}");
 331					isAtStartOfLine = false;
 332					writer.Unindent();
 333					break;
 334				default:
 335					throw new ArgumentOutOfRangeException();
 336			}
 337		}
 338
 339		#endregion
 340		
 341		#region IsKeyword Test
 342		static readonly HashSet<string> unconditionalKeywords = new HashSet<string> {
 343			"abstract", "as", "base", "bool", "break", "byte", "case", "catch",
 344			"char", "checked", "class", "const", "continue", "decimal", "default", "delegate",
 345			"do", "double", "else", "enum", "event", "explicit", "extern", "false",
 346			"finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit",
 347			"in", "int", "interface", "internal", "is", "lock", "long", "namespace",
 348			"new", "null", "object", "operator", "out", "override", "params", "private",
 349			"protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short",
 350			"sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw",
 351			"true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort",
 352			"using", "virtual", "void", "volatile", "while"
 353		};
 354		static readonly HashSet<string> queryKeywords = new HashSet<string> {
 355			"from", "where", "join", "on", "equals", "into", "let", "orderby",
 356			"ascending", "descending", "select", "group", "by"
 357		};
 358		
 359		/// <summary>
 360		/// Determines whether the specified identifier is a keyword in the given context.
 361		/// </summary>
 362		public static bool IsKeyword(string identifier, AstNode context)
 363		{
 364			if (unconditionalKeywords.Contains(identifier)) {
 365				return true;
 366			}
 367			foreach (AstNode ancestor in context.Ancestors) {
 368				if (ancestor is QueryExpression && queryKeywords.Contains(identifier)) {
 369					return true;
 370				}
 371				if (identifier == "await") {
 372					// with lambdas/anonymous methods,
 373					if (ancestor is LambdaExpression) {
 374						return ((LambdaExpression)ancestor).IsAsync;
 375					}
 376					if (ancestor is AnonymousMethodExpression) {
 377						return ((AnonymousMethodExpression)ancestor).IsAsync;
 378					}
 379					if (ancestor is EntityDeclaration) {
 380						return (((EntityDeclaration)ancestor).Modifiers & Modifiers.Async) == Modifiers.Async;
 381					}
 382				}
 383			}
 384			return false;
 385		}
 386		#endregion
 387		
 388		#region Write constructs
 389		void WriteTypeArguments(IEnumerable<AstType> typeArguments)
 390		{
 391			if (typeArguments.Any()) {
 392				WriteToken(Roles.LChevron);
 393				WriteCommaSeparatedList(typeArguments);
 394				WriteToken(Roles.RChevron);
 395			}
 396		}
 397		
 398		public void WriteTypeParameters(IEnumerable<TypeParameterDeclaration> typeParameters)
 399		{
 400			if (typeParameters.Any()) {
 401				WriteToken(Roles.LChevron);
 402				WriteCommaSeparatedList(typeParameters);
 403				WriteToken(Roles.RChevron);
 404			}
 405		}
 406		
 407		void WriteModifiers(IEnumerable<CSharpModifierToken> modifierTokens)
 408		{
 409			foreach (CSharpModifierToken modifier in modifierTokens) {
 410				modifier.AcceptVisitor(this);
 411			}
 412		}
 413		
 414		void WriteQualifiedIdentifier(IEnumerable<Identifier> identifiers)
 415		{
 416			bool first = true;
 417			foreach (Identifier ident in identifiers) {
 418				if (first) {
 419					first = false;
 420				} else {
 421					writer.WriteToken(Roles.Dot, ".");
 422				}
 423				writer.WriteIdentifier(ident);
 424			}
 425		}
 426		
 427		void WriteEmbeddedStatement(Statement embeddedStatement)
 428		{
 429			if (embeddedStatement.IsNull) {
 430				NewLine();
 431				return;
 432			}
 433			BlockStatement block = embeddedStatement as BlockStatement;
 434			if (block != null) {
 435				VisitBlockStatement(block);
 436			} else {
 437				NewLine();
 438				writer.Indent();
 439				embeddedStatement.AcceptVisitor(this);
 440				writer.Unindent();
 441			}
 442		}
 443		
 444		void WriteMethodBody(BlockStatement body)
 445		{
 446			if (body.IsNull) {
 447				Semicolon();
 448			} else {
 449				VisitBlockStatement(body);
 450			}
 451		}
 452		
 453		void WriteAttributes(IEnumerable<AttributeSection> attributes)
 454		{
 455			foreach (AttributeSection attr in attributes) {
 456				attr.AcceptVisitor(this);
 457			}
 458		}
 459		
 460		void WritePrivateImplementationType(AstType privateImplementationType)
 461		{
 462			if (!privateImplementationType.IsNull) {
 463				privateImplementationType.AcceptVisitor(this);
 464				WriteToken(Roles.Dot);
 465			}
 466		}
 467
 468		#endregion
 469		
 470		#region Expressions
 471		public void VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
 472		{
 473			StartNode(anonymousMethodExpression);
 474			if (anonymousMethodExpression.IsAsync) {
 475				WriteKeyword(AnonymousMethodExpression.AsyncModifierRole);
 476				Space();
 477			}
 478			WriteKeyword(AnonymousMethodExpression.DelegateKeywordRole);
 479			if (anonymousMethodExpression.HasParameterList) {
 480				Space(policy.SpaceBeforeMethodDeclarationParentheses);
 481				WriteCommaSeparatedListInParenthesis(anonymousMethodExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
 482			}
 483			anonymousMethodExpression.Body.AcceptVisitor(this);
 484			EndNode(anonymousMethodExpression);
 485		}
 486		
 487		public void VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression)
 488		{
 489			StartNode(undocumentedExpression);
 490			switch (undocumentedExpression.UndocumentedExpressionType) {
 491				case UndocumentedExpressionType.ArgList:
 492				case UndocumentedExpressionType.ArgListAccess:
 493					WriteKeyword(UndocumentedExpression.ArglistKeywordRole);
 494					break;
 495				case UndocumentedExpressionType.MakeRef:
 496					WriteKeyword(UndocumentedExpression.MakerefKeywordRole);
 497					break;
 498				case UndocumentedExpressionType.RefType:
 499					WriteKeyword(UndocumentedExpression.ReftypeKeywordRole);
 500					break;
 501				case UndocumentedExpressionType.RefValue:
 502					WriteKeyword(UndocumentedExpression.RefvalueKeywordRole);
 503					break;
 504			}
 505			if (undocumentedExpression.Arguments.Count > 0) {
 506				Space(policy.SpaceBeforeMethodCallParentheses);
 507				WriteCommaSeparatedListInParenthesis(undocumentedExpression.Arguments, policy.SpaceWithinMethodCallParentheses);
 508			}
 509			EndNode(undocumentedExpression);
 510		}
 511		
 512		public void VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression)
 513		{
 514			StartNode(arrayCreateExpression);
 515			WriteKeyword(ArrayCreateExpression.NewKeywordRole);
 516			arrayCreateExpression.Type.AcceptVisitor(this);
 517			if (arrayCreateExpression.Arguments.Count > 0) {
 518				WriteCommaSeparatedListInBrackets(arrayCreateExpression.Arguments);
 519			}
 520			foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers) {
 521				specifier.AcceptVisitor(this);
 522			}
 523			arrayCreateExpression.Initializer.AcceptVisitor(this);
 524			EndNode(arrayCreateExpression);
 525		}
 526		
 527		public void VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression)
 528		{
 529			StartNode(arrayInitializerExpression);
 530			// "new List<int> { { 1 } }" and "new List<int> { 1 }" are the same semantically.
 531			// We also use the same AST for both: we always use two nested ArrayInitializerExpressions
 532			// for collection initializers, even if the user did not write nested brackets.
 533			// The output visitor will output nested braces only if they are necessary,
 534			// or if the braces tokens exist in the AST.
 535			bool bracesAreOptional = arrayInitializerExpression.Elements.Count == 1
 536				&& IsObjectOrCollectionInitializer(arrayInitializerExpression.Parent)
 537				&& !CanBeConfusedWithObjectInitializer(arrayInitializerExpression.Elements.Single());
 538			if (bracesAreOptional && arrayInitializerExpression.LBraceToken.IsNull) {
 539				arrayInitializerExpression.Elements.Single().AcceptVisitor(this);
 540			} else {
 541				PrintInitializerElements(arrayInitializerExpression.Elements);
 542			}
 543			EndNode(arrayInitializerExpression);
 544		}
 545		
 546		bool CanBeConfusedWithObjectInitializer(Expression expr)
 547		{
 548			// "int a; new List<int> { a = 1 };" is an object initalizers and invalid, but
 549			// "int a; new List<int> { { a = 1 } };" is a valid collection initializer.
 550			AssignmentExpression ae = expr as AssignmentExpression;
 551			return ae != null && ae.Operator == AssignmentOperatorType.Assign;
 552		}
 553		
 554		bool IsObjectOrCollectionInitializer(AstNode node)
 555		{
 556			if (!(node is ArrayInitializerExpression)) {
 557				return false;
 558			}
 559			if (node.Parent is ObjectCreateExpression) {
 560				return node.Role == ObjectCreateExpression.InitializerRole;
 561			}
 562			if (node.Parent is NamedExpression) {
 563				return node.Role == Roles.Expression;
 564			}
 565			return false;
 566		}
 567		
 568		void PrintInitializerElements(AstNodeCollection<Expression> elements)
 569		{
 570			BraceStyle style;
 571			if (policy.ArrayInitializerWrapping == Wrapping.WrapAlways) {
 572				style = BraceStyle.NextLine;
 573			} else {
 574				style = BraceStyle.EndOfLine;
 575			}
 576			OpenBrace(style);
 577			bool isFirst = true;
 578			AstNode last = null;
 579			foreach (AstNode node in elements) {
 580				if (isFirst) {
 581					isFirst = false;
 582				} else {
 583					Comma(node, noSpaceAfterComma: true);
 584					NewLine();
 585				}
 586				last = node;
 587				node.AcceptVisitor(this);
 588			}
 589			if (last != null)
 590				OptionalComma(last.NextSibling);
 591			NewLine();
 592			CloseBrace(style);
 593		}
 594		
 595		public void VisitAsExpression(AsExpression asExpression)
 596		{
 597			StartNode(asExpression);
 598			asExpression.Expression.AcceptVisitor(this);
 599			Space();
 600			WriteKeyword(AsExpression.AsKeywordRole);
 601			Space();
 602			asExpression.Type.AcceptVisitor(this);
 603			EndNode(asExpression);
 604		}
 605		
 606		public void VisitAssignmentExpression(AssignmentExpression assignmentExpression)
 607		{
 608			StartNode(assignmentExpression);
 609			assignmentExpression.Left.AcceptVisitor(this);
 610			Space(policy.SpaceAroundAssignment);
 611			WriteToken(AssignmentExpression.GetOperatorRole(assignmentExpression.Operator));
 612			Space(policy.SpaceAroundAssignment);
 613			assignmentExpression.Right.AcceptVisitor(this);
 614			EndNode(assignmentExpression);
 615		}
 616		
 617		public void VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression)
 618		{
 619			StartNode(baseReferenceExpression);
 620			WriteKeyword("base", baseReferenceExpression.Role);
 621			EndNode(baseReferenceExpression);
 622		}
 623		
 624		public void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
 625		{
 626			StartNode(binaryOperatorExpression);
 627			binaryOperatorExpression.Left.AcceptVisitor(this);
 628			bool spacePolicy;
 629			switch (binaryOperatorExpression.Operator) {
 630				case BinaryOperatorType.BitwiseAnd:
 631				case BinaryOperatorType.BitwiseOr:
 632				case BinaryOperatorType.ExclusiveOr:
 633					spacePolicy = policy.SpaceAroundBitwiseOperator;
 634					break;
 635				case BinaryOperatorType.ConditionalAnd:
 636				case BinaryOperatorType.ConditionalOr:
 637					spacePolicy = policy.SpaceAroundLogicalOperator;
 638					break;
 639				case BinaryOperatorType.GreaterThan:
 640				case BinaryOperatorType.GreaterThanOrEqual:
 641				case BinaryOperatorType.LessThanOrEqual:
 642				case BinaryOperatorType.LessThan:
 643					spacePolicy = policy.SpaceAroundRelationalOperator;
 644					break;
 645				case BinaryOperatorType.Equality:
 646				case BinaryOperatorType.InEquality:
 647					spacePolicy = policy.SpaceAroundEqualityOperator;
 648					break;
 649				case BinaryOperatorType.Add:
 650				case BinaryOperatorType.Subtract:
 651					spacePolicy = policy.SpaceAroundAdditiveOperator;
 652					break;
 653				case BinaryOperatorType.Multiply:
 654				case BinaryOperatorType.Divide:
 655				case BinaryOperatorType.Modulus:
 656					spacePolicy = policy.SpaceAroundMultiplicativeOperator;
 657					break;
 658				case BinaryOperatorType.ShiftLeft:
 659				case BinaryOperatorType.ShiftRight:
 660					spacePolicy = policy.SpaceAroundShiftOperator;
 661					break;
 662				case BinaryOperatorType.NullCoalescing:
 663					spacePolicy = true;
 664					break;
 665				default:
 666					throw new NotSupportedException ("Invalid value for BinaryOperatorType");
 667			}
 668			Space(spacePolicy);
 669			WriteToken(BinaryOperatorExpression.GetOperatorRole(binaryOperatorExpression.Operator));
 670			Space(spacePolicy);
 671			binaryOperatorExpression.Right.AcceptVisitor(this);
 672			EndNode(binaryOperatorExpression);
 673		}
 674		
 675		public void VisitCastExpression(CastExpression castExpression)
 676		{
 677			StartNode(castExpression);
 678			LPar();
 679			Space(policy.SpacesWithinCastParentheses);
 680			castExpression.Type.AcceptVisitor(this);
 681			Space(policy.SpacesWithinCastParentheses);
 682			RPar();
 683			Space(policy.SpaceAfterTypecast);
 684			castExpression.Expression.AcceptVisitor(this);
 685			EndNode(castExpression);
 686		}
 687		
 688		public void VisitCheckedExpression(CheckedExpression checkedExpression)
 689		{
 690			StartNode(checkedExpression);
 691			WriteKeyword(CheckedExpression.CheckedKeywordRole);
 692			LPar();
 693			Space(policy.SpacesWithinCheckedExpressionParantheses);
 694			checkedExpression.Expression.AcceptVisitor(this);
 695			Space(policy.SpacesWithinCheckedExpressionParantheses);
 696			RPar();
 697			EndNode(checkedExpression);
 698		}
 699		
 700		public void VisitConditionalExpression(ConditionalExpression conditionalExpression)
 701		{
 702			StartNode(conditionalExpression);
 703			conditionalExpression.Condition.AcceptVisitor(this);
 704			
 705			Space(policy.SpaceBeforeConditionalOperatorCondition);
 706			WriteToken(ConditionalExpression.QuestionMarkRole);
 707			Space(policy.SpaceAfterConditionalOperatorCondition);
 708			
 709			conditionalExpression.TrueExpression.AcceptVisitor(this);
 710			
 711			Space(policy.SpaceBeforeConditionalOperatorSeparator);
 712			WriteToken(ConditionalExpression.ColonRole);
 713			Space(policy.SpaceAfterConditionalOperatorSeparator);
 714			
 715			conditionalExpression.FalseExpression.AcceptVisitor(this);
 716			
 717			EndNode(conditionalExpression);
 718		}
 719		
 720		public void VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression)
 721		{
 722			StartNode(defaultValueExpression);
 723			
 724			WriteKeyword(DefaultValueExpression.DefaultKeywordRole);
 725			LPar();
 726			Space(policy.SpacesWithinTypeOfParentheses);
 727			defaultValueExpression.Type.AcceptVisitor(this);
 728			Space(policy.SpacesWithinTypeOfParentheses);
 729			RPar();
 730			
 731			EndNode(defaultValueExpression);
 732		}
 733		
 734		public void VisitDirectionExpression(DirectionExpression directionExpression)
 735		{
 736			StartNode(directionExpression);
 737			
 738			switch (directionExpression.FieldDirection) {
 739				case FieldDirection.Out:
 740					WriteKeyword(DirectionExpression.OutKeywordRole);
 741					break;
 742				case FieldDirection.Ref:
 743					WriteKeyword(DirectionExpression.RefKeywordRole);
 744					break;
 745				default:
 746					throw new NotSupportedException ("Invalid value for FieldDirection");
 747			}
 748			Space();
 749			directionExpression.Expression.AcceptVisitor(this);
 750			
 751			EndNode(directionExpression);
 752		}
 753		
 754		public void VisitIdentifierExpression(IdentifierExpression identifierExpression)
 755		{
 756			StartNode(identifierExpression);
 757			WriteIdentifier(identifierExpression.IdentifierToken);
 758			WriteTypeArguments(identifierExpression.TypeArguments);
 759			EndNode(identifierExpression);
 760		}
 761		
 762		public void VisitIndexerExpression(IndexerExpression indexerExpression)
 763		{
 764			StartNode(indexerExpression);
 765			indexerExpression.Target.AcceptVisitor(this);
 766			Space(policy.SpaceBeforeMethodCallParentheses);
 767			WriteCommaSeparatedListInBrackets(indexerExpression.Arguments);
 768			EndNode(indexerExpression);
 769		}
 770		
 771		public void VisitInvocationExpression(InvocationExpression invocationExpression)
 772		{
 773			StartNode(invocationExpression);
 774			invocationExpression.Target.AcceptVisitor(this);
 775			Space(policy.SpaceBeforeMethodCallParentheses);
 776			WriteCommaSeparatedListInParenthesis(invocationExpression.Arguments, policy.SpaceWithinMethodCallParentheses);
 777			EndNode(invocationExpression);
 778		}
 779		
 780		public void VisitIsExpression(IsExpression isExpression)
 781		{
 782			StartNode(isExpression);
 783			isExpression.Expression.AcceptVisitor(this);
 784			Space();
 785			WriteKeyword(IsExpression.IsKeywordRole);
 786			isExpression.Type.AcceptVisitor(this);
 787			EndNode(isExpression);
 788		}
 789		
 790		public void VisitLambdaExpression(LambdaExpression lambdaExpression)
 791		{
 792			StartNode(lambdaExpression);
 793			if (lambdaExpression.IsAsync) {
 794				WriteKeyword(LambdaExpression.AsyncModifierRole);
 795				Space();
 796			}
 797			if (LambdaNeedsParenthesis(lambdaExpression)) {
 798				WriteCommaSeparatedListInParenthesis(lambdaExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
 799			} else {
 800				lambdaExpression.Parameters.Single().AcceptVisitor(this);
 801			}
 802			Space();
 803			WriteToken(LambdaExpression.ArrowRole);
 804			Space();
 805			lambdaExpression.Body.AcceptVisitor(this);
 806			EndNode(lambdaExpression);
 807		}
 808		
 809		bool LambdaNeedsParenthesis(LambdaExpression lambdaExpression)
 810		{
 811			if (lambdaExpression.Parameters.Count != 1) {
 812				return true;
 813			}
 814			var p = lambdaExpression.Parameters.Single();
 815			return !(p.Type.IsNull && p.ParameterModifier == ParameterModifier.None);
 816		}
 817		
 818		public void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
 819		{
 820			StartNode(memberReferenceExpression);
 821			memberReferenceExpression.Target.AcceptVisitor(this);
 822			WriteToken(Roles.Dot);
 823			WriteIdentifier(memberReferenceExpression.MemberNameToken);
 824			WriteTypeArguments(memberReferenceExpression.TypeArguments);
 825			EndNode(memberReferenceExpression);
 826		}
 827		
 828		public void VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression)
 829		{
 830			StartNode(namedArgumentExpression);
 831			WriteIdentifier(namedArgumentExpression.NameToken);
 832			WriteToken(Roles.Colon);
 833			Space();
 834			namedArgumentExpression.Expression.AcceptVisitor(this);
 835			EndNode(namedArgumentExpression);
 836		}
 837		
 838		public void VisitNamedExpression(NamedExpression namedExpression)
 839		{
 840			StartNode(namedExpression);
 841			WriteIdentifier(namedExpression.NameToken);
 842			Space();
 843			WriteToken(Roles.Assign);
 844			Space();
 845			namedExpression.Expression.AcceptVisitor(this);
 846			EndNode(namedExpression);
 847		}
 848		
 849		public void VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression)
 850		{
 851			StartNode(nullReferenceExpression);
 852			writer.WritePrimitiveValue(null);
 853			EndNode(nullReferenceExpression);
 854		}
 855		
 856		public void VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression)
 857		{
 858			StartNode(objectCreateExpression);
 859			WriteKeyword(ObjectCreateExpression.NewKeywordRole);
 860			objectCreateExpression.Type.AcceptVisitor(this);
 861			bool useParenthesis = objectCreateExpression.Arguments.Any() || objectCreateExpression.Initializer.IsNull;
 862			// also use parenthesis if there is an '(' token
 863			if (!objectCreateExpression.LParToken.IsNull) {
 864				useParenthesis = true;
 865			}
 866			if (useParenthesis) {
 867				Space(policy.SpaceBeforeMethodCallParentheses);
 868				WriteCommaSeparatedListInParenthesis(objectCreateExpression.Arguments, policy.SpaceWithinMethodCallParentheses);
 869			}
 870			objectCreateExpression.Initializer.AcceptVisitor(this);
 871			EndNode(objectCreateExpression);
 872		}
 873		
 874		public void VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression)
 875		{
 876			StartNode(anonymousTypeCreateExpression);
 877			WriteKeyword(AnonymousTypeCreateExpression.NewKeywordRole);
 878			PrintInitializerElements(anonymousTypeCreateExpression.Initializers);
 879			EndNode(anonymousTypeCreateExpression);
 880		}
 881
 882		public void VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression)
 883		{
 884			StartNode(parenthesizedExpression);
 885			LPar();
 886			Space(policy.SpacesWithinParentheses);
 887			parenthesizedExpression.Expression.AcceptVisitor(this);
 888			Space(policy.SpacesWithinParentheses);
 889			RPar();
 890			EndNode(parenthesizedExpression);
 891		}
 892		
 893		public void VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression)
 894		{
 895			StartNode(pointerReferenceExpression);
 896			pointerReferenceExpression.Target.AcceptVisitor(this);
 897			WriteToken(PointerReferenceExpression.ArrowRole);
 898			WriteIdentifier(pointerReferenceExpression.MemberNameToken);
 899			WriteTypeArguments(pointerReferenceExpression.TypeArguments);
 900			EndNode(pointerReferenceExpression);
 901		}
 902		
 903		#region VisitPrimitiveExpression
 904		public void VisitPrimitiveExpression(PrimitiveExpression primitiveExpression)
 905		{
 906			StartNode(primitiveExpression);
 907			writer.WritePrimitiveValue(primitiveExpression.Value, primitiveExpression.UnsafeLiteralValue);
 908			EndNode(primitiveExpression);
 909		}
 910		#endregion
 911		
 912		public void VisitSizeOfExpression(SizeOfExpression sizeOfExpression)
 913		{
 914			StartNode(sizeOfExpression);
 915			
 916			WriteKeyword(SizeOfExpression.SizeofKeywordRole);
 917			LPar();
 918			Space(policy.SpacesWithinSizeOfParentheses);
 919			sizeOfExpression.Type.AcceptVisitor(this);
 920			Space(policy.SpacesWithinSizeOfParentheses);
 921			RPar();
 922			
 923			EndNode(sizeOfExpression);
 924		}
 925		
 926		public void VisitStackAllocExpression(StackAllocExpression stackAllocExpression)
 927		{
 928			StartNode(stackAllocExpression);
 929			WriteKeyword(StackAllocExpression.StackallocKeywordRole);
 930			stackAllocExpression.Type.AcceptVisitor(this);
 931			WriteCommaSeparatedListInBrackets(new[] { stackAllocExpression.CountExpression });
 932			EndNode(stackAllocExpression);
 933		}
 934		
 935		public void VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression)
 936		{
 937			StartNode(thisReferenceExpression);
 938			WriteKeyword("this", thisReferenceExpression.Role);
 939			EndNode(thisReferenceExpression);
 940		}
 941		
 942		public void VisitTypeOfExpression(TypeOfExpression typeOfExpression)
 943		{
 944			StartNode(typeOfExpression);
 945			
 946			WriteKeyword(TypeOfExpression.TypeofKeywordRole);
 947			LPar();
 948			Space(policy.SpacesWithinTypeOfParentheses);
 949			typeOfExpression.Type.AcceptVisitor(this);
 950			Space(policy.SpacesWithinTypeOfParentheses);
 951			RPar();
 952			
 953			EndNode(typeOfExpression);
 954		}
 955		
 956		public void VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression)
 957		{
 958			StartNode(typeReferenceExpression);
 959			typeReferenceExpression.Type.AcceptVisitor(this);
 960			EndNode(typeReferenceExpression);
 961		}
 962		
 963		public void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
 964		{
 965			StartNode(unaryOperatorExpression);
 966			UnaryOperatorType opType = unaryOperatorExpression.Operator;
 967			var opSymbol = UnaryOperatorExpression.GetOperatorRole(opType);
 968			if (opType == UnaryOperatorType.Await) {
 969				WriteKeyword(opSymbol);
 970			} else if (!(opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)) {
 971				WriteToken(opSymbol);
 972			}
 973			unaryOperatorExpression.Expression.AcceptVisitor(this);
 974			if (opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement) {
 975				WriteToken(opSymbol);
 976			}
 977			EndNode(unaryOperatorExpression);
 978		}
 979		
 980		public void VisitUncheckedExpression(UncheckedExpression uncheckedExpression)
 981		{
 982			StartNode(uncheckedExpression);
 983			WriteKeyword(UncheckedExpression.UncheckedKeywordRole);
 984			LPar();
 985			Space(policy.SpacesWithinCheckedExpressionParantheses);
 986			uncheckedExpression.Expression.AcceptVisitor(this);
 987			Space(policy.SpacesWithinCheckedExpressionParantheses);
 988			RPar();
 989			EndNode(uncheckedExpression);
 990		}
 991
 992		#endregion
 993		
 994		#region Query Expressions
 995		public void VisitQueryExpression(QueryExpression queryExpression)
 996		{
 997			StartNode(queryExpression);
 998			bool indent = queryExpression.Parent is QueryClause && !(queryExpression.Parent is QueryContinuationClause);
 999			if (indent) {
1000				writer.Indent();
1001				NewLine();
1002			}
1003			bool first = true;
1004			foreach (var clause in queryExpression.Clauses) {
1005				if (first) {
1006					first = false;
1007				} else {
1008					if (!(clause is QueryContinuationClause)) {
1009						NewLine();
1010					}
1011				}
1012				clause.AcceptVisitor(this);
1013			}
1014			if (indent) {
1015				writer.Unindent();
1016			}
1017			EndNode(queryExpression);
1018		}
1019		
1020		public void VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause)
1021		{
1022			StartNode(queryContinuationClause);
1023			queryContinuationClause.PrecedingQuery.AcceptVisitor(this);
1024			Space();
1025			WriteKeyword(QueryContinuationClause.IntoKeywordRole);
1026			Space();
1027			WriteIdentifier(queryContinuationClause.IdentifierToken);
1028			EndNode(queryContinuationClause);
1029		}
1030		
1031		public void VisitQueryFromClause(QueryFromClause queryFromClause)
1032		{
1033			StartNode(queryFromClause);
1034			WriteKeyword(QueryFromClause.FromKeywordRole);
1035			queryFromClause.Type.AcceptVisitor(this);
1036			Space();
1037			WriteIdentifier(queryFromClause.IdentifierToken);
1038			Space();
1039			WriteKeyword(QueryFromClause.InKeywordRole);
1040			Space();
1041			queryFromClause.Expression.AcceptVisitor(this);
1042			EndNode(queryFromClause);
1043		}
1044		
1045		public void VisitQueryLetClause(QueryLetClause queryLetClause)
1046		{
1047			StartNode(queryLetClause);
1048			WriteKeyword(QueryLetClause.LetKeywordRole);
1049			Space();
1050			WriteIdentifier(queryLetClause.IdentifierToken);
1051			Space(policy.SpaceAroundAssignment);
1052			WriteToken(Roles.Assign);
1053			Space(policy.SpaceAroundAssignment);
1054			queryLetClause.Expression.AcceptVisitor(this);
1055			EndNode(queryLetClause);
1056		}
1057		
1058		public void VisitQueryWhereClause(QueryWhereClause queryWhereClause)
1059		{
1060			StartNode(queryWhereClause);
1061			WriteKeyword(QueryWhereClause.WhereKeywordRole);
1062			Space();
1063			queryWhereClause.Condition.AcceptVisitor(this);
1064			EndNode(queryWhereClause);
1065		}
1066		
1067		public void VisitQueryJoinClause(QueryJoinClause queryJoinClause)
1068		{
1069			StartNode(queryJoinClause);
1070			WriteKeyword(QueryJoinClause.JoinKeywordRole);
1071			queryJoinClause.Type.AcceptVisitor(this);
1072			Space();
1073			WriteIdentifier(queryJoinClause.JoinIdentifierToken);
1074			Space();
1075			WriteKeyword(QueryJoinClause.InKeywordRole);
1076			Space();
1077			queryJoinClause.InExpression.AcceptVisitor(this);
1078			Space();
1079			WriteKeyword(QueryJoinClause.OnKeywordRole);
1080			Space();
1081			queryJoinClause.OnExpression.AcceptVisitor(this);
1082			Space();
1083			WriteKeyword(QueryJoinClause.EqualsKeywordRole);
1084			Space();
1085			queryJoinClause.EqualsExpression.AcceptVisitor(this);
1086			if (queryJoinClause.IsGroupJoin) {
1087				Space();
1088				WriteKeyword(QueryJoinClause.IntoKeywordRole);
1089				WriteIdentifier(queryJoinClause.IntoIdentifierToken);
1090			}
1091			EndNode(queryJoinClause);
1092		}
1093		
1094		public void VisitQueryOrderClause(QueryOrderClause queryOrderClause)
1095		{
1096			StartNode(queryOrderClause);
1097			WriteKeyword(QueryOrderClause.OrderbyKeywordRole);
1098			Space();
1099			WriteCommaSeparatedList(queryOrderClause.Orderings);
1100			EndNode(queryOrderClause);
1101		}
1102		
1103		public void VisitQueryOrdering(QueryOrdering queryOrdering)
1104		{
1105			StartNode(queryOrdering);
1106			queryOrdering.Expression.AcceptVisitor(this);
1107			switch (queryOrdering.Direction) {
1108				case QueryOrderingDirection.Ascending:
1109					Space();
1110					WriteKeyword(QueryOrdering.AscendingKeywordRole);
1111					break;
1112				case QueryOrderingDirection.Descending:
1113					Space();
1114					WriteKeyword(QueryOrdering.DescendingKeywordRole);
1115					break;
1116			}
1117			EndNode(queryOrdering);
1118		}
1119		
1120		public void VisitQuerySelectClause(QuerySelectClause querySelectClause)
1121		{
1122			StartNode(querySelectClause);
1123			WriteKeyword(QuerySelectClause.SelectKeywordRole);
1124			Space();
1125			querySelectClause.Expression.AcceptVisitor(this);
1126			EndNode(querySelectClause);
1127		}
1128		
1129		public void VisitQueryGroupClause(QueryGroupClause queryGroupClause)
1130		{
1131			StartNode(queryGroupClause);
1132			WriteKeyword(QueryGroupClause.GroupKeywordRole);
1133			Space();
1134			queryGroupClause.Projection.AcceptVisitor(this);
1135			Space();
1136			WriteKeyword(QueryGroupClause.ByKeywordRole);
1137			Space();
1138			queryGroupClause.Key.AcceptVisitor(this);
1139			EndNode(queryGroupClause);
1140		}
1141
1142		#endregion
1143		
1144		#region GeneralScope
1145		public void VisitAttribute(Attribute attribute)
1146		{
1147			StartNode(attribute);
1148			attribute.Type.AcceptVisitor(this);
1149			if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole(Roles.LPar).IsNull) {
1150				Space(policy.SpaceBeforeMethodCallParentheses);
1151				WriteCommaSeparatedListInParenthesis(attribute.Arguments, policy.SpaceWithinMethodCallParentheses);
1152			}
1153			EndNode(attribute);
1154		}
1155		
1156		public void VisitAttributeSection(AttributeSection attributeSection)
1157		{
1158			StartNode(attributeSection);
1159			WriteToken(Roles.LBracket);
1160			if (!string.IsNullOrEmpty(attributeSection.AttributeTarget)) {
1161				WriteIdentifier(attributeSection.AttributeTargetToken);
1162				WriteToken(Roles.Colon);
1163				Space();
1164			}
1165			WriteCommaSeparatedList(attributeSection.Attributes);
1166			WriteToken(Roles.RBracket);
1167			if (attributeSection.Parent is ParameterDeclaration || attributeSection.Parent is TypeParameterDeclaration) {
1168				Space();
1169			} else {
1170				NewLine();
1171			}
1172			EndNode(attributeSection);
1173		}
1174		
1175		public void VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
1176		{
1177			StartNode(delegateDeclaration);
1178			WriteAttributes(delegateDeclaration.Attributes);
1179			WriteModifiers(delegateDeclaration.ModifierTokens);
1180			WriteKeyword(Roles.DelegateKeyword);
1181			delegateDeclaration.ReturnType.AcceptVisitor(this);
1182			Space();
1183			WriteIdentifier(delegateDeclaration.NameToken);
1184			WriteTypeParameters(delegateDeclaration.TypeParameters);
1185			Space(policy.SpaceBeforeDelegateDeclarationParentheses);
1186			WriteCommaSeparatedListInParenthesis(delegateDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
1187			foreach (Constraint constraint in delegateDeclaration.Constraints) {
1188				constraint.AcceptVisitor(this);
1189			}
1190			Semicolon();
1191			EndNode(delegateDeclaration);
1192		}
1193		
1194		public void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
1195		{
1196			StartNode(namespaceDeclaration);
1197			WriteKeyword(Roles.NamespaceKeyword);
1198			namespaceDeclaration.NamespaceName.AcceptVisitor (this);
1199			OpenBrace(policy.NamespaceBraceStyle);
1200			foreach (var member in namespaceDeclaration.Members) {
1201				member.AcceptVisitor(this);
1202				MaybeNewLinesAfterUsings(member);
1203			}
1204			CloseBrace(policy.NamespaceBraceStyle);
1205			OptionalSemicolon(namespaceDeclaration.LastChild);
1206			NewLine();
1207			EndNode(namespaceDeclaration);
1208		}
1209		
1210		public void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
1211		{
1212			StartNode(typeDeclaration);
1213			WriteAttributes(typeDeclaration.Attributes);
1214			WriteModifiers(typeDeclaration.ModifierTokens);
1215			BraceStyle braceStyle;
1216			switch (typeDeclaration.ClassType) {
1217				case ClassType.Enum:
1218					WriteKeyword(Roles.EnumKeyword);
1219					braceStyle = policy.EnumBraceStyle;
1220					break;
1221				case ClassType.Interface:
1222					WriteKeyword(Roles.InterfaceKeyword);
1223					braceStyle = policy.InterfaceBraceStyle;
1224					break;
1225				case ClassType.Struct:
1226					WriteKeyword(Roles.StructKeyword);
1227					braceStyle = policy.StructBraceStyle;
1228					break;
1229				default:
1230					WriteKeyword(Roles.ClassKeyword);
1231					braceStyle = policy.ClassBraceStyle;
1232					break;
1233			}
1234			WriteIdentifier(typeDeclaration.NameToken);
1235			WriteTypeParameters(typeDeclaration.TypeParameters);
1236			if (typeDeclaration.BaseTypes.Any()) {
1237				Space();
1238				WriteToken(Roles.Colon);
1239				Space();
1240				WriteCommaSeparatedList(typeDeclaration.BaseTypes);
1241			}
1242			foreach (Constraint constraint in typeDeclaration.Constraints) {
1243				constraint.AcceptVisitor(this);
1244			}
1245			OpenBrace(braceStyle);
1246			if (typeDeclaration.ClassType == ClassType.Enum) {
1247				bool first = true;
1248				AstNode last = null;
1249				foreach (var member in typeDeclaration.Members) {
1250					if (first) {
1251						first = false;
1252					} else {
1253						Comma(member, noSpaceAfterComma: true);
1254						NewLine();
1255					}
1256					last = member;
1257					member.AcceptVisitor(this);
1258				}
1259				if (last != null)
1260					OptionalComma(last.NextSibling);
1261				NewLine();
1262			} else {
1263				bool first = true;
1264				foreach (var member in typeDeclaration.Members) {
1265					if (!first) {
1266						for (int i = 0; i < policy.MinimumBlankLinesBetweenMembers; i++)
1267							NewLine();
1268					}
1269					first = false;
1270					member.AcceptVisitor(this);
1271				}
1272			}
1273			CloseBrace(braceStyle);
1274			OptionalSemicolon(typeDeclaration.LastChild);
1275			NewLine();
1276			EndNode(typeDeclaration);
1277		}
1278		
1279		public void VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration)
1280		{
1281			StartNode(usingAliasDeclaration);
1282			WriteKeyword(UsingAliasDeclaration.UsingKeywordRole);
1283			WriteIdentifier(usingAliasDeclaration.GetChildByRole(UsingAliasDeclaration.AliasRole));
1284			Space(policy.SpaceAroundEqualityOperator);
1285			WriteToken(Roles.Assign);
1286			Space(policy.SpaceAroundEqualityOperator);
1287			usingAliasDeclaration.Import.AcceptVisitor(this);
1288			Semicolon();
1289			EndNode(usingAliasDeclaration);
1290		}
1291		
1292		public void VisitUsingDeclaration(UsingDeclaration usingDeclaration)
1293		{
1294			StartNode(usingDeclaration);
1295			WriteKeyword(UsingDeclaration.UsingKeywordRole);
1296			usingDeclaration.Import.AcceptVisitor(this);
1297			Semicolon();
1298			EndNode(usingDeclaration);
1299		}
1300		
1301		public void VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration)
1302		{
1303			StartNode(externAliasDeclaration);
1304			WriteKeyword(Roles.ExternKeyword);
1305			Space();
1306			WriteKeyword(Roles.AliasKeyword);
1307			Space();
1308			WriteIdentifier(externAliasDeclaration.NameToken);
1309			Semicolon();
1310			EndNode(externAliasDeclaration);
1311		}
1312
1313		#endregion
1314		
1315		#region Statements
1316		public void VisitBlockStatement(BlockStatement blockStatement)
1317		{
1318			StartNode(blockStatement);
1319			BraceStyle style;
1320			if (blockStatement.Parent is AnonymousMethodExpression || blockStatement.Parent is LambdaExpression) {
1321				style = policy.AnonymousMethodBraceStyle;
1322			} else if (blockStatement.Parent is ConstructorDeclaration) {
1323				style = policy.ConstructorBraceStyle;
1324			} else if (blockStatement.Parent is DestructorDeclaration) {
1325				style = policy.DestructorBraceStyle;
1326			} else if (blockStatement.Parent is MethodDeclaration) {
1327				style = policy.MethodBraceStyle;
1328			} else if (blockStatement.Parent is Accessor) {
1329				if (blockStatement.Parent.Role == PropertyDeclaration.GetterRole) {
1330					style = policy.PropertyGetBraceStyle;
1331				} else if (blockStatement.Parent.Role == PropertyDeclaration.SetterRole) {
1332					style = policy.PropertySetBraceStyle;
1333				} else if (blockStatement.Parent.Role == CustomEventDeclaration.AddAccessorRole) {
1334					style = policy.EventAddBraceStyle;
1335				} else if (blockStatement.Parent.Role == CustomEventDeclaration.RemoveAccessorRole) {
1336					style = policy.EventRemoveBraceStyle;
1337				} else {
1338					style = policy.StatementBraceStyle;
1339				}
1340			} else {
1341				style = policy.StatementBraceStyle;
1342			}
1343			OpenBrace(style);
1344			foreach (var node in blockStatement.Statements) {
1345				node.AcceptVisitor(this);
1346			}
1347			EndNode(blockStatement);
1348			CloseBrace(style);
1349			if (!(blockStatement.Parent is Expression))
1350				NewLine();
1351		}
1352		
1353		public void VisitBreakStatement(BreakStatement breakStatement)
1354		{
1355			StartNode(breakStatement);
1356			WriteKeyword("break", BreakStatement.BreakKeywordRole);
1357			Semicolon();
1358			EndNode(breakStatement);
1359		}
1360		
1361		public void VisitCheckedStatement(CheckedStatement checkedStatement)
1362		{
1363			StartNode(checkedStatement);
1364			WriteKeyword(CheckedStatement.CheckedKeywordRole);
1365			checkedStatement.Body.AcceptVisitor(this);
1366			EndNode(checkedStatement);
1367		}
1368		
1369		public void VisitContinueStatement(ContinueStatement continueStatement)
1370		{
1371			StartNode(continueStatement);
1372			WriteKeyword("continue", ContinueStatement.ContinueKeywordRole);
1373			Semicolon();
1374			EndNode(continueStatement);
1375		}
1376		
1377		public void VisitDoWhileStatement(DoWhileStatement doWhileStatement)
1378		{
1379			StartNode(doWhileStatement);
1380			WriteKeyword(DoWhileStatement.DoKeywordRole);
1381			WriteEmbeddedStatement(doWhileStatement.EmbeddedStatement);
1382			WriteKeyword(DoWhileStatement.WhileKeywordRole);
1383			Space(policy.SpaceBeforeWhileParentheses);
1384			LPar();
1385			Space(policy.SpacesWithinWhileParentheses);
1386			doWhileStatement.Condition.AcceptVisitor(this);
1387			Space(policy.SpacesWithinWhileParentheses);
1388			RPar();
1389			Semicolon();
1390			EndNode(doWhileStatement);
1391		}
1392		
1393		public void VisitEmptyStatement(EmptyStatement emptyStatement)
1394		{
1395			StartNode(emptyStatement);
1396			Semicolon();
1397			EndNode(emptyStatement);
1398		}
1399		
1400		public void VisitExpressionStatement(ExpressionStatement expressionStatement)
1401		{
1402			StartNode(expressionStatement);
1403			expressionStatement.Expression.AcceptVisitor(this);
1404			Semicolon();
1405			EndNode(expressionStatement);
1406		}
1407		
1408		public void VisitFixedStatement(FixedStatement fixedStatement)
1409		{
1410			StartNode(fixedStatement);
1411			WriteKeyword(FixedStatement.FixedKeywordRole);
1412			Space(policy.SpaceBeforeUsingParentheses);
1413			LPar();
1414			Space(policy.SpacesWithinUsingParentheses);
1415			fixedStatement.Type.AcceptVisitor(this);
1416			Space();
1417			WriteCommaSeparatedList(fixedStatement.Variables);
1418			Space(policy.SpacesWithinUsingParentheses);
1419			RPar();
1420			WriteEmbeddedStatement(fixedStatement.EmbeddedStatement);
1421			EndNode(fixedStatement);
1422		}
1423		
1424		public void VisitForeachStatement(ForeachStatement foreachStatement)
1425		{
1426			StartNode(foreachStatement);
1427			WriteKeyword(ForeachStatement.ForeachKeywordRole);
1428			Space(policy.SpaceBeforeForeachParentheses);
1429			LPar();
1430			Space(policy.SpacesWithinForeachParentheses);
1431			foreachStatement.VariableType.AcceptVisitor(this);
1432			Space();
1433			WriteIdentifier(foreachStatement.VariableNameToken);
1434			WriteKeyword(ForeachStatement.InKeywordRole);
1435			Space();
1436			foreachStatement.InExpression.AcceptVisitor(this);
1437			Space(policy.SpacesWithinForeachParentheses);
1438			RPar();
1439			WriteEmbeddedStatement(foreachStatement.EmbeddedStatement);
1440			EndNode(foreachStatement);
1441		}
1442		
1443		public void VisitForStatement(ForStatement forStatement)
1444		{
1445			StartNode(forStatement);
1446			WriteKeyword(ForStatement.ForKeywordRole);
1447			Space(policy.SpaceBeforeForParentheses);
1448			LPar();
1449			Space(policy.SpacesWithinForParentheses);
1450			
1451			WriteCommaSeparatedList(forStatement.Initializers);
1452			Space(policy.SpaceBeforeForSemicolon);
1453			WriteToken(Roles.Semicolon);
1454			Space(policy.SpaceAfterForSemicolon);
1455			
1456			forStatement.Condition.AcceptVisitor(this);
1457			Space(policy.SpaceBeforeForSemicolon);
1458			WriteToken(Roles.Semicolon);
1459			if (forStatement.Iterators.Any()) {
1460				Space(policy.SpaceAfterForSemicolon);
1461				WriteCommaSeparatedList(forStatement.Iterators);
1462			}
1463			
1464			Space(policy.SpacesWithinForParentheses);
1465			RPar();
1466			WriteEmbeddedStatement(forStatement.EmbeddedStatement);
1467			EndNode(forStatement);
1468		}
1469		
1470		public void VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement)
1471		{
1472			StartNode(gotoCaseStatement);
1473			WriteKeyword(GotoCaseStatement.GotoKeywordRole);
1474			WriteKeyword(GotoCaseStatement.CaseKeywordRole);
1475			Space();
1476			gotoCaseStatement.LabelExpression.AcceptVisitor(this);
1477			Semicolon();
1478			EndNode(gotoCaseStatement);
1479		}
1480		
1481		public void VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement)
1482		{
1483			StartNode(gotoDefaultStatement);
1484			WriteKeyword(GotoDefaultStatement.GotoKeywordRole);
1485			WriteKeyword(GotoDefaultStatement.DefaultKeywordRole);
1486			Semicolon();
1487			EndNode(gotoDefaultStatement);
1488		}
1489		
1490		public void VisitGotoStatement(GotoStatement gotoStatement)
1491		{
1492			StartNode(gotoStatement);
1493			WriteKeyword(GotoStatement.GotoKeywordRole);
1494			WriteIdentifier(gotoStatement.GetChildByRole(Roles.Identifier));
1495			Semicolon();
1496			EndNode(gotoStatement);
1497		}
1498		
1499		public void VisitIfElseStatement(IfElseStatement ifElseStatement)
1500		{
1501			StartNode(ifElseStatement);
1502			WriteKeyword(IfElseStatement.IfKeywordRole);
1503			Space(policy.SpaceBeforeIfParentheses);
1504			LPar();
1505			Space(policy.SpacesWithinIfParentheses);
1506			ifElseStatement.Condition.AcceptVisitor(this);
1507			Space(policy.SpacesWithinIfParentheses);
1508			RPar();
1509			WriteEmbeddedStatement(ifElseStatement.TrueStatement);
1510			if (!ifElseStatement.FalseStatement.IsNull) {
1511				WriteKeyword(IfElseStatement.ElseKeywordRole);
1512				if (ifElseStatement.FalseStatement is IfElseStatement) {
1513					// don't put newline between 'else' and 'if'
1514					ifElseStatement.FalseStatement.AcceptVisitor(this);
1515				} else {
1516					WriteEmbeddedStatement(ifElseStatement.FalseStatement);
1517				}
1518			}
1519			EndNode(ifElseStatement);
1520		}
1521		
1522		public void VisitLabelStatement(LabelStatement labelStatement)
1523		{
1524			StartNode(labelStatement);
1525			WriteIdentifier(labelStatement.GetChildByRole(Roles.Identifier));
1526			WriteToken(Roles.Colon);
1527			bool foundLabelledStatement = false;
1528			for (AstNode tmp = labelStatement.NextSibling; tmp != null; tmp = tmp.NextSibling) {
1529				if (tmp.Role == labelStatement.Role) {
1530					foundLabelledStatement = true;
1531				}
1532			}
1533			if (!foundLabelledStatement) {
1534				// introduce an EmptyStatement so that the output becomes syntactically valid
1535				WriteToken(Roles.Semicolon);
1536			}
1537			NewLine();
1538			EndNode(labelStatement);
1539		}
1540		
1541		public void VisitLockStatement(LockStatement lockStatement)
1542		{
1543			StartNode(lockStatement);
1544			WriteKeyword(LockStatement.LockKeywordRole);
1545			Space(policy.SpaceBeforeLockParentheses);
1546			LPar();
1547			Space(policy.SpacesWithinLockParentheses);
1548			lockStatement.Expression.AcceptVisitor(this);
1549			Space(policy.SpacesWithinLockParentheses);
1550			RPar();
1551			WriteEmbeddedStatement(lockStatement.EmbeddedStatement);
1552			EndNode(lockStatement);
1553		}
1554		
1555		public void VisitReturnStatement(ReturnStatement returnStatement)
1556		{
1557			StartNode(returnStatement);
1558			WriteKeyword(ReturnStatement.ReturnKeywordRole);
1559			if (!returnStatement.Expression.IsNull) {
1560				Space();
1561				returnStatement.Expression.AcceptVisitor(this);
1562			}
1563			Semicolon();
1564			EndNode(returnStatement);
1565		}
1566		
1567		public void VisitSwitchStatement(SwitchStatement switchStatement)
1568		{
1569			StartNode(switchStatement);
1570			WriteKeyword(SwitchStatement.SwitchKeywordRole);
1571			Space(policy.SpaceBeforeSwitchParentheses);
1572			LPar();
1573			Space(policy.SpacesWithinSwitchParentheses);
1574			switchStatement.Expression.AcceptVisitor(this);
1575			Space(policy.SpacesWithinSwitchParentheses);
1576			RPar();
1577			OpenBrace(policy.StatementBraceStyle);
1578			if (!policy.IndentSwitchBody) {
1579				writer.Unindent();
1580			}
1581			
1582			foreach (var section in switchStatement.SwitchSections

Large files files are truncated, but you can click here to view the full file