PageRenderTime 70ms CodeModel.GetById 12ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 1ms

/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs

http://github.com/icsharpcode/ILSpy
C# | 2676 lines | 2373 code | 226 blank | 77 comment | 170 complexity | 1f3be533fe71a888134d1aa409a74358 MD5 | raw file

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

   1// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
   2// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
   3
   4using System;
   5using System.Collections.Generic;
   6using System.Diagnostics;
   7using System.Globalization;
   8using System.IO;
   9using System.Linq;
  10using System.Text;
  11
  12using ICSharpCode.NRefactory.PatternMatching;
  13using ICSharpCode.NRefactory.VB.Ast;
  14
  15namespace ICSharpCode.NRefactory.VB
  16{
  17	/// <summary>
  18	/// Description of OutputVisitor.
  19	/// </summary>
  20	public class OutputVisitor : IAstVisitor<object, object>
  21	{
  22		readonly IOutputFormatter formatter;
  23		readonly VBFormattingOptions policy;
  24		
  25		readonly Stack<AstNode> containerStack = new Stack<AstNode>();
  26		readonly Stack<AstNode> positionStack = new Stack<AstNode>();
  27		
  28		/// <summary>
  29		/// Used to insert the minimal amount of spaces so that the lexer recognizes the tokens that were written.
  30		/// </summary>
  31		LastWritten lastWritten;
  32		
  33		enum LastWritten
  34		{
  35			Whitespace,
  36			Other,
  37			KeywordOrIdentifier
  38		}
  39		
  40		public OutputVisitor(TextWriter textWriter, VBFormattingOptions formattingPolicy)
  41		{
  42			if (textWriter == null)
  43				throw new ArgumentNullException("textWriter");
  44			if (formattingPolicy == null)
  45				throw new ArgumentNullException("formattingPolicy");
  46			this.formatter = new TextWriterOutputFormatter(textWriter);
  47			this.policy = formattingPolicy;
  48		}
  49		
  50		public OutputVisitor(IOutputFormatter formatter, VBFormattingOptions formattingPolicy)
  51		{
  52			if (formatter == null)
  53				throw new ArgumentNullException("formatter");
  54			if (formattingPolicy == null)
  55				throw new ArgumentNullException("formattingPolicy");
  56			this.formatter = formatter;
  57			this.policy = formattingPolicy;
  58		}
  59		
  60		public object VisitCompilationUnit(CompilationUnit compilationUnit, object data)
  61		{
  62			// don't do node tracking as we visit all children directly
  63			foreach (AstNode node in compilationUnit.Children)
  64				node.AcceptVisitor(this, data);
  65			return null;
  66		}
  67		
  68		public object VisitBlockStatement(BlockStatement blockStatement, object data)
  69		{
  70			StartNode(blockStatement);
  71			foreach (var stmt in blockStatement) {
  72				stmt.AcceptVisitor(this, data);
  73				NewLine();
  74			}
  75			return EndNode(blockStatement);
  76		}
  77		
  78		public object VisitPatternPlaceholder(AstNode placeholder, Pattern pattern, object data)
  79		{
  80			throw new NotImplementedException();
  81		}
  82		
  83		public object VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, object data)
  84		{
  85			StartNode(typeParameterDeclaration);
  86			
  87			switch (typeParameterDeclaration.Variance) {
  88				case ICSharpCode.NRefactory.TypeSystem.VarianceModifier.Invariant:
  89					break;
  90				case ICSharpCode.NRefactory.TypeSystem.VarianceModifier.Covariant:
  91					WriteKeyword("Out");
  92					break;
  93				case ICSharpCode.NRefactory.TypeSystem.VarianceModifier.Contravariant:
  94					WriteKeyword("In");
  95					break;
  96				default:
  97					throw new Exception("Invalid value for VarianceModifier");
  98			}
  99			
 100			WriteIdentifier(typeParameterDeclaration.Name);
 101			if (typeParameterDeclaration.Constraints.Any()) {
 102				WriteKeyword("As");
 103				if (typeParameterDeclaration.Constraints.Count > 1)
 104					WriteToken("{", TypeParameterDeclaration.Roles.LBrace);
 105				WriteCommaSeparatedList(typeParameterDeclaration.Constraints);
 106				if (typeParameterDeclaration.Constraints.Count > 1)
 107					WriteToken("}", TypeParameterDeclaration.Roles.RBrace);
 108			}
 109			
 110			return EndNode(typeParameterDeclaration);
 111		}
 112		
 113		public object VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, object data)
 114		{
 115			StartNode(parameterDeclaration);
 116			WriteAttributes(parameterDeclaration.Attributes);
 117			WriteModifiers(parameterDeclaration.ModifierTokens);
 118			WriteIdentifier(parameterDeclaration.Name.Name);
 119			if (!parameterDeclaration.Type.IsNull) {
 120				WriteKeyword("As");
 121				parameterDeclaration.Type.AcceptVisitor(this, data);
 122			}
 123			if (!parameterDeclaration.OptionalValue.IsNull) {
 124				WriteToken("=", ParameterDeclaration.Roles.Assign);
 125				parameterDeclaration.OptionalValue.AcceptVisitor(this, data);
 126			}
 127			return EndNode(parameterDeclaration);
 128		}
 129		
 130		public object VisitVBTokenNode(VBTokenNode vBTokenNode, object data)
 131		{
 132			var mod = vBTokenNode as VBModifierToken;
 133			if (mod != null) {
 134				StartNode(vBTokenNode);
 135				WriteKeyword(VBModifierToken.GetModifierName(mod.Modifier));
 136				return EndNode(vBTokenNode);
 137			} else {
 138				throw new NotSupportedException("Should never visit individual tokens");
 139			}
 140		}
 141		
 142		public object VisitAliasImportsClause(AliasImportsClause aliasImportsClause, object data)
 143		{
 144			throw new NotImplementedException();
 145		}
 146		
 147		public object VisitAttribute(ICSharpCode.NRefactory.VB.Ast.Attribute attribute, object data)
 148		{
 149			StartNode(attribute);
 150			
 151			if (attribute.Target != AttributeTarget.None) {
 152				switch (attribute.Target) {
 153					case AttributeTarget.None:
 154						break;
 155					case AttributeTarget.Assembly:
 156						WriteKeyword("Assembly");
 157						break;
 158					case AttributeTarget.Module:
 159						WriteKeyword("Module");
 160						break;
 161					default:
 162						throw new Exception("Invalid value for AttributeTarget");
 163				}
 164				WriteToken(":", Ast.Attribute.Roles.Colon);
 165				Space();
 166			}
 167			attribute.Type.AcceptVisitor(this, data);
 168			WriteCommaSeparatedListInParenthesis(attribute.Arguments, false);
 169			
 170			return EndNode(attribute);
 171		}
 172		
 173		public object VisitAttributeBlock(AttributeBlock attributeBlock, object data)
 174		{
 175			StartNode(attributeBlock);
 176			
 177			WriteToken("<", AttributeBlock.Roles.LChevron);
 178			WriteCommaSeparatedList(attributeBlock.Attributes);
 179			WriteToken(">", AttributeBlock.Roles.RChevron);
 180			if (attributeBlock.Parent is ParameterDeclaration)
 181				Space();
 182			else
 183				NewLine();
 184			
 185			return EndNode(attributeBlock);
 186		}
 187		
 188		public object VisitImportsStatement(ImportsStatement importsStatement, object data)
 189		{
 190			StartNode(importsStatement);
 191			
 192			WriteKeyword("Imports", AstNode.Roles.Keyword);
 193			Space();
 194			WriteCommaSeparatedList(importsStatement.ImportsClauses);
 195			NewLine();
 196			
 197			return EndNode(importsStatement);
 198		}
 199		
 200		public object VisitMemberImportsClause(MemberImportsClause memberImportsClause, object data)
 201		{
 202			StartNode(memberImportsClause);
 203			memberImportsClause.Member.AcceptVisitor(this, data);
 204			return EndNode(memberImportsClause);
 205		}
 206		
 207		public object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data)
 208		{
 209			StartNode(namespaceDeclaration);
 210			NewLine();
 211			WriteKeyword("Namespace");
 212			bool isFirst = true;
 213			foreach (Identifier node in namespaceDeclaration.Identifiers) {
 214				if (isFirst) {
 215					isFirst = false;
 216				} else {
 217					WriteToken(".", NamespaceDeclaration.Roles.Dot);
 218				}
 219				node.AcceptVisitor(this, null);
 220			}
 221			NewLine();
 222			WriteMembers(namespaceDeclaration.Members);
 223			WriteKeyword("End");
 224			WriteKeyword("Namespace");
 225			NewLine();
 226			return EndNode(namespaceDeclaration);
 227		}
 228		
 229		public object VisitOptionStatement(OptionStatement optionStatement, object data)
 230		{
 231			throw new NotImplementedException();
 232		}
 233		
 234		public object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
 235		{
 236			StartNode(typeDeclaration);
 237			WriteAttributes(typeDeclaration.Attributes);
 238			WriteModifiers(typeDeclaration.ModifierTokens);
 239			WriteClassTypeKeyword(typeDeclaration);
 240			WriteIdentifier(typeDeclaration.Name.Name);
 241			MarkFoldStart();
 242			NewLine();
 243			
 244			if (!typeDeclaration.InheritsType.IsNull) {
 245				Indent();
 246				WriteKeyword("Inherits");
 247				typeDeclaration.InheritsType.AcceptVisitor(this, data);
 248				Unindent();
 249				NewLine();
 250			}
 251			if (typeDeclaration.ImplementsTypes.Any()) {
 252				Indent();
 253				WriteImplementsClause(typeDeclaration.ImplementsTypes);
 254				Unindent();
 255				NewLine();
 256			}
 257			
 258			if (!typeDeclaration.InheritsType.IsNull || typeDeclaration.ImplementsTypes.Any())
 259				NewLine();
 260			
 261			WriteMembers(typeDeclaration.Members);
 262			
 263			WriteKeyword("End");
 264			WriteClassTypeKeyword(typeDeclaration);
 265			MarkFoldEnd();
 266			NewLine();
 267			return EndNode(typeDeclaration);
 268		}
 269
 270		void WriteClassTypeKeyword(TypeDeclaration typeDeclaration)
 271		{
 272			switch (typeDeclaration.ClassType) {
 273				case ClassType.Class:
 274					WriteKeyword("Class");
 275					break;
 276				case ClassType.Interface:
 277					WriteKeyword("Interface");
 278					break;
 279				case ClassType.Struct:
 280					WriteKeyword("Structure");
 281					break;
 282				case ClassType.Module:
 283					WriteKeyword("Module");
 284					break;
 285				default:
 286					throw new Exception("Invalid value for ClassType");
 287			}
 288		}
 289		
 290		public object VisitXmlNamespaceImportsClause(XmlNamespaceImportsClause xmlNamespaceImportsClause, object data)
 291		{
 292			throw new NotImplementedException();
 293		}
 294		
 295		public object VisitEnumDeclaration(EnumDeclaration enumDeclaration, object data)
 296		{
 297			StartNode(enumDeclaration);
 298			
 299			WriteAttributes(enumDeclaration.Attributes);
 300			WriteModifiers(enumDeclaration.ModifierTokens);
 301			WriteKeyword("Enum");
 302			WriteIdentifier(enumDeclaration.Name.Name);
 303			if (!enumDeclaration.UnderlyingType.IsNull) {
 304				Space();
 305				WriteKeyword("As");
 306				enumDeclaration.UnderlyingType.AcceptVisitor(this, data);
 307			}
 308			MarkFoldStart();
 309			NewLine();
 310			
 311			Indent();
 312			foreach (var member in enumDeclaration.Members) {
 313				member.AcceptVisitor(this, null);
 314			}
 315			Unindent();
 316			
 317			WriteKeyword("End");
 318			WriteKeyword("Enum");
 319			MarkFoldEnd();
 320			NewLine();
 321			
 322			return EndNode(enumDeclaration);
 323		}
 324		
 325		public object VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data)
 326		{
 327			StartNode(enumMemberDeclaration);
 328			
 329			WriteAttributes(enumMemberDeclaration.Attributes);
 330			WriteIdentifier(enumMemberDeclaration.Name.Name);
 331			
 332			if (!enumMemberDeclaration.Value.IsNull) {
 333				Space();
 334				WriteToken("=", EnumMemberDeclaration.Roles.Assign);
 335				Space();
 336				enumMemberDeclaration.Value.AcceptVisitor(this, data);
 337			}
 338			NewLine();
 339			
 340			return EndNode(enumMemberDeclaration);
 341		}
 342		
 343		public object VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data)
 344		{
 345			StartNode(delegateDeclaration);
 346			
 347			WriteAttributes(delegateDeclaration.Attributes);
 348			WriteModifiers(delegateDeclaration.ModifierTokens);
 349			WriteKeyword("Delegate");
 350			if (delegateDeclaration.IsSub)
 351				WriteKeyword("Sub");
 352			else
 353				WriteKeyword("Function");
 354			WriteIdentifier(delegateDeclaration.Name.Name);
 355			WriteTypeParameters(delegateDeclaration.TypeParameters);
 356			WriteCommaSeparatedListInParenthesis(delegateDeclaration.Parameters, false);
 357			if (!delegateDeclaration.IsSub) {
 358				Space();
 359				WriteKeyword("As");
 360				WriteAttributes(delegateDeclaration.ReturnTypeAttributes);
 361				delegateDeclaration.ReturnType.AcceptVisitor(this, data);
 362			}
 363			NewLine();
 364			
 365			return EndNode(delegateDeclaration);
 366		}
 367		
 368		public object VisitIdentifier(Identifier identifier, object data)
 369		{
 370			StartNode(identifier);
 371			WriteIdentifier(identifier.Name);
 372			WriteTypeCharacter(identifier.TypeCharacter);
 373			return EndNode(identifier);
 374		}
 375		
 376		public object VisitXmlIdentifier(XmlIdentifier xmlIdentifier, object data)
 377		{
 378			throw new NotImplementedException();
 379		}
 380		
 381		public object VisitXmlLiteralString(XmlLiteralString xmlLiteralString, object data)
 382		{
 383			throw new NotImplementedException();
 384		}
 385		
 386		public object VisitSimpleNameExpression(SimpleNameExpression simpleNameExpression, object data)
 387		{
 388			StartNode(simpleNameExpression);
 389			
 390			simpleNameExpression.Identifier.AcceptVisitor(this, data);
 391			WriteTypeArguments(simpleNameExpression.TypeArguments);
 392			
 393			return EndNode(simpleNameExpression);
 394		}
 395		
 396		public object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data)
 397		{
 398			StartNode(primitiveExpression);
 399			
 400			if (lastWritten == LastWritten.KeywordOrIdentifier)
 401				Space();
 402			WritePrimitiveValue(primitiveExpression.Value);
 403			
 404			return EndNode(primitiveExpression);
 405		}
 406		
 407		public object VisitInstanceExpression(InstanceExpression instanceExpression, object data)
 408		{
 409			StartNode(instanceExpression);
 410			
 411			switch (instanceExpression.Type) {
 412				case InstanceExpressionType.Me:
 413					WriteKeyword("Me");
 414					break;
 415				case InstanceExpressionType.MyBase:
 416					WriteKeyword("MyBase");
 417					break;
 418				case InstanceExpressionType.MyClass:
 419					WriteKeyword("MyClass");
 420					break;
 421				default:
 422					throw new Exception("Invalid value for InstanceExpressionType");
 423			}
 424			
 425			return EndNode(instanceExpression);
 426		}
 427		
 428		public object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
 429		{
 430			StartNode(parenthesizedExpression);
 431			
 432			LPar();
 433			parenthesizedExpression.Expression.AcceptVisitor(this, data);
 434			RPar();
 435			
 436			return EndNode(parenthesizedExpression);
 437		}
 438		
 439		public object VisitGetTypeExpression(GetTypeExpression getTypeExpression, object data)
 440		{
 441			StartNode(getTypeExpression);
 442			
 443			WriteKeyword("GetType");
 444			LPar();
 445			getTypeExpression.Type.AcceptVisitor(this, data);
 446			RPar();
 447			
 448			return EndNode(getTypeExpression);
 449		}
 450		
 451		public object VisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, object data)
 452		{
 453			StartNode(typeOfIsExpression);
 454			
 455			WriteKeyword("TypeOf");
 456			typeOfIsExpression.TypeOfExpression.AcceptVisitor(this, data);
 457			WriteKeyword("Is");
 458			typeOfIsExpression.Type.AcceptVisitor(this, data);
 459			
 460			return EndNode(typeOfIsExpression);
 461		}
 462		
 463		public object VisitGetXmlNamespaceExpression(GetXmlNamespaceExpression getXmlNamespaceExpression, object data)
 464		{
 465			throw new NotImplementedException();
 466		}
 467		
 468		public object VisitMemberAccessExpression(MemberAccessExpression memberAccessExpression, object data)
 469		{
 470			StartNode(memberAccessExpression);
 471			
 472			memberAccessExpression.Target.AcceptVisitor(this, data);
 473			WriteToken(".", MemberAccessExpression.Roles.Dot);
 474			memberAccessExpression.MemberName.AcceptVisitor(this, data);
 475			WriteTypeArguments(memberAccessExpression.TypeArguments);
 476			
 477			return EndNode(memberAccessExpression);
 478		}
 479		
 480		public object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data)
 481		{
 482			StartNode(typeReferenceExpression);
 483			
 484			typeReferenceExpression.Type.AcceptVisitor(this, data);
 485			
 486			return EndNode(typeReferenceExpression);
 487		}
 488		
 489		public object VisitEventMemberSpecifier(EventMemberSpecifier eventMemberSpecifier, object data)
 490		{
 491			StartNode(eventMemberSpecifier);
 492			
 493			eventMemberSpecifier.Target.AcceptVisitor(this, data);
 494			WriteToken(".", EventMemberSpecifier.Roles.Dot);
 495			eventMemberSpecifier.Member.AcceptVisitor(this, data);
 496			
 497			return EndNode(eventMemberSpecifier);
 498		}
 499		
 500		public object VisitInterfaceMemberSpecifier(InterfaceMemberSpecifier interfaceMemberSpecifier, object data)
 501		{
 502			StartNode(interfaceMemberSpecifier);
 503			
 504			interfaceMemberSpecifier.Target.AcceptVisitor(this, data);
 505			WriteToken(".", EventMemberSpecifier.Roles.Dot);
 506			interfaceMemberSpecifier.Member.AcceptVisitor(this, data);
 507			
 508			return EndNode(interfaceMemberSpecifier);
 509		}
 510		
 511		#region TypeMembers
 512		public object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
 513		{
 514			StartNode(constructorDeclaration);
 515			
 516			WriteAttributes(constructorDeclaration.Attributes);
 517			WriteModifiers(constructorDeclaration.ModifierTokens);
 518			WriteKeyword("Sub");
 519			WriteKeyword("New");
 520			WriteCommaSeparatedListInParenthesis(constructorDeclaration.Parameters, false);
 521			MarkFoldStart();
 522			NewLine();
 523			
 524			Indent();
 525			WriteBlock(constructorDeclaration.Body);
 526			Unindent();
 527			
 528			WriteKeyword("End");
 529			WriteKeyword("Sub");
 530			MarkFoldEnd();
 531			NewLine();
 532			
 533			return EndNode(constructorDeclaration);
 534		}
 535		
 536		public object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
 537		{
 538			StartNode(methodDeclaration);
 539			
 540			WriteAttributes(methodDeclaration.Attributes);
 541			WriteModifiers(methodDeclaration.ModifierTokens);
 542			if (methodDeclaration.IsSub)
 543				WriteKeyword("Sub");
 544			else
 545				WriteKeyword("Function");
 546			methodDeclaration.Name.AcceptVisitor(this, data);
 547			WriteTypeParameters(methodDeclaration.TypeParameters);
 548			WriteCommaSeparatedListInParenthesis(methodDeclaration.Parameters, false);
 549			if (!methodDeclaration.IsSub && !methodDeclaration.ReturnType.IsNull) {
 550				Space();
 551				WriteKeyword("As");
 552				WriteAttributes(methodDeclaration.ReturnTypeAttributes);
 553				methodDeclaration.ReturnType.AcceptVisitor(this, data);
 554			}
 555			WriteHandlesClause(methodDeclaration.HandlesClause);
 556			WriteImplementsClause(methodDeclaration.ImplementsClause);
 557			if (!methodDeclaration.Body.IsNull) {
 558				MarkFoldStart();
 559				NewLine();
 560				Indent();
 561				WriteBlock(methodDeclaration.Body);
 562				Unindent();
 563				WriteKeyword("End");
 564				if (methodDeclaration.IsSub)
 565					WriteKeyword("Sub");
 566				else
 567					WriteKeyword("Function");
 568				MarkFoldEnd();
 569			}
 570			NewLine();
 571			
 572			return EndNode(methodDeclaration);
 573		}
 574
 575		public object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data)
 576		{
 577			StartNode(fieldDeclaration);
 578			
 579			WriteAttributes(fieldDeclaration.Attributes);
 580			WriteModifiers(fieldDeclaration.ModifierTokens);
 581			WriteCommaSeparatedList(fieldDeclaration.Variables);
 582			NewLine();
 583			
 584			return EndNode(fieldDeclaration);
 585		}
 586		
 587		public object VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data)
 588		{
 589			StartNode(propertyDeclaration);
 590			
 591			WriteAttributes(propertyDeclaration.Attributes);
 592			WriteModifiers(propertyDeclaration.ModifierTokens);
 593			WriteKeyword("Property");
 594			WriteIdentifier(propertyDeclaration.Name.Name);
 595			WriteCommaSeparatedListInParenthesis(propertyDeclaration.Parameters, false);
 596			if (!propertyDeclaration.ReturnType.IsNull) {
 597				Space();
 598				WriteKeyword("As");
 599				WriteAttributes(propertyDeclaration.ReturnTypeAttributes);
 600				propertyDeclaration.ReturnType.AcceptVisitor(this, data);
 601			}
 602			
 603			bool needsBody = !propertyDeclaration.Getter.Body.IsNull || !propertyDeclaration.Setter.Body.IsNull;
 604			
 605			if (needsBody) {
 606				MarkFoldStart();
 607				NewLine();
 608				Indent();
 609				
 610				if (!propertyDeclaration.Getter.Body.IsNull) {
 611					propertyDeclaration.Getter.AcceptVisitor(this, data);
 612				}
 613				
 614				if (!propertyDeclaration.Setter.Body.IsNull) {
 615					propertyDeclaration.Setter.AcceptVisitor(this, data);
 616				}
 617				Unindent();
 618				
 619				WriteKeyword("End");
 620				WriteKeyword("Property");
 621				MarkFoldEnd();
 622			}
 623			NewLine();
 624			
 625			return EndNode(propertyDeclaration);
 626		}
 627		#endregion
 628		
 629		#region TypeName
 630		public object VisitPrimitiveType(PrimitiveType primitiveType, object data)
 631		{
 632			StartNode(primitiveType);
 633			
 634			WriteKeyword(primitiveType.Keyword);
 635			
 636			return EndNode(primitiveType);
 637		}
 638		
 639		public object VisitQualifiedType(QualifiedType qualifiedType, object data)
 640		{
 641			StartNode(qualifiedType);
 642			
 643			qualifiedType.Target.AcceptVisitor(this, data);
 644			WriteToken(".", AstNode.Roles.Dot);
 645			WriteIdentifier(qualifiedType.Name);
 646			WriteTypeArguments(qualifiedType.TypeArguments);
 647			
 648			return EndNode(qualifiedType);
 649		}
 650		
 651		public object VisitComposedType(ComposedType composedType, object data)
 652		{
 653			StartNode(composedType);
 654			
 655			composedType.BaseType.AcceptVisitor(this, data);
 656			if (composedType.HasNullableSpecifier)
 657				WriteToken("?", ComposedType.Roles.QuestionMark);
 658			WriteArraySpecifiers(composedType.ArraySpecifiers);
 659			
 660			return EndNode(composedType);
 661		}
 662		
 663		public object VisitArraySpecifier(ArraySpecifier arraySpecifier, object data)
 664		{
 665			StartNode(arraySpecifier);
 666			
 667			LPar();
 668			for (int i = 0; i < arraySpecifier.Dimensions - 1; i++) {
 669				WriteToken(",", ArraySpecifier.Roles.Comma);
 670			}
 671			RPar();
 672			
 673			return EndNode(arraySpecifier);
 674		}
 675		
 676		public object VisitSimpleType(SimpleType simpleType, object data)
 677		{
 678			StartNode(simpleType);
 679			
 680			WriteIdentifier(simpleType.Identifier);
 681			WriteTypeArguments(simpleType.TypeArguments);
 682			
 683			return EndNode(simpleType);
 684		}
 685		#endregion
 686		
 687		#region StartNode/EndNode
 688		void StartNode(AstNode node)
 689		{
 690			// Ensure that nodes are visited in the proper nested order.
 691			// Jumps to different subtrees are allowed only for the child of a placeholder node.
 692			Debug.Assert(containerStack.Count == 0 || node.Parent == containerStack.Peek());
 693			if (positionStack.Count > 0)
 694				WriteSpecialsUpToNode(node);
 695			containerStack.Push(node);
 696			positionStack.Push(node.FirstChild);
 697			formatter.StartNode(node);
 698		}
 699		
 700		object EndNode(AstNode node)
 701		{
 702			Debug.Assert(node == containerStack.Peek());
 703			AstNode pos = positionStack.Pop();
 704			Debug.Assert(pos == null || pos.Parent == node);
 705			WriteSpecials(pos, null);
 706			containerStack.Pop();
 707			formatter.EndNode(node);
 708			return null;
 709		}
 710		#endregion
 711		
 712		#region WriteSpecials
 713		/// <summary>
 714		/// Writes all specials from start to end (exclusive). Does not touch the positionStack.
 715		/// </summary>
 716		void WriteSpecials(AstNode start, AstNode end)
 717		{
 718			for (AstNode pos = start; pos != end; pos = pos.NextSibling) {
 719				if (pos.Role == AstNode.Roles.Comment) {
 720					pos.AcceptVisitor(this, null);
 721				}
 722			}
 723		}
 724		
 725		/// <summary>
 726		/// Writes all specials between the current position (in the positionStack) and the next
 727		/// node with the specified role. Advances the current position.
 728		/// </summary>
 729		void WriteSpecialsUpToRole(Role role)
 730		{
 731			for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) {
 732				if (pos.Role == role) {
 733					WriteSpecials(positionStack.Pop(), pos);
 734					positionStack.Push(pos);
 735					break;
 736				}
 737			}
 738		}
 739		
 740		/// <summary>
 741		/// Writes all specials between the current position (in the positionStack) and the specified node.
 742		/// Advances the current position.
 743		/// </summary>
 744		void WriteSpecialsUpToNode(AstNode node)
 745		{
 746			for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) {
 747				if (pos == node) {
 748					WriteSpecials(positionStack.Pop(), pos);
 749					positionStack.Push(pos);
 750					break;
 751				}
 752			}
 753		}
 754		
 755		void WriteSpecialsUpToRole(Role role, AstNode nextNode)
 756		{
 757			// Look for the role between the current position and the nextNode.
 758			for (AstNode pos = positionStack.Peek(); pos != null && pos != nextNode; pos = pos.NextSibling) {
 759				if (pos.Role == AstNode.Roles.Comma) {
 760					WriteSpecials(positionStack.Pop(), pos);
 761					positionStack.Push(pos);
 762					break;
 763				}
 764			}
 765		}
 766		#endregion
 767		
 768		#region Comma
 769		/// <summary>
 770		/// Writes a comma.
 771		/// </summary>
 772		/// <param name="nextNode">The next node after the comma.</param>
 773		/// <param name="noSpacesAfterComma">When set prevents printing a space after comma.</param>
 774		void Comma(AstNode nextNode, bool noSpaceAfterComma = false)
 775		{
 776			WriteSpecialsUpToRole(AstNode.Roles.Comma, nextNode);
 777			formatter.WriteToken(",");
 778			lastWritten = LastWritten.Other;
 779			Space(!noSpaceAfterComma); // TODO: Comma policy has changed.
 780		}
 781		
 782		void WriteCommaSeparatedList(IEnumerable<AstNode> list)
 783		{
 784			bool isFirst = true;
 785			foreach (AstNode node in list) {
 786				if (isFirst) {
 787					isFirst = false;
 788				} else {
 789					Comma(node);
 790				}
 791				node.AcceptVisitor(this, null);
 792			}
 793		}
 794		
 795		void WriteCommaSeparatedListInParenthesis(IEnumerable<AstNode> list, bool spaceWithin)
 796		{
 797			LPar();
 798			if (list.Any()) {
 799				Space(spaceWithin);
 800				WriteCommaSeparatedList(list);
 801				Space(spaceWithin);
 802			}
 803			RPar();
 804		}
 805		
 806		#if DOTNET35
 807		void WriteCommaSeparatedList(IEnumerable<VariableInitializer> list)
 808		{
 809			WriteCommaSeparatedList(list);
 810		}
 811		
 812		void WriteCommaSeparatedList(IEnumerable<AstType> list)
 813		{
 814			WriteCommaSeparatedList(list);
 815		}
 816		
 817		void WriteCommaSeparatedListInParenthesis(IEnumerable<Expression> list, bool spaceWithin)
 818		{
 819			WriteCommaSeparatedListInParenthesis(list.SafeCast<Expression, AstNode>(), spaceWithin);
 820		}
 821		
 822		void WriteCommaSeparatedListInParenthesis(IEnumerable<ParameterDeclaration> list, bool spaceWithin)
 823		{
 824			WriteCommaSeparatedListInParenthesis(list.SafeCast<ParameterDeclaration, AstNode>(), spaceWithin);
 825		}
 826
 827		#endif
 828
 829		void WriteCommaSeparatedListInBrackets(IEnumerable<ParameterDeclaration> list, bool spaceWithin)
 830		{
 831			WriteToken("[", AstNode.Roles.LBracket);
 832			if (list.Any()) {
 833				Space(spaceWithin);
 834				WriteCommaSeparatedList(list);
 835				Space(spaceWithin);
 836			}
 837			WriteToken("]", AstNode.Roles.RBracket);
 838		}
 839		#endregion
 840		
 841		#region Write tokens
 842		/// <summary>
 843		/// Writes a keyword, and all specials up to
 844		/// </summary>
 845		void WriteKeyword(string keyword, Role<VBTokenNode> tokenRole = null)
 846		{
 847			WriteSpecialsUpToRole(tokenRole ?? AstNode.Roles.Keyword);
 848			if (lastWritten == LastWritten.KeywordOrIdentifier)
 849				formatter.Space();
 850			formatter.WriteKeyword(keyword);
 851			lastWritten = LastWritten.KeywordOrIdentifier;
 852		}
 853		
 854		void WriteIdentifier(string identifier, Role<Identifier> identifierRole = null)
 855		{
 856			WriteSpecialsUpToRole(identifierRole ?? AstNode.Roles.Identifier);
 857			if (IsKeyword(identifier, containerStack.Peek())) {
 858				if (lastWritten == LastWritten.KeywordOrIdentifier)
 859					Space(); // this space is not strictly required, so we call Space()
 860				formatter.WriteToken("[");
 861			} else if (lastWritten == LastWritten.KeywordOrIdentifier) {
 862				formatter.Space(); // this space is strictly required, so we directly call the formatter
 863			}
 864			formatter.WriteIdentifier(identifier);
 865			if (IsKeyword(identifier, containerStack.Peek())) {
 866				formatter.WriteToken("]");
 867			}
 868			lastWritten = LastWritten.KeywordOrIdentifier;
 869		}
 870		
 871		void WriteToken(string token, Role<VBTokenNode> tokenRole)
 872		{
 873			WriteSpecialsUpToRole(tokenRole);
 874			// Avoid that two +, - or ? tokens are combined into a ++, -- or ?? token.
 875			// Note that we don't need to handle tokens like = because there's no valid
 876			// C# program that contains the single token twice in a row.
 877			// (for +, - and &, this can happen with unary operators;
 878			// for ?, this can happen in "a is int? ? b : c" or "a as int? ?? 0";
 879			// and for /, this can happen with "1/ *ptr" or "1/ //comment".)
 880//			if (lastWritten == LastWritten.Plus && token[0] == '+'
 881//			    || lastWritten == LastWritten.Minus && token[0] == '-'
 882//			    || lastWritten == LastWritten.Ampersand && token[0] == '&'
 883//			    || lastWritten == LastWritten.QuestionMark && token[0] == '?'
 884//			    || lastWritten == LastWritten.Division && token[0] == '*')
 885//			{
 886//				formatter.Space();
 887//			}
 888			formatter.WriteToken(token);
 889//			if (token == "+")
 890//				lastWritten = LastWritten.Plus;
 891//			else if (token == "-")
 892//				lastWritten = LastWritten.Minus;
 893//			else if (token == "&")
 894//				lastWritten = LastWritten.Ampersand;
 895//			else if (token == "?")
 896//				lastWritten = LastWritten.QuestionMark;
 897//			else if (token == "/")
 898//				lastWritten = LastWritten.Division;
 899//			else
 900			lastWritten = LastWritten.Other;
 901		}
 902		
 903		void WriteTypeCharacter(TypeCode typeCharacter)
 904		{
 905			switch (typeCharacter) {
 906				case TypeCode.Empty:
 907				case TypeCode.Object:
 908				case TypeCode.DBNull:
 909				case TypeCode.Boolean:
 910				case TypeCode.Char:
 911					
 912					break;
 913				case TypeCode.SByte:
 914					
 915					break;
 916				case TypeCode.Byte:
 917					
 918					break;
 919				case TypeCode.Int16:
 920					
 921					break;
 922				case TypeCode.UInt16:
 923					
 924					break;
 925				case TypeCode.Int32:
 926					WriteToken("%", null);
 927					break;
 928				case TypeCode.UInt32:
 929					
 930					break;
 931				case TypeCode.Int64:
 932					WriteToken("&", null);
 933					break;
 934				case TypeCode.UInt64:
 935					
 936					break;
 937				case TypeCode.Single:
 938					WriteToken("!", null);
 939					break;
 940				case TypeCode.Double:
 941					WriteToken("#", null);
 942					break;
 943				case TypeCode.Decimal:
 944					WriteToken("@", null);
 945					break;
 946				case TypeCode.DateTime:
 947					
 948					break;
 949				case TypeCode.String:
 950					WriteToken("$", null);
 951					break;
 952				default:
 953					throw new Exception("Invalid value for TypeCode");
 954			}
 955		}
 956		
 957		void LPar()
 958		{
 959			WriteToken("(", AstNode.Roles.LPar);
 960		}
 961		
 962		void RPar()
 963		{
 964			WriteToken(")", AstNode.Roles.LPar);
 965		}
 966		
 967		/// <summary>
 968		/// Writes a space depending on policy.
 969		/// </summary>
 970		void Space(bool addSpace = true)
 971		{
 972			if (addSpace) {
 973				formatter.Space();
 974				lastWritten = LastWritten.Whitespace;
 975			}
 976		}
 977		
 978		void NewLine()
 979		{
 980			formatter.NewLine();
 981			lastWritten = LastWritten.Whitespace;
 982		}
 983		
 984		void Indent()
 985		{
 986			formatter.Indent();
 987		}
 988		
 989		void Unindent()
 990		{
 991			formatter.Unindent();
 992		}
 993		
 994		void MarkFoldStart()
 995		{
 996			formatter.MarkFoldStart();
 997		}
 998		
 999		void MarkFoldEnd()
1000		{
1001			formatter.MarkFoldEnd();
1002		}
1003		#endregion
1004		
1005		#region IsKeyword Test
1006		static readonly HashSet<string> unconditionalKeywords = new HashSet<string>(StringComparer.OrdinalIgnoreCase) {
1007			"AddHandler", "AddressOf", "Alias", "And", "AndAlso", "As", "Boolean", "ByRef", "Byte",
1008			"ByVal", "Call", "Case", "Catch", "CBool", "CByte", "CChar", "CInt", "Class", "CLng",
1009			"CObj", "Const", "Continue", "CSByte", "CShort", "CSng", "CStr", "CType", "CUInt",
1010			"CULng", "CUShort", "Date", "Decimal", "Declare", "Default", "Delegate", "Dim",
1011			"DirectCast", "Do", "Double", "Each", "Else", "ElseIf", "End", "EndIf", "Enum", "Erase",
1012			"Error", "Event", "Exit", "False", "Finally", "For", "Friend", "Function", "Get",
1013			"GetType", "GetXmlNamespace", "Global", "GoSub", "GoTo", "Handles", "If", "Implements",
1014			"Imports", "In", "Inherits", "Integer", "Interface", "Is", "IsNot", "Let", "Lib", "Like",
1015			"Long", "Loop", "Me", "Mod", "Module", "MustInherit", "MustOverride", "MyBase", "MyClass",
1016			"Namespace", "Narrowing", "New", "Next", "Not", "Nothing", "NotInheritable", "NotOverridable",
1017			"Object", "Of", "On", "Operator", "Option", "Optional", "Or", "OrElse", "Overloads",
1018			"Overridable", "Overrides", "ParamArray", "Partial", "Private", "Property", "Protected",
1019			"Public", "RaiseEvent", "ReadOnly", "ReDim", "REM", "RemoveHandler", "Resume", "Return",
1020			"SByte", "Select", "Set", "Shadows", "Shared", "Short", "Single", "Static", "Step", "Stop",
1021			"String", "Structure", "Sub", "SyncLock", "Then", "Throw", "To", "True", "Try", "TryCast",
1022			"TypeOf", "UInteger", "ULong", "UShort", "Using", "Variant", "Wend", "When", "While",
1023			"Widening", "With", "WithEvents", "WriteOnly", "Xor"
1024		};
1025		
1026		static readonly HashSet<string> queryKeywords = new HashSet<string> {
1027			
1028		};
1029		
1030		/// <summary>
1031		/// Determines whether the specified identifier is a keyword in the given context.
1032		/// </summary>
1033		public static bool IsKeyword(string identifier, AstNode context)
1034		{
1035			if (unconditionalKeywords.Contains(identifier))
1036				return true;
1037//			if (context.Ancestors.Any(a => a is QueryExpression)) {
1038//				if (queryKeywords.Contains(identifier))
1039//					return true;
1040//			}
1041			return false;
1042		}
1043		#endregion
1044		
1045		#region Write constructs
1046		void WriteTypeArguments(IEnumerable<AstType> typeArguments)
1047		{
1048			if (typeArguments.Any()) {
1049				LPar();
1050				WriteKeyword("Of");
1051				WriteCommaSeparatedList(typeArguments);
1052				RPar();
1053			}
1054		}
1055		
1056		void WriteTypeParameters(IEnumerable<TypeParameterDeclaration> typeParameters)
1057		{
1058			if (typeParameters.Any()) {
1059				LPar();
1060				WriteKeyword("Of");
1061				WriteCommaSeparatedList(typeParameters);
1062				RPar();
1063			}
1064		}
1065		
1066		void WriteModifiers(IEnumerable<VBModifierToken> modifierTokens)
1067		{
1068			foreach (VBModifierToken modifier in modifierTokens) {
1069				modifier.AcceptVisitor(this, null);
1070			}
1071		}
1072		
1073		void WriteArraySpecifiers(IEnumerable<ArraySpecifier> arraySpecifiers)
1074		{
1075			foreach (ArraySpecifier specifier in arraySpecifiers) {
1076				specifier.AcceptVisitor(this, null);
1077			}
1078		}
1079		
1080		void WriteQualifiedIdentifier(IEnumerable<Identifier> identifiers)
1081		{
1082			bool first = true;
1083			foreach (Identifier ident in identifiers) {
1084				if (first) {
1085					first = false;
1086					if (lastWritten == LastWritten.KeywordOrIdentifier)
1087						formatter.Space();
1088				} else {
1089					WriteSpecialsUpToRole(AstNode.Roles.Dot, ident);
1090					formatter.WriteToken(".");
1091					lastWritten = LastWritten.Other;
1092				}
1093				WriteSpecialsUpToNode(ident);
1094				formatter.WriteIdentifier(ident.Name);
1095				lastWritten = LastWritten.KeywordOrIdentifier;
1096			}
1097		}
1098		
1099		void WriteEmbeddedStatement(Statement embeddedStatement)
1100		{
1101			if (embeddedStatement.IsNull)
1102				return;
1103			BlockStatement block = embeddedStatement as BlockStatement;
1104			if (block != null)
1105				VisitBlockStatement(block, null);
1106			else
1107				embeddedStatement.AcceptVisitor(this, null);
1108		}
1109		
1110		void WriteBlock(BlockStatement body)
1111		{
1112			if (body.IsNull)
1113				NewLine();
1114			else
1115				VisitBlockStatement(body, null);
1116		}
1117		
1118		void WriteMembers(IEnumerable<AstNode> members)
1119		{
1120			Indent();
1121			bool isFirst = true;
1122			foreach (var member in members) {
1123				if (isFirst) {
1124					isFirst = false;
1125				} else {
1126					NewLine();
1127				}
1128				member.AcceptVisitor(this, null);
1129			}
1130			Unindent();
1131		}
1132		
1133		void WriteAttributes(IEnumerable<AttributeBlock> attributes)
1134		{
1135			foreach (AttributeBlock attr in attributes) {
1136				attr.AcceptVisitor(this, null);
1137			}
1138		}
1139		
1140		void WritePrivateImplementationType(AstType privateImplementationType)
1141		{
1142			if (!privateImplementationType.IsNull) {
1143				privateImplementationType.AcceptVisitor(this, null);
1144				WriteToken(".", AstNode.Roles.Dot);
1145			}
1146		}
1147		
1148		void WriteImplementsClause(AstNodeCollection<InterfaceMemberSpecifier> implementsClause)
1149		{
1150			if (implementsClause.Any()) {
1151				Space();
1152				WriteKeyword("Implements");
1153				WriteCommaSeparatedList(implementsClause);
1154			}
1155		}
1156		
1157		void WriteImplementsClause(AstNodeCollection<AstType> implementsClause)
1158		{
1159			if (implementsClause.Any()) {
1160				WriteKeyword("Implements");
1161				WriteCommaSeparatedList(implementsClause);
1162			}
1163		}
1164		
1165		void WriteHandlesClause(AstNodeCollection<EventMemberSpecifier> handlesClause)
1166		{
1167			if (handlesClause.Any()) {
1168				Space();
1169				WriteKeyword("Handles");
1170				WriteCommaSeparatedList(handlesClause);
1171			}
1172		}
1173		
1174		void WritePrimitiveValue(object val)
1175		{
1176			if (val == null) {
1177				WriteKeyword("Nothing");
1178				return;
1179			}
1180			
1181			if (val is bool) {
1182				if ((bool)val) {
1183					WriteKeyword("True");
1184				} else {
1185					WriteKeyword("False");
1186				}
1187				return;
1188			}
1189			
1190			if (val is string) {
1191				formatter.WriteToken("\"" + ConvertString(val.ToString()) + "\"");
1192				lastWritten = LastWritten.Other;
1193			} else if (val is char) {
1194				formatter.WriteToken("\"" + ConvertCharLiteral((char)val) + "\"c");
1195				lastWritten = LastWritten.Other;
1196			} else if (val is decimal) {
1197				formatter.WriteToken(((decimal)val).ToString(NumberFormatInfo.InvariantInfo) + "D");
1198				lastWritten = LastWritten.Other;
1199			} else if (val is float) {
1200				float f = (float)val;
1201				if (float.IsInfinity(f) || float.IsNaN(f)) {
1202					// Strictly speaking, these aren't PrimitiveExpressions;
1203					// but we still support writing these to make life easier for code generators.
1204					WriteKeyword("Single");
1205					WriteToken(".", AstNode.Roles.Dot);
1206					if (float.IsPositiveInfinity(f))
1207						WriteIdentifier("PositiveInfinity");
1208					else if (float.IsNegativeInfinity(f))
1209						WriteIdentifier("NegativeInfinity");
1210					else
1211						WriteIdentifier("NaN");
1212					return;
1213				}
1214				formatter.WriteToken(f.ToString("R", NumberFormatInfo.InvariantInfo) + "F");
1215				lastWritten = LastWritten.Other;
1216			} else if (val is double) {
1217				double f = (double)val;
1218				if (double.IsInfinity(f) || double.IsNaN(f)) {
1219					// Strictly speaking, these aren't PrimitiveExpressions;
1220					// but we still support writing these to make life easier for code generators.
1221					WriteKeyword("Double");
1222					WriteToken(".", AstNode.Roles.Dot);
1223					if (double.IsPositiveInfinity(f))
1224						WriteIdentifier("PositiveInfinity");
1225					else if (double.IsNegativeInfinity(f))
1226						WriteIdentifier("NegativeInfinity");
1227					else
1228						WriteIdentifier("NaN");
1229					return;
1230				}
1231				string number = f.ToString("R", NumberFormatInfo.InvariantInfo);
1232				if (number.IndexOf('.') < 0 && number.IndexOf('E') < 0)
1233					number += ".0";
1234				formatter.WriteToken(number);
1235				// needs space if identifier follows number; this avoids mistaking the following identifier as type suffix
1236				lastWritten = LastWritten.KeywordOrIdentifier;
1237			} else if (val is IFormattable) {
1238				StringBuilder b = new StringBuilder();
1239//				if (primitiveExpression.LiteralFormat == LiteralFormat.HexadecimalNumber) {
1240//					b.Append("0x");
1241//					b.Append(((IFormattable)val).ToString("x", NumberFormatInfo.InvariantInfo));
1242//				} else {
1243				b.Append(((IFormattable)val).ToString(null, NumberFormatInfo.InvariantInfo));
1244//				}
1245				if (val is uint || val is ulong) {
1246					b.Append("U");
1247				}
1248				if (val is long || val is ulong) {
1249					b.Append("L");
1250				}
1251				formatter.WriteToken(b.ToString());
1252				// needs space if identifier follows number; this avoids mistaking the following identifier as type suffix
1253				lastWritten = LastWritten.KeywordOrIdentifier;
1254			} else {
1255				formatter.WriteToken(val.ToString());
1256				lastWritten = LastWritten.Other;
1257			}
1258		}
1259		#endregion
1260		
1261		#region ConvertLiteral
1262		static string ConvertCharLiteral(char ch)
1263		{
1264			if (ch == '"') return "\"\"";
1265			return ch.ToString();
1266		}
1267		
1268		static string ConvertString(string str)
1269		{
1270			StringBuilder sb = new StringBuilder();
1271			foreach (char ch in str) {
1272				sb.Append(ConvertCharLiteral(ch));
1273			}
1274			return sb.ToString();
1275		}
1276		#endregion
1277		
1278		public object VisitVariableIdentifier(VariableIdentifier variableIdentifier, object data)
1279		{
1280			StartNode(variableIdentifier);
1281			
1282			WriteIdentifier(variableIdentifier.Name.Name);
1283			if (variableIdentifier.HasNullableSpecifier)
1284				WriteToken("?", VariableIdentifier.Roles.QuestionMark);
1285			if (variableIdentifier.ArraySizeSpecifiers.Count > 0)
1286				WriteCommaSeparatedListInParenthesis(variableIdentifier.ArraySizeSpecifiers, false);
1287			WriteArraySpecifiers(variableIdentifier.ArraySpecifiers);
1288			
1289			return EndNode(variableIdentifier);
1290		}
1291		
1292		public object VisitAccessor(Accessor accessor, object data)
1293		{
1294			StartNode(accessor);
1295			WriteAttributes(accessor.Attributes);
1296			WriteModifiers(accessor.ModifierTokens);
1297			if (accessor.Role == PropertyDeclaration.GetterRole) {
1298				WriteKeyword("Get");
1299			} else if (accessor.Role == PropertyDeclaration.SetterRole) {
1300				WriteKeyword("Set");
1301			} else if (accessor.Role == EventDeclaration.AddHandlerRole) {
1302				WriteKeyword("AddHandler");
1303			} else if (accessor.Role == EventDeclaration.RemoveHandlerRole) {
1304				WriteKeyword("RemoveHandler");
1305			} else if (accessor.Role == EventDeclaration.RaiseEventRole) {
1306				WriteKeyword("RaiseEvent");
1307			}
1308			if (accessor.Parameters.Any())
1309				WriteCommaSeparatedListInParenthesis(accessor.Parameters, false);
1310			NewLine();
1311			Indent();
1312			WriteBlock(accessor.Body);
1313			Unindent();
1314			WriteKeyword("End");
1315
1316			if (accessor.Role == PropertyDeclaration.GetterRole) {
1317				WriteKeyword("Get");
1318			} else if (accessor.Role == PropertyDeclaration.SetterRole) {
1319				WriteKeyword("Set");
1320			} else if (accessor.Role == EventDeclaration.AddHandlerRole) {
1321				WriteKeyword("AddHandler");
1322			} else if (accessor.Role == EventDeclaration.RemoveHandlerRole) {
1323				WriteKeyword("RemoveHandler");
1324			} else if (accessor.Role == EventDeclaration.RaiseEventRole) {
1325				WriteKeyword("RaiseEvent");
1326			}
1327			NewLine();
1328			
1329			return EndNode(accessor);
1330		}
1331
1332		
1333		public object VisitLabelDeclarationStatement(LabelDeclarationStatement labelDeclarationStatement, object data)
1334		{
1335			StartNode(labelDeclarationStatement);
1336			
1337			labelDeclarationStatement.Label.AcceptVisitor(this, data);
1338			WriteToken(":", LabelDeclarationStatement.Roles.Colon);
1339			
1340			return EndNode(labelDeclarationStatement);
1341		}
1342		
1343		public object VisitLocalDeclarationStatement(LocalDeclarationStatement localDeclarationStatement, object data)
1344		{
1345			StartNode(localDeclarationStatement);
1346			
1347			if (localDeclarationStatement.ModifierToken != null && !localDeclarationStatement.ModifierToken.IsNull)
1348				WriteModifiers(new [] { localDeclarationStatement.ModifierToken });
1349			WriteCommaSeparatedList(localDeclarationStatement.Variables);
1350			
1351			return EndNode(localDeclarationStatement);
1352		}
1353		
1354		public object VisitWithStatement(WithStatement withStatement, object data)
1355		{
1356			StartNode(withStatement);
1357			WriteKeyword("With");
1358			withStatement.Expression.AcceptVisitor(this, data);
1359			NewLine();
1360			Indent();
1361			withStatement.Body.AcceptVisitor(this, data);
1362			Unindent();
1363			WriteKeyword("End");
1364			WriteKeyword("With");
1365			return EndNode(withStatement);
1366		}
1367		
1368		public object VisitSyncLockStatement(SyncLockStatement syncLockStatement, object data)
1369		{
1370			StartNode(syncLockStatement);
1371			WriteKeyword("SyncLock");
1372			syncLockStatement.Expression.AcceptVisitor(this, data);
1373			NewLine();
1374			Indent();
1375			syncLockStatement.Body.AcceptVisitor(this, data);
1376			Unindent();
1377			WriteKeyword("End");
1378			WriteKeyword("SyncLock");
1379			return EndNode(syncLockStatement);
1380		}
1381		
1382		public object VisitTryStatement(TryStatement tryStatement, object data)
1383		{
1384			StartNode(tryStatement);
1385			WriteKeyword("Try");
1386			NewLine();
1387			Indent();
1388			tryStatement.Body.AcceptVisitor(this, data);
1389			Unindent();
1390			foreach (var clause in tryStatement.CatchBlocks) {
1391				clause.AcceptVisitor(this, data);
1392			}
1393			if (!tryStatement.FinallyBlock.IsNull) {
1394				WriteKeyword("Finally");
1395				NewLine();
1396				Indent();
1397				tryStatement.FinallyBlock.AcceptVisitor(this, data);
1398				Unindent();
1399			}
1400			WriteKeyword("End");
1401			WriteKeyword("Try");
1402			return EndNode(tryStatement);
1403		}
1404		
1405		public object VisitCatchBlock(CatchBlock catchBlock, object data)
1406		{
1407			StartNode(catchBlock);
1408			WriteKeyword("Catch");
1409			catchBlock.ExceptionVariable.AcceptVisitor(this, data);
1410			if (!catchBlock.ExceptionType.IsNull) {
1411				WriteKeyword("As");
1412				catchBlock.ExceptionType.AcceptVisitor(this, data);
1413			}
1414			NewLine();
1415			Indent();
1416			foreach (var stmt in catchBlock) {
1417				stmt.AcceptVisitor(this, data);
1418				NewLine();
1419			}
1420			Unindent();
1421			return EndNode(catchBlock);
1422		}
1423		
1424		public object VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
1425		{
1426			StartNode(expressionStatement);
1427			expressionStatement.Expression.AcceptVisitor(this, data);
1428			return EndNode(expressionStatement);
1429		}
1430		
1431		public object VisitThrowStatement(ThrowStatement throwStatement, object data)
1432		{
1433			StartNode(throwStatement);
1434			
1435			WriteKeyword("Throw");
1436			throwStatement.Expression.AcceptVisitor(this, data);
1437			
1438			return EndNode(throwStatement);
1439		}
1440		
1441		public object VisitIfElseStatement(IfElseStatement ifElseStatement, object data)
1442		{
1443			StartNode(ifElseStatement);
1444			WriteKeyword("If");
1445			ifElseStatement.Condition.AcceptVisitor(this, data);
1446			Space();
1447			WriteKeyword("Then");
1448			NewLine();
1449			Indent();
1450			ifElseStatement.Body.AcceptVisitor(this, data);
1451			Unindent();
1452			if (!ifElseStatement.ElseBlock.IsNull) {
1453				WriteKeyword("Else");
1454				NewLine();
1455				Indent();
1456				ifElseStatement.ElseBlock.AcceptVisitor(this, data);
1457				Unindent();
1458			}
1459			WriteKeyword("End");
1460			WriteKeyword("If");
1461			return EndNode(ifElseStatement);
1462		}
1463		
1464		public object VisitReturnStatement(ReturnStatement returnStatement, object data)
1465		{
1466			StartNode(returnStatement);
1467			WriteKeyword("Return");
1468			returnStatement.Expression.AcceptVisitor(this, data);
1469			return EndNode(returnStatement);
1470		}
1471		
1472		public object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
1473		{
1474			StartNode(binaryOperatorExpression);
1475			binaryOperatorExpression.Left.AcceptVisitor(this, data);
1476			Space();
1477			switch (binaryOperatorExpression.Operator) {
1478				case BinaryOperatorType.BitwiseAnd:
1479					WriteKeyword("And");
1480					break;
1481				case BinaryOperatorType.BitwiseOr:
1482					WriteKeyword("Or");
1483					break;
1484				case BinaryOperatorType.LogicalAnd:
1485					WriteKeyword("AndAlso");
1486					break;
1487				case BinaryOperatorType.LogicalOr:
1488					WriteKeyword("OrElse");
1489					break;
1490				case BinaryOperatorType.ExclusiveOr:
1491					WriteKeyword("Xor");
1492					break;
1493				case BinaryOperatorType.GreaterThan:
1494					WriteToken(">", BinaryOperatorExpression.OperatorRole);
1495					break;
1496				case BinaryOperatorType.GreaterThanOrEqual:
1497					WriteToken(">=", BinaryOperatorExpression.OperatorRole);
1498					break;
1499				case BinaryOperatorType.Equality:
1500					WriteToken("=", BinaryOperatorExpression.OperatorRole);
1501					break;
1502				case BinaryOperatorType.InEquality:
1503					WriteToken("<>", BinaryOperatorExpression.OperatorRole);
1504					break;
1505				case BinaryOperatorType.LessThan:
1506					WriteToken("<", BinaryOperatorExpression.OperatorRole);
1507					break;
1508				case BinaryOperatorType.LessThanOrEqual:
1509					WriteToken("<=", BinaryOperatorExpression.OperatorRole);
1510					break;
1511				case BinaryOperatorType.Add:
1512					WriteToken("+", BinaryOperatorExpression.OperatorRole);
1513					break;
1514				case BinaryOperatorType.Subtract:
1515					WriteToken("-", BinaryOperatorExpression.OperatorRole);
1516					break;
1517				case BinaryOperatorType.Multiply:
1518					WriteToken("*", BinaryOperatorExpression.OperatorRole);
1519					break;
1520				case BinaryOperatorType.Divide:
1521					WriteToken("/", BinaryOperatorExpression.OperatorRole);
1522					break;
1523				case BinaryOperatorType.Modulus:
1524					WriteKeyword("Mod");
1525					break;
1526				case BinaryOperatorType.DivideInteger:
1527					WriteToken("\\", BinaryOperatorExpression.OperatorRole);
1528					break;
1529				case BinaryOperatorType.Power:
1530					WriteToken("*", BinaryOperatorExpression.OperatorRole);
1531					break;
1532				case BinaryOperatorType.Concat:
1533					WriteToken("&", BinaryOperatorExpression.OperatorRole);
1534					break;
1535				case BinaryOperatorType.ShiftLeft:
1536					WriteToken("<<", BinaryOperatorExpression.OperatorRole);
1537					break;
1538				case BinaryOperatorType.ShiftRight:
1539					WriteToken(">>", BinaryOperatorExpression.OperatorRole);
1540					break;
1541				case BinaryOperatorType.ReferenceEquality:
1542					WriteKeyword("Is");
1543					break;
1544				case BinaryOperatorType.ReferenceInequality:
1545					WriteKeyword("IsNot");
1546					break;
1547				case BinaryOperatorType.Like:
1548					WriteKeyword("Like");
1549					break;
1550				case BinaryOperatorType.DictionaryAccess:
1551					WriteToken("!", BinaryOperatorExpression.OperatorRole);
1552					break;
1553				default:
1554					throw new Exception("Invalid value for BinaryOperatorType: " + binaryOperatorExpression.Operator);
1555			}
1556			Space();
1557			binaryOperatorExpression.Right.AcceptVisitor(this, data);
1558			return EndNode(binaryOperatorExpression);
1559		}
1560		
1561		public object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
1562		{
1563			StartNode(identifierExpression);
1564			identifierExpression.Identifier.AcceptVisitor(this, data);
1565			WriteTypeArguments(identifierExpression.TypeArguments);
1566			return EndNode(identifierExpression);
1567		}
1568		
1569		public object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data)
1570		{
1571			StartNode(assignmentExpression);
1572			assignmentExpression.Left.AcceptVisitor(this, data);
1573			Space();
1574			switch (assignmentExpression.Operator) {
1575				case AssignmentOperatorType.Assign:
1576					WriteToken("=", AssignmentExpression.OperatorRole);
1577					break;
1578				case AssignmentOperatorType.Add:
1579					WriteToken("+=", AssignmentExpression.OperatorRole);
1580					break;
1581				case AssignmentOperatorType.Subtract:
1582					WriteToken("-=", AssignmentExpression.OperatorRole);
1583					break;
1584				case AssignmentOperatorType.Multiply:
1585					WriteToken("*=", AssignmentExpression.OperatorRole);
1586					break;
1587				case AssignmentOperatorType.Divide:
1588					WriteToken("/=", AssignmentExpression.OperatorRole);
1589					break;
1590				case AssignmentOperatorType.Power:
1591					WriteToken("^=", AssignmentExpression.OperatorRole);
1592					break;
1593				case AssignmentOperatorType.DivideInteger:
1594					WriteToken("\\=", AssignmentExpression.OperatorRole);
1595					break;
1596				case AssignmentOperatorType.ConcatString:
1597					WriteToken("&=", AssignmentExpression.OperatorRole);
1598					break;
1599				case AssignmentOperatorType.ShiftLeft:
1600					WriteToken("<<=", AssignmentExpression.OperatorRole);
1601					break;
1602				case AssignmentOperatorType.ShiftRight:
1603					WriteToken(">>=", AssignmentExpression.OperatorRole);
1604					break;
1605				default:
1606					throw new Exception("Invalid value for AssignmentOperatorType: " + assignmentExpression.Operator);
1607			}
1608			Space();
1609			assignmentExpression.Right.AcceptVisitor(this, data);
1610			return EndNode(assignmentExpression);
1611		}
1612		
1613		public object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
1614		{
1615			StartNode(invocationExpression);
1616			invocationExpression.Target.AcceptVisitor(this, data);
1617			WriteCommaSeparatedListInParenthesis(invocationExpression.Arguments, false);
1618			return EndNode(invocationExpression);
1619		}
1620		
1621		public object VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, object data)
1622		{
1623			StartNode(arrayInitializerExpression);
1624			WriteToken("{", ArrayInitializerExpression.Roles.LBrace);
1625			Space();
1626			WriteCommaSeparatedList(arrayInitializerExpression.Elements);
1627			Space();
1628			WriteToken("}", ArrayInitializerExpression.Roles.RBrace);
1629			return EndNode(arrayInitializerExpression);
1630		}
1631		
1632		public object VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data)
1633		{
1634			StartNode(arrayCreateExpression);
1635			WriteKeyword("New");
1636			Space();
1637			arrayCreateExpression.Type.AcceptVisitor(this, data);
1638			WriteCommaSeparatedListInParenthesis(arrayCreateExpression.Arguments, false);
1639			foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers) {
1640				specifier.AcceptVisitor(this, data);
1641			}
1642			if (lastWritten != LastWritten.Whitespace)
1643				Space();
1644			if (arrayCreateExpression.Initializer.IsNull) {
1645				WriteToken("{", ArrayInitializerExpression.Roles.LBrace);
1646				WriteToken("}", ArrayInitializerExpression.Roles.RBrace);
1647			} else {
1648				arrayCreateExpression.Initializer.AcceptVisitor(this, data);
1649			}
1650			return EndNode(arrayCreateExpression);
1651		}
1652		
1653		public object VisitObjectCreationExpression(ObjectCreationExpression objectCreationExpression, object data)
1654		{
1655			StartNode(objectCreationExpression);
1656			
1657			WriteKeyword("New");
1658			objectCreationExpression.Type.AcceptVisitor(this, data);
1659			WriteCommaSeparatedListInParenthesis(objectCreationExpression.Arguments, false);
1660			if (!objectCreationExpression.Initializer.IsNull) {
1661				Space();
1662				if (objectCreationExpression.Initializer.Elements.Any(x =

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