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