You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2396 lines
79 KiB
2396 lines
79 KiB
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team |
|
// |
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this |
|
// software and associated documentation files (the "Software"), to deal in the Software |
|
// without restriction, including without limitation the rights to use, copy, modify, merge, |
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons |
|
// to whom the Software is furnished to do so, subject to the following conditions: |
|
// |
|
// The above copyright notice and this permission notice shall be included in all copies or |
|
// substantial portions of the Software. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE |
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
// DEALINGS IN THE SOFTWARE. |
|
|
|
using System; |
|
using System.Collections.Generic; |
|
using System.Diagnostics; |
|
using System.Globalization; |
|
using System.IO; |
|
using System.Linq; |
|
using System.Text; |
|
|
|
using ICSharpCode.NRefactory.PatternMatching; |
|
using ICSharpCode.NRefactory.TypeSystem; |
|
|
|
namespace ICSharpCode.NRefactory.CSharp |
|
{ |
|
/// <summary> |
|
/// Outputs the AST. |
|
/// </summary> |
|
public class OutputVisitor : IAstVisitor<object, object>, IPatternAstVisitor<object, object> |
|
{ |
|
readonly IOutputFormatter formatter; |
|
readonly CSharpFormattingOptions policy; |
|
readonly Stack<AstNode> containerStack = new Stack<AstNode> (); |
|
readonly Stack<AstNode> positionStack = new Stack<AstNode> (); |
|
|
|
/// <summary> |
|
/// Used to insert the minimal amount of spaces so that the lexer recognizes the tokens that were written. |
|
/// </summary> |
|
LastWritten lastWritten; |
|
|
|
enum LastWritten |
|
{ |
|
Whitespace, |
|
Other, |
|
KeywordOrIdentifier, |
|
Plus, |
|
Minus, |
|
Ampersand, |
|
QuestionMark, |
|
Division |
|
} |
|
|
|
public OutputVisitor (TextWriter textWriter, CSharpFormattingOptions formattingPolicy) |
|
{ |
|
if (textWriter == null) |
|
throw new ArgumentNullException ("textWriter"); |
|
if (formattingPolicy == null) |
|
throw new ArgumentNullException ("formattingPolicy"); |
|
this.formatter = new TextWriterOutputFormatter (textWriter); |
|
this.policy = formattingPolicy; |
|
} |
|
|
|
public OutputVisitor (IOutputFormatter formatter, CSharpFormattingOptions formattingPolicy) |
|
{ |
|
if (formatter == null) |
|
throw new ArgumentNullException ("formatter"); |
|
if (formattingPolicy == null) |
|
throw new ArgumentNullException ("formattingPolicy"); |
|
this.formatter = formatter; |
|
this.policy = formattingPolicy; |
|
} |
|
|
|
#region StartNode/EndNode |
|
public event EventHandler<AstNodeEventArgs> OutputStarted; |
|
|
|
protected virtual void OnOutputStarted (AstNodeEventArgs e) |
|
{ |
|
EventHandler<AstNodeEventArgs> handler = this.OutputStarted; |
|
if (handler != null) |
|
handler (this, e); |
|
} |
|
|
|
public event EventHandler<AstNodeEventArgs> OutputFinished; |
|
|
|
protected virtual void OnOutputFinished (AstNodeEventArgs e) |
|
{ |
|
EventHandler<AstNodeEventArgs> handler = this.OutputFinished; |
|
if (handler != null) |
|
handler (this, e); |
|
} |
|
|
|
[Serializable] |
|
public sealed class AstNodeEventArgs : EventArgs |
|
{ |
|
public AstNode AstNode { |
|
get; |
|
private set; |
|
} |
|
|
|
public AstNodeEventArgs (AstNode node) |
|
{ |
|
this.AstNode = node; |
|
} |
|
} |
|
|
|
void StartNode (AstNode node) |
|
{ |
|
// Ensure that nodes are visited in the proper nested order. |
|
// Jumps to different subtrees are allowed only for the child of a placeholder node. |
|
Debug.Assert (containerStack.Count == 0 || node.Parent == containerStack.Peek () || containerStack.Peek ().NodeType == NodeType.Pattern); |
|
if (positionStack.Count > 0) |
|
WriteSpecialsUpToNode (node); |
|
containerStack.Push (node); |
|
positionStack.Push (node.FirstChild); |
|
OnOutputStarted (new AstNodeEventArgs (node)); |
|
formatter.StartNode (node); |
|
} |
|
|
|
object EndNode (AstNode node) |
|
{ |
|
Debug.Assert (node == containerStack.Peek ()); |
|
AstNode pos = positionStack.Pop (); |
|
Debug.Assert (pos == null || pos.Parent == node); |
|
WriteSpecials (pos, null); |
|
containerStack.Pop (); |
|
OnOutputFinished (new AstNodeEventArgs (node)); |
|
formatter.EndNode (node); |
|
return null; |
|
} |
|
#endregion |
|
|
|
#region WriteSpecials |
|
/// <summary> |
|
/// Writes all specials from start to end (exclusive). Does not touch the positionStack. |
|
/// </summary> |
|
void WriteSpecials (AstNode start, AstNode end) |
|
{ |
|
for (AstNode pos = start; pos != end; pos = pos.NextSibling) { |
|
if (pos.Role == AstNode.Roles.Comment) { |
|
pos.AcceptVisitor (this, null); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Writes all specials between the current position (in the positionStack) and the next |
|
/// node with the specified role. Advances the current position. |
|
/// </summary> |
|
void WriteSpecialsUpToRole (Role role) |
|
{ |
|
for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) { |
|
if (pos.Role == role) { |
|
WriteSpecials (positionStack.Pop (), pos); |
|
positionStack.Push (pos); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Writes all specials between the current position (in the positionStack) and the specified node. |
|
/// Advances the current position. |
|
/// </summary> |
|
void WriteSpecialsUpToNode (AstNode node) |
|
{ |
|
for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) { |
|
if (pos == node) { |
|
WriteSpecials (positionStack.Pop (), pos); |
|
positionStack.Push (pos); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
void WriteSpecialsUpToRole (Role role, AstNode nextNode) |
|
{ |
|
// Look for the role between the current position and the nextNode. |
|
for (AstNode pos = positionStack.Peek(); pos != null && pos != nextNode; pos = pos.NextSibling) { |
|
if (pos.Role == AstNode.Roles.Comma) { |
|
WriteSpecials (positionStack.Pop (), pos); |
|
positionStack.Push (pos); |
|
break; |
|
} |
|
} |
|
} |
|
#endregion |
|
|
|
#region Comma |
|
/// <summary> |
|
/// Writes a comma. |
|
/// </summary> |
|
/// <param name="nextNode">The next node after the comma.</param> |
|
/// <param name="noSpacesAfterComma">When set prevents printing a space after comma.</param> |
|
void Comma (AstNode nextNode, bool noSpaceAfterComma = false) |
|
{ |
|
WriteSpecialsUpToRole (AstNode.Roles.Comma, nextNode); |
|
Space (policy.SpaceBeforeBracketComma); // TODO: Comma policy has changed. |
|
formatter.WriteToken (","); |
|
lastWritten = LastWritten.Other; |
|
Space (!noSpaceAfterComma && policy.SpaceAfterBracketComma); // TODO: Comma policy has changed. |
|
} |
|
|
|
void WriteCommaSeparatedList (IEnumerable<AstNode> list) |
|
{ |
|
bool isFirst = true; |
|
foreach (AstNode node in list) { |
|
if (isFirst) { |
|
isFirst = false; |
|
} else { |
|
Comma (node); |
|
} |
|
node.AcceptVisitor (this, null); |
|
} |
|
} |
|
|
|
void WriteCommaSeparatedListInParenthesis (IEnumerable<AstNode> list, bool spaceWithin) |
|
{ |
|
LPar (); |
|
if (list.Any ()) { |
|
Space (spaceWithin); |
|
WriteCommaSeparatedList (list); |
|
Space (spaceWithin); |
|
} |
|
RPar (); |
|
} |
|
|
|
#if DOTNET35 |
|
void WriteCommaSeparatedList(IEnumerable<VariableInitializer> list) |
|
{ |
|
WriteCommaSeparatedList(list.SafeCast<VariableInitializer, AstNode>()); |
|
} |
|
|
|
void WriteCommaSeparatedList(IEnumerable<AstType> list) |
|
{ |
|
WriteCommaSeparatedList(list.SafeCast<AstType, AstNode>()); |
|
} |
|
|
|
void WriteCommaSeparatedListInParenthesis(IEnumerable<Expression> list, bool spaceWithin) |
|
{ |
|
WriteCommaSeparatedListInParenthesis(list.SafeCast<Expression, AstNode>(), spaceWithin); |
|
} |
|
|
|
void WriteCommaSeparatedListInParenthesis(IEnumerable<ParameterDeclaration> list, bool spaceWithin) |
|
{ |
|
WriteCommaSeparatedListInParenthesis(list.SafeCast<ParameterDeclaration, AstNode>(), spaceWithin); |
|
} |
|
|
|
#endif |
|
|
|
void WriteCommaSeparatedListInBrackets (IEnumerable<ParameterDeclaration> list, bool spaceWithin) |
|
{ |
|
WriteToken ("[", AstNode.Roles.LBracket); |
|
if (list.Any ()) { |
|
Space (spaceWithin); |
|
WriteCommaSeparatedList (list.SafeCast<ParameterDeclaration, AstNode> ()); |
|
Space (spaceWithin); |
|
} |
|
WriteToken ("]", AstNode.Roles.RBracket); |
|
} |
|
|
|
void WriteCommaSeparatedListInBrackets (IEnumerable<Expression> list) |
|
{ |
|
WriteToken ("[", AstNode.Roles.LBracket); |
|
if (list.Any ()) { |
|
Space (policy.SpacesWithinBrackets); |
|
WriteCommaSeparatedList (list.SafeCast<Expression, AstNode> ()); |
|
Space (policy.SpacesWithinBrackets); |
|
} |
|
WriteToken ("]", AstNode.Roles.RBracket); |
|
} |
|
#endregion |
|
|
|
#region Write tokens |
|
/// <summary> |
|
/// Writes a keyword, and all specials up to |
|
/// </summary> |
|
void WriteKeyword (string keyword, Role<CSharpTokenNode> tokenRole = null) |
|
{ |
|
WriteSpecialsUpToRole (tokenRole ?? AstNode.Roles.Keyword); |
|
if (lastWritten == LastWritten.KeywordOrIdentifier) |
|
formatter.Space (); |
|
formatter.WriteKeyword (keyword); |
|
lastWritten = LastWritten.KeywordOrIdentifier; |
|
} |
|
|
|
void WriteIdentifier (string identifier, Role<Identifier> identifierRole = null) |
|
{ |
|
WriteSpecialsUpToRole (identifierRole ?? AstNode.Roles.Identifier); |
|
if (IsKeyword (identifier, containerStack.Peek ())) { |
|
if (lastWritten == LastWritten.KeywordOrIdentifier) |
|
Space (); // this space is not strictly required, so we call Space() |
|
formatter.WriteToken ("@"); |
|
} else if (lastWritten == LastWritten.KeywordOrIdentifier) { |
|
formatter.Space (); // this space is strictly required, so we directly call the formatter |
|
} |
|
formatter.WriteIdentifier (identifier); |
|
lastWritten = LastWritten.KeywordOrIdentifier; |
|
} |
|
|
|
void WriteToken (string token, Role<CSharpTokenNode> tokenRole) |
|
{ |
|
WriteSpecialsUpToRole (tokenRole); |
|
// Avoid that two +, - or ? tokens are combined into a ++, -- or ?? token. |
|
// Note that we don't need to handle tokens like = because there's no valid |
|
// C# program that contains the single token twice in a row. |
|
// (for +, - and &, this can happen with unary operators; |
|
// for ?, this can happen in "a is int? ? b : c" or "a as int? ?? 0"; |
|
// and for /, this can happen with "1/ *ptr" or "1/ //comment".) |
|
if (lastWritten == LastWritten.Plus && token [0] == '+' |
|
|| lastWritten == LastWritten.Minus && token [0] == '-' |
|
|| lastWritten == LastWritten.Ampersand && token [0] == '&' |
|
|| lastWritten == LastWritten.QuestionMark && token [0] == '?' |
|
|| lastWritten == LastWritten.Division && token [0] == '*') { |
|
formatter.Space (); |
|
} |
|
formatter.WriteToken (token); |
|
if (token == "+") |
|
lastWritten = LastWritten.Plus; |
|
else if (token == "-") |
|
lastWritten = LastWritten.Minus; |
|
else if (token == "&") |
|
lastWritten = LastWritten.Ampersand; |
|
else if (token == "?") |
|
lastWritten = LastWritten.QuestionMark; |
|
else if (token == "/") |
|
lastWritten = LastWritten.Division; |
|
else |
|
lastWritten = LastWritten.Other; |
|
} |
|
|
|
void LPar () |
|
{ |
|
WriteToken ("(", AstNode.Roles.LPar); |
|
} |
|
|
|
void RPar () |
|
{ |
|
WriteToken (")", AstNode.Roles.LPar); |
|
} |
|
|
|
/// <summary> |
|
/// Marks the end of a statement |
|
/// </summary> |
|
void Semicolon () |
|
{ |
|
Role role = containerStack.Peek ().Role; // get the role of the current node |
|
if (!(role == ForStatement.InitializerRole || role == ForStatement.IteratorRole || role == UsingStatement.ResourceAcquisitionRole)) { |
|
WriteToken (";", AstNode.Roles.Semicolon); |
|
NewLine (); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Writes a space depending on policy. |
|
/// </summary> |
|
void Space (bool addSpace = true) |
|
{ |
|
if (addSpace) { |
|
formatter.Space (); |
|
lastWritten = LastWritten.Whitespace; |
|
} |
|
} |
|
|
|
void NewLine () |
|
{ |
|
formatter.NewLine (); |
|
lastWritten = LastWritten.Whitespace; |
|
} |
|
|
|
void OpenBrace (BraceStyle style) |
|
{ |
|
WriteSpecialsUpToRole (AstNode.Roles.LBrace); |
|
formatter.OpenBrace (style); |
|
lastWritten = LastWritten.Other; |
|
} |
|
|
|
void CloseBrace (BraceStyle style) |
|
{ |
|
WriteSpecialsUpToRole (AstNode.Roles.RBrace); |
|
formatter.CloseBrace (style); |
|
lastWritten = LastWritten.Other; |
|
} |
|
|
|
#endregion |
|
|
|
#region IsKeyword Test |
|
static readonly HashSet<string> unconditionalKeywords = new HashSet<string> { |
|
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", |
|
"char", "checked", "class", "const", "continue", "decimal", "default", "delegate", |
|
"do", "double", "else", "enum", "event", "explicit", "extern", "false", |
|
"finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", |
|
"in", "int", "interface", "internal", "is", "lock", "long", "namespace", |
|
"new", "null", "object", "operator", "out", "override", "params", "private", |
|
"protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", |
|
"sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", |
|
"true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", |
|
"using", "virtual", "void", "volatile", "while" |
|
}; |
|
static readonly HashSet<string> queryKeywords = new HashSet<string> { |
|
"from", "where", "join", "on", "equals", "into", "let", "orderby", |
|
"ascending", "descending", "select", "group", "by" |
|
}; |
|
|
|
/// <summary> |
|
/// Determines whether the specified identifier is a keyword in the given context. |
|
/// </summary> |
|
public static bool IsKeyword (string identifier, AstNode context) |
|
{ |
|
if (unconditionalKeywords.Contains (identifier)) |
|
return true; |
|
if (context.Ancestors.Any (a => a is QueryExpression)) { |
|
if (queryKeywords.Contains (identifier)) |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
#endregion |
|
|
|
#region Write constructs |
|
void WriteTypeArguments (IEnumerable<AstType> typeArguments) |
|
{ |
|
if (typeArguments.Any ()) { |
|
WriteToken ("<", AstNode.Roles.LChevron); |
|
WriteCommaSeparatedList (typeArguments); |
|
WriteToken (">", AstNode.Roles.RChevron); |
|
} |
|
} |
|
|
|
void WriteTypeParameters (IEnumerable<TypeParameterDeclaration> typeParameters) |
|
{ |
|
if (typeParameters.Any ()) { |
|
WriteToken ("<", AstNode.Roles.LChevron); |
|
WriteCommaSeparatedList (typeParameters.SafeCast<TypeParameterDeclaration, AstNode> ()); |
|
WriteToken (">", AstNode.Roles.RChevron); |
|
} |
|
} |
|
|
|
void WriteModifiers (IEnumerable<CSharpModifierToken> modifierTokens) |
|
{ |
|
foreach (CSharpModifierToken modifier in modifierTokens) { |
|
modifier.AcceptVisitor (this, null); |
|
} |
|
} |
|
|
|
void WriteQualifiedIdentifier (IEnumerable<Identifier> identifiers) |
|
{ |
|
bool first = true; |
|
foreach (Identifier ident in identifiers) { |
|
if (first) { |
|
first = false; |
|
if (lastWritten == LastWritten.KeywordOrIdentifier) |
|
formatter.Space (); |
|
} else { |
|
WriteSpecialsUpToRole (AstNode.Roles.Dot, ident); |
|
formatter.WriteToken ("."); |
|
lastWritten = LastWritten.Other; |
|
} |
|
WriteSpecialsUpToNode (ident); |
|
formatter.WriteIdentifier (ident.Name); |
|
lastWritten = LastWritten.KeywordOrIdentifier; |
|
} |
|
} |
|
|
|
void WriteEmbeddedStatement (Statement embeddedStatement) |
|
{ |
|
if (embeddedStatement.IsNull) |
|
return; |
|
BlockStatement block = embeddedStatement as BlockStatement; |
|
if (block != null) |
|
VisitBlockStatement (block, null); |
|
else { |
|
NewLine (); |
|
formatter.Indent (); |
|
embeddedStatement.AcceptVisitor (this, null); |
|
formatter.Unindent (); |
|
} |
|
} |
|
|
|
void WriteMethodBody (BlockStatement body) |
|
{ |
|
if (body.IsNull) |
|
Semicolon (); |
|
else |
|
VisitBlockStatement (body, null); |
|
} |
|
|
|
void WriteAttributes (IEnumerable<AttributeSection> attributes) |
|
{ |
|
foreach (AttributeSection attr in attributes) { |
|
attr.AcceptVisitor (this, null); |
|
} |
|
} |
|
|
|
void WritePrivateImplementationType (AstType privateImplementationType) |
|
{ |
|
if (!privateImplementationType.IsNull) { |
|
privateImplementationType.AcceptVisitor (this, null); |
|
WriteToken (".", AstNode.Roles.Dot); |
|
} |
|
} |
|
|
|
#endregion |
|
|
|
#region Expressions |
|
public object VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression, object data) |
|
{ |
|
StartNode (anonymousMethodExpression); |
|
WriteKeyword ("delegate"); |
|
if (anonymousMethodExpression.HasParameterList) { |
|
Space (policy.SpaceBeforeMethodDeclarationParentheses); |
|
WriteCommaSeparatedListInParenthesis (anonymousMethodExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses); |
|
} |
|
anonymousMethodExpression.Body.AcceptVisitor (this, data); |
|
return EndNode (anonymousMethodExpression); |
|
} |
|
|
|
public object VisitUndocumentedExpression (UndocumentedExpression undocumentedExpression, object data) |
|
{ |
|
StartNode (undocumentedExpression); |
|
switch (undocumentedExpression.UndocumentedExpressionType) { |
|
case UndocumentedExpressionType.ArgList: |
|
case UndocumentedExpressionType.ArgListAccess: |
|
WriteKeyword ("__arglist"); |
|
break; |
|
case UndocumentedExpressionType.MakeRef: |
|
WriteKeyword ("__makeref"); |
|
break; |
|
case UndocumentedExpressionType.RefType: |
|
WriteKeyword ("__reftype"); |
|
break; |
|
case UndocumentedExpressionType.RefValue: |
|
WriteKeyword ("__refvalue"); |
|
break; |
|
} |
|
if (undocumentedExpression.Arguments.Count > 0) { |
|
Space (policy.SpaceBeforeMethodCallParentheses); |
|
WriteCommaSeparatedListInParenthesis (undocumentedExpression.Arguments, policy.SpaceWithinMethodCallParentheses); |
|
} |
|
return EndNode (undocumentedExpression); |
|
} |
|
|
|
public object VisitArrayCreateExpression (ArrayCreateExpression arrayCreateExpression, object data) |
|
{ |
|
StartNode (arrayCreateExpression); |
|
WriteKeyword ("new"); |
|
arrayCreateExpression.Type.AcceptVisitor (this, data); |
|
WriteCommaSeparatedListInBrackets (arrayCreateExpression.Arguments); |
|
foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers) |
|
specifier.AcceptVisitor (this, data); |
|
arrayCreateExpression.Initializer.AcceptVisitor (this, data); |
|
return EndNode (arrayCreateExpression); |
|
} |
|
|
|
public object VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression, object data) |
|
{ |
|
StartNode (arrayInitializerExpression); |
|
PrintInitializerElements(arrayInitializerExpression.Elements); |
|
return EndNode (arrayInitializerExpression); |
|
} |
|
|
|
void PrintInitializerElements(AstNodeCollection<Expression> elements) |
|
{ |
|
BraceStyle style; |
|
if (policy.PlaceArrayInitializersOnNewLine == ArrayInitializerPlacement.AlwaysNewLine) |
|
style = BraceStyle.NextLine; |
|
else |
|
style = BraceStyle.EndOfLine; |
|
OpenBrace(style); |
|
bool isFirst = true; |
|
foreach (AstNode node in elements) { |
|
if (isFirst) { |
|
isFirst = false; |
|
} else { |
|
Comma(node, noSpaceAfterComma: true); |
|
NewLine(); |
|
} |
|
node.AcceptVisitor(this, null); |
|
} |
|
NewLine(); |
|
CloseBrace(style); |
|
} |
|
|
|
public object VisitAsExpression (AsExpression asExpression, object data) |
|
{ |
|
StartNode (asExpression); |
|
asExpression.Expression.AcceptVisitor (this, data); |
|
Space (); |
|
WriteKeyword ("as"); |
|
Space (); |
|
asExpression.Type.AcceptVisitor (this, data); |
|
return EndNode (asExpression); |
|
} |
|
|
|
public object VisitAssignmentExpression (AssignmentExpression assignmentExpression, object data) |
|
{ |
|
StartNode (assignmentExpression); |
|
assignmentExpression.Left.AcceptVisitor (this, data); |
|
Space (policy.SpaceAroundAssignment); |
|
WriteToken (AssignmentExpression.GetOperatorSymbol (assignmentExpression.Operator), AssignmentExpression.OperatorRole); |
|
Space (policy.SpaceAroundAssignment); |
|
assignmentExpression.Right.AcceptVisitor (this, data); |
|
return EndNode (assignmentExpression); |
|
} |
|
|
|
public object VisitBaseReferenceExpression (BaseReferenceExpression baseReferenceExpression, object data) |
|
{ |
|
StartNode (baseReferenceExpression); |
|
WriteKeyword ("base"); |
|
return EndNode (baseReferenceExpression); |
|
} |
|
|
|
public object VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression, object data) |
|
{ |
|
StartNode (binaryOperatorExpression); |
|
binaryOperatorExpression.Left.AcceptVisitor (this, data); |
|
bool spacePolicy; |
|
switch (binaryOperatorExpression.Operator) { |
|
case BinaryOperatorType.BitwiseAnd: |
|
case BinaryOperatorType.BitwiseOr: |
|
case BinaryOperatorType.ExclusiveOr: |
|
spacePolicy = policy.SpaceAroundBitwiseOperator; |
|
break; |
|
case BinaryOperatorType.ConditionalAnd: |
|
case BinaryOperatorType.ConditionalOr: |
|
spacePolicy = policy.SpaceAroundLogicalOperator; |
|
break; |
|
case BinaryOperatorType.GreaterThan: |
|
case BinaryOperatorType.GreaterThanOrEqual: |
|
case BinaryOperatorType.LessThanOrEqual: |
|
case BinaryOperatorType.LessThan: |
|
spacePolicy = policy.SpaceAroundRelationalOperator; |
|
break; |
|
case BinaryOperatorType.Equality: |
|
case BinaryOperatorType.InEquality: |
|
spacePolicy = policy.SpaceAroundEqualityOperator; |
|
break; |
|
case BinaryOperatorType.Add: |
|
case BinaryOperatorType.Subtract: |
|
spacePolicy = policy.SpaceAroundAdditiveOperator; |
|
break; |
|
case BinaryOperatorType.Multiply: |
|
case BinaryOperatorType.Divide: |
|
case BinaryOperatorType.Modulus: |
|
spacePolicy = policy.SpaceAroundMultiplicativeOperator; |
|
break; |
|
case BinaryOperatorType.ShiftLeft: |
|
case BinaryOperatorType.ShiftRight: |
|
spacePolicy = policy.SpaceAroundShiftOperator; |
|
break; |
|
case BinaryOperatorType.NullCoalescing: |
|
spacePolicy = true; |
|
break; |
|
default: |
|
throw new NotSupportedException ("Invalid value for BinaryOperatorType"); |
|
} |
|
Space (spacePolicy); |
|
WriteToken (BinaryOperatorExpression.GetOperatorSymbol (binaryOperatorExpression.Operator), BinaryOperatorExpression.OperatorRole); |
|
Space (spacePolicy); |
|
binaryOperatorExpression.Right.AcceptVisitor (this, data); |
|
return EndNode (binaryOperatorExpression); |
|
} |
|
|
|
public object VisitCastExpression (CastExpression castExpression, object data) |
|
{ |
|
StartNode (castExpression); |
|
LPar (); |
|
Space (policy.SpacesWithinCastParentheses); |
|
castExpression.Type.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinCastParentheses); |
|
RPar (); |
|
Space (policy.SpaceAfterTypecast); |
|
castExpression.Expression.AcceptVisitor (this, data); |
|
return EndNode (castExpression); |
|
} |
|
|
|
public object VisitCheckedExpression (CheckedExpression checkedExpression, object data) |
|
{ |
|
StartNode (checkedExpression); |
|
WriteKeyword ("checked"); |
|
LPar (); |
|
Space (policy.SpacesWithinCheckedExpressionParantheses); |
|
checkedExpression.Expression.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinCheckedExpressionParantheses); |
|
RPar (); |
|
return EndNode (checkedExpression); |
|
} |
|
|
|
public object VisitConditionalExpression (ConditionalExpression conditionalExpression, object data) |
|
{ |
|
StartNode (conditionalExpression); |
|
conditionalExpression.Condition.AcceptVisitor (this, data); |
|
|
|
Space (policy.SpaceBeforeConditionalOperatorCondition); |
|
WriteToken ("?", ConditionalExpression.QuestionMarkRole); |
|
Space (policy.SpaceAfterConditionalOperatorCondition); |
|
|
|
conditionalExpression.TrueExpression.AcceptVisitor (this, data); |
|
|
|
Space (policy.SpaceBeforeConditionalOperatorSeparator); |
|
WriteToken (":", ConditionalExpression.ColonRole); |
|
Space (policy.SpaceAfterConditionalOperatorSeparator); |
|
|
|
conditionalExpression.FalseExpression.AcceptVisitor (this, data); |
|
|
|
return EndNode (conditionalExpression); |
|
} |
|
|
|
public object VisitDefaultValueExpression (DefaultValueExpression defaultValueExpression, object data) |
|
{ |
|
StartNode (defaultValueExpression); |
|
|
|
WriteKeyword ("default"); |
|
LPar (); |
|
Space (policy.SpacesWithinTypeOfParentheses); |
|
defaultValueExpression.Type.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinTypeOfParentheses); |
|
RPar (); |
|
|
|
return EndNode (defaultValueExpression); |
|
} |
|
|
|
public object VisitDirectionExpression (DirectionExpression directionExpression, object data) |
|
{ |
|
StartNode (directionExpression); |
|
|
|
switch (directionExpression.FieldDirection) { |
|
case FieldDirection.Out: |
|
WriteKeyword ("out"); |
|
break; |
|
case FieldDirection.Ref: |
|
WriteKeyword ("ref"); |
|
break; |
|
default: |
|
throw new NotSupportedException ("Invalid value for FieldDirection"); |
|
} |
|
Space (); |
|
directionExpression.Expression.AcceptVisitor (this, data); |
|
|
|
return EndNode (directionExpression); |
|
} |
|
|
|
public object VisitIdentifierExpression (IdentifierExpression identifierExpression, object data) |
|
{ |
|
StartNode (identifierExpression); |
|
WriteIdentifier (identifierExpression.Identifier); |
|
WriteTypeArguments (identifierExpression.TypeArguments); |
|
return EndNode (identifierExpression); |
|
} |
|
|
|
public object VisitIndexerExpression (IndexerExpression indexerExpression, object data) |
|
{ |
|
StartNode (indexerExpression); |
|
indexerExpression.Target.AcceptVisitor (this, data); |
|
Space (policy.SpaceBeforeMethodCallParentheses); |
|
WriteCommaSeparatedListInBrackets (indexerExpression.Arguments); |
|
return EndNode (indexerExpression); |
|
} |
|
|
|
public object VisitInvocationExpression (InvocationExpression invocationExpression, object data) |
|
{ |
|
StartNode (invocationExpression); |
|
invocationExpression.Target.AcceptVisitor (this, data); |
|
Space (policy.SpaceBeforeMethodCallParentheses); |
|
WriteCommaSeparatedListInParenthesis (invocationExpression.Arguments, policy.SpaceWithinMethodCallParentheses); |
|
return EndNode (invocationExpression); |
|
} |
|
|
|
public object VisitIsExpression (IsExpression isExpression, object data) |
|
{ |
|
StartNode (isExpression); |
|
isExpression.Expression.AcceptVisitor (this, data); |
|
Space (); |
|
WriteKeyword ("is"); |
|
isExpression.Type.AcceptVisitor (this, data); |
|
return EndNode (isExpression); |
|
} |
|
|
|
public object VisitLambdaExpression (LambdaExpression lambdaExpression, object data) |
|
{ |
|
StartNode (lambdaExpression); |
|
if (LambdaNeedsParenthesis (lambdaExpression)) { |
|
WriteCommaSeparatedListInParenthesis (lambdaExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses); |
|
} else { |
|
lambdaExpression.Parameters.Single ().AcceptVisitor (this, data); |
|
} |
|
Space (); |
|
WriteToken ("=>", LambdaExpression.ArrowRole); |
|
Space (); |
|
lambdaExpression.Body.AcceptVisitor (this, data); |
|
return EndNode (lambdaExpression); |
|
} |
|
|
|
bool LambdaNeedsParenthesis (LambdaExpression lambdaExpression) |
|
{ |
|
if (lambdaExpression.Parameters.Count != 1) |
|
return true; |
|
var p = lambdaExpression.Parameters.Single (); |
|
return !(p.Type.IsNull && p.ParameterModifier == ParameterModifier.None); |
|
} |
|
|
|
public object VisitMemberReferenceExpression (MemberReferenceExpression memberReferenceExpression, object data) |
|
{ |
|
StartNode (memberReferenceExpression); |
|
memberReferenceExpression.Target.AcceptVisitor (this, data); |
|
WriteToken (".", MemberReferenceExpression.Roles.Dot); |
|
WriteIdentifier (memberReferenceExpression.MemberName); |
|
WriteTypeArguments (memberReferenceExpression.TypeArguments); |
|
return EndNode (memberReferenceExpression); |
|
} |
|
|
|
public object VisitNamedArgumentExpression (NamedArgumentExpression namedArgumentExpression, object data) |
|
{ |
|
StartNode (namedArgumentExpression); |
|
WriteIdentifier (namedArgumentExpression.Identifier); |
|
if (namedArgumentExpression.Parent is AnonymousTypeCreateExpression) { |
|
Space(); |
|
WriteToken("=", NamedArgumentExpression.Roles.Assign); |
|
} else { |
|
WriteToken(":", NamedArgumentExpression.Roles.Colon); |
|
} |
|
Space (); |
|
namedArgumentExpression.Expression.AcceptVisitor (this, data); |
|
return EndNode (namedArgumentExpression); |
|
} |
|
|
|
public object VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression, object data) |
|
{ |
|
StartNode (nullReferenceExpression); |
|
WriteKeyword ("null"); |
|
return EndNode (nullReferenceExpression); |
|
} |
|
|
|
public object VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression, object data) |
|
{ |
|
StartNode (objectCreateExpression); |
|
WriteKeyword ("new"); |
|
objectCreateExpression.Type.AcceptVisitor (this, data); |
|
bool useParenthesis = objectCreateExpression.Arguments.Any() || objectCreateExpression.Initializer.IsNull; |
|
// also use parenthesis if there is an '(' token |
|
if (!objectCreateExpression.LParToken.IsNull) |
|
useParenthesis = true; |
|
if (useParenthesis) { |
|
Space (policy.SpaceBeforeMethodCallParentheses); |
|
WriteCommaSeparatedListInParenthesis (objectCreateExpression.Arguments, policy.SpaceWithinMethodCallParentheses); |
|
} |
|
objectCreateExpression.Initializer.AcceptVisitor (this, data); |
|
return EndNode (objectCreateExpression); |
|
} |
|
|
|
public object VisitAnonymousTypeCreateExpression (AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) |
|
{ |
|
StartNode (anonymousTypeCreateExpression); |
|
WriteKeyword ("new"); |
|
Space (); |
|
PrintInitializerElements(anonymousTypeCreateExpression.Initializers); |
|
return EndNode (anonymousTypeCreateExpression); |
|
} |
|
|
|
public object VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, object data) |
|
{ |
|
StartNode (parenthesizedExpression); |
|
LPar (); |
|
Space (policy.SpacesWithinParentheses); |
|
parenthesizedExpression.Expression.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinParentheses); |
|
RPar (); |
|
return EndNode (parenthesizedExpression); |
|
} |
|
|
|
public object VisitPointerReferenceExpression (PointerReferenceExpression pointerReferenceExpression, object data) |
|
{ |
|
StartNode (pointerReferenceExpression); |
|
pointerReferenceExpression.Target.AcceptVisitor (this, data); |
|
WriteToken ("->", PointerReferenceExpression.ArrowRole); |
|
WriteIdentifier (pointerReferenceExpression.MemberName); |
|
WriteTypeArguments (pointerReferenceExpression.TypeArguments); |
|
return EndNode (pointerReferenceExpression); |
|
} |
|
|
|
public object VisitEmptyExpression (EmptyExpression emptyExpression, object data) |
|
{ |
|
StartNode (emptyExpression); |
|
return EndNode (emptyExpression); |
|
} |
|
|
|
#region VisitPrimitiveExpression |
|
public object VisitPrimitiveExpression (PrimitiveExpression primitiveExpression, object data) |
|
{ |
|
StartNode (primitiveExpression); |
|
if (!string.IsNullOrEmpty (primitiveExpression.LiteralValue)) { |
|
formatter.WriteToken (primitiveExpression.LiteralValue); |
|
} else { |
|
WritePrimitiveValue (primitiveExpression.Value); |
|
} |
|
return EndNode (primitiveExpression); |
|
} |
|
|
|
void WritePrimitiveValue (object val) |
|
{ |
|
if (val == null) { |
|
// usually NullReferenceExpression should be used for this, but we'll handle it anyways |
|
WriteKeyword ("null"); |
|
return; |
|
} |
|
|
|
if (val is bool) { |
|
if ((bool)val) { |
|
WriteKeyword ("true"); |
|
} else { |
|
WriteKeyword ("false"); |
|
} |
|
return; |
|
} |
|
|
|
if (val is string) { |
|
formatter.WriteToken ("\"" + ConvertString (val.ToString ()) + "\""); |
|
lastWritten = LastWritten.Other; |
|
} else if (val is char) { |
|
formatter.WriteToken ("'" + ConvertCharLiteral ((char)val) + "'"); |
|
lastWritten = LastWritten.Other; |
|
} else if (val is decimal) { |
|
formatter.WriteToken (((decimal)val).ToString (NumberFormatInfo.InvariantInfo) + "m"); |
|
lastWritten = LastWritten.Other; |
|
} else if (val is float) { |
|
float f = (float)val; |
|
if (float.IsInfinity (f) || float.IsNaN (f)) { |
|
// Strictly speaking, these aren't PrimitiveExpressions; |
|
// but we still support writing these to make life easier for code generators. |
|
WriteKeyword ("float"); |
|
WriteToken (".", AstNode.Roles.Dot); |
|
if (float.IsPositiveInfinity (f)) |
|
WriteIdentifier ("PositiveInfinity"); |
|
else if (float.IsNegativeInfinity (f)) |
|
WriteIdentifier ("NegativeInfinity"); |
|
else |
|
WriteIdentifier ("NaN"); |
|
return; |
|
} |
|
formatter.WriteToken (f.ToString ("R", NumberFormatInfo.InvariantInfo) + "f"); |
|
lastWritten = LastWritten.Other; |
|
} else if (val is double) { |
|
double f = (double)val; |
|
if (double.IsInfinity (f) || double.IsNaN (f)) { |
|
// Strictly speaking, these aren't PrimitiveExpressions; |
|
// but we still support writing these to make life easier for code generators. |
|
WriteKeyword ("double"); |
|
WriteToken (".", AstNode.Roles.Dot); |
|
if (double.IsPositiveInfinity (f)) |
|
WriteIdentifier ("PositiveInfinity"); |
|
else if (double.IsNegativeInfinity (f)) |
|
WriteIdentifier ("NegativeInfinity"); |
|
else |
|
WriteIdentifier ("NaN"); |
|
return; |
|
} |
|
string number = f.ToString ("R", NumberFormatInfo.InvariantInfo); |
|
if (number.IndexOf ('.') < 0 && number.IndexOf ('E') < 0) |
|
number += ".0"; |
|
formatter.WriteToken (number); |
|
// needs space if identifier follows number; this avoids mistaking the following identifier as type suffix |
|
lastWritten = LastWritten.KeywordOrIdentifier; |
|
} else if (val is IFormattable) { |
|
StringBuilder b = new StringBuilder (); |
|
// if (primitiveExpression.LiteralFormat == LiteralFormat.HexadecimalNumber) { |
|
// b.Append("0x"); |
|
// b.Append(((IFormattable)val).ToString("x", NumberFormatInfo.InvariantInfo)); |
|
// } else { |
|
b.Append (((IFormattable)val).ToString (null, NumberFormatInfo.InvariantInfo)); |
|
// } |
|
if (val is uint || val is ulong) { |
|
b.Append ("u"); |
|
} |
|
if (val is long || val is ulong) { |
|
b.Append ("L"); |
|
} |
|
formatter.WriteToken (b.ToString ()); |
|
// needs space if identifier follows number; this avoids mistaking the following identifier as type suffix |
|
lastWritten = LastWritten.KeywordOrIdentifier; |
|
} else { |
|
formatter.WriteToken (val.ToString ()); |
|
lastWritten = LastWritten.Other; |
|
} |
|
} |
|
|
|
static string ConvertCharLiteral (char ch) |
|
{ |
|
if (ch == '\'') |
|
return "\\'"; |
|
return ConvertChar (ch); |
|
} |
|
|
|
/// <summary> |
|
/// Gets the escape sequence for the specified character. |
|
/// </summary> |
|
/// <remarks>This method does not convert ' or ".</remarks> |
|
public static string ConvertChar(char ch) |
|
{ |
|
switch (ch) { |
|
case '\\': |
|
return "\\\\"; |
|
case '\0': |
|
return "\\0"; |
|
case '\a': |
|
return "\\a"; |
|
case '\b': |
|
return "\\b"; |
|
case '\f': |
|
return "\\f"; |
|
case '\n': |
|
return "\\n"; |
|
case '\r': |
|
return "\\r"; |
|
case '\t': |
|
return "\\t"; |
|
case '\v': |
|
return "\\v"; |
|
default: |
|
if (char.IsControl(ch) || char.IsSurrogate(ch) || |
|
// print all uncommon white spaces as numbers |
|
(char.IsWhiteSpace(ch) && ch != ' ')) { |
|
return "\\u" + ((int)ch).ToString ("x4"); |
|
} else { |
|
return ch.ToString (); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Converts special characters to escape sequences within the given string. |
|
/// </summary> |
|
public static string ConvertString(string str) |
|
{ |
|
StringBuilder sb = new StringBuilder (); |
|
foreach (char ch in str) { |
|
if (ch == '"') |
|
sb.Append ("\\\""); |
|
else |
|
sb.Append (ConvertChar (ch)); |
|
} |
|
return sb.ToString (); |
|
} |
|
|
|
#endregion |
|
|
|
public object VisitSizeOfExpression (SizeOfExpression sizeOfExpression, object data) |
|
{ |
|
StartNode (sizeOfExpression); |
|
|
|
WriteKeyword ("sizeof"); |
|
LPar (); |
|
Space (policy.SpacesWithinSizeOfParentheses); |
|
sizeOfExpression.Type.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinSizeOfParentheses); |
|
RPar (); |
|
|
|
return EndNode (sizeOfExpression); |
|
} |
|
|
|
public object VisitStackAllocExpression (StackAllocExpression stackAllocExpression, object data) |
|
{ |
|
StartNode (stackAllocExpression); |
|
WriteKeyword ("stackalloc"); |
|
stackAllocExpression.Type.AcceptVisitor (this, data); |
|
WriteCommaSeparatedListInBrackets (new[] { stackAllocExpression.CountExpression }); |
|
return EndNode (stackAllocExpression); |
|
} |
|
|
|
public object VisitThisReferenceExpression (ThisReferenceExpression thisReferenceExpression, object data) |
|
{ |
|
StartNode (thisReferenceExpression); |
|
WriteKeyword ("this"); |
|
return EndNode (thisReferenceExpression); |
|
} |
|
|
|
public object VisitTypeOfExpression (TypeOfExpression typeOfExpression, object data) |
|
{ |
|
StartNode (typeOfExpression); |
|
|
|
WriteKeyword ("typeof"); |
|
LPar (); |
|
Space (policy.SpacesWithinTypeOfParentheses); |
|
typeOfExpression.Type.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinTypeOfParentheses); |
|
RPar (); |
|
|
|
return EndNode (typeOfExpression); |
|
} |
|
|
|
public object VisitTypeReferenceExpression (TypeReferenceExpression typeReferenceExpression, object data) |
|
{ |
|
StartNode (typeReferenceExpression); |
|
typeReferenceExpression.Type.AcceptVisitor (this, data); |
|
return EndNode (typeReferenceExpression); |
|
} |
|
|
|
public object VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression, object data) |
|
{ |
|
StartNode (unaryOperatorExpression); |
|
UnaryOperatorType opType = unaryOperatorExpression.Operator; |
|
string opSymbol = UnaryOperatorExpression.GetOperatorSymbol (opType); |
|
if (!(opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)) |
|
WriteToken (opSymbol, UnaryOperatorExpression.OperatorRole); |
|
unaryOperatorExpression.Expression.AcceptVisitor (this, data); |
|
if (opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement) |
|
WriteToken (opSymbol, UnaryOperatorExpression.OperatorRole); |
|
return EndNode (unaryOperatorExpression); |
|
} |
|
|
|
public object VisitUncheckedExpression (UncheckedExpression uncheckedExpression, object data) |
|
{ |
|
StartNode (uncheckedExpression); |
|
WriteKeyword ("unchecked"); |
|
LPar (); |
|
Space (policy.SpacesWithinCheckedExpressionParantheses); |
|
uncheckedExpression.Expression.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinCheckedExpressionParantheses); |
|
RPar (); |
|
return EndNode (uncheckedExpression); |
|
} |
|
|
|
#endregion |
|
|
|
#region Query Expressions |
|
public object VisitQueryExpression (QueryExpression queryExpression, object data) |
|
{ |
|
StartNode (queryExpression); |
|
bool indent = !(queryExpression.Parent is QueryContinuationClause); |
|
if (indent) { |
|
formatter.Indent(); |
|
NewLine(); |
|
} |
|
bool first = true; |
|
foreach (var clause in queryExpression.Clauses) { |
|
if (first) { |
|
first = false; |
|
} else { |
|
if (!(clause is QueryContinuationClause)) |
|
NewLine (); |
|
} |
|
clause.AcceptVisitor (this, data); |
|
} |
|
if (indent) |
|
formatter.Unindent(); |
|
return EndNode (queryExpression); |
|
} |
|
|
|
public object VisitQueryContinuationClause (QueryContinuationClause queryContinuationClause, object data) |
|
{ |
|
StartNode (queryContinuationClause); |
|
queryContinuationClause.PrecedingQuery.AcceptVisitor (this, data); |
|
Space (); |
|
WriteKeyword ("into", QueryContinuationClause.IntoKeywordRole); |
|
Space (); |
|
WriteIdentifier (queryContinuationClause.Identifier); |
|
return EndNode (queryContinuationClause); |
|
} |
|
|
|
public object VisitQueryFromClause (QueryFromClause queryFromClause, object data) |
|
{ |
|
StartNode (queryFromClause); |
|
WriteKeyword ("from", QueryFromClause.FromKeywordRole); |
|
queryFromClause.Type.AcceptVisitor (this, data); |
|
Space (); |
|
WriteIdentifier (queryFromClause.Identifier); |
|
Space (); |
|
WriteKeyword ("in", QueryFromClause.InKeywordRole); |
|
Space (); |
|
queryFromClause.Expression.AcceptVisitor (this, data); |
|
return EndNode (queryFromClause); |
|
} |
|
|
|
public object VisitQueryLetClause (QueryLetClause queryLetClause, object data) |
|
{ |
|
StartNode (queryLetClause); |
|
WriteKeyword ("let"); |
|
Space (); |
|
WriteIdentifier (queryLetClause.Identifier); |
|
Space (policy.SpaceAroundAssignment); |
|
WriteToken ("=", QueryLetClause.Roles.Assign); |
|
Space (policy.SpaceAroundAssignment); |
|
queryLetClause.Expression.AcceptVisitor (this, data); |
|
return EndNode (queryLetClause); |
|
} |
|
|
|
public object VisitQueryWhereClause (QueryWhereClause queryWhereClause, object data) |
|
{ |
|
StartNode (queryWhereClause); |
|
WriteKeyword ("where"); |
|
Space (); |
|
queryWhereClause.Condition.AcceptVisitor (this, data); |
|
return EndNode (queryWhereClause); |
|
} |
|
|
|
public object VisitQueryJoinClause (QueryJoinClause queryJoinClause, object data) |
|
{ |
|
StartNode (queryJoinClause); |
|
WriteKeyword ("join", QueryJoinClause.JoinKeywordRole); |
|
queryJoinClause.Type.AcceptVisitor (this, data); |
|
Space (); |
|
WriteIdentifier (queryJoinClause.JoinIdentifier, QueryJoinClause.JoinIdentifierRole); |
|
Space (); |
|
WriteKeyword ("in", QueryJoinClause.InKeywordRole); |
|
Space (); |
|
queryJoinClause.InExpression.AcceptVisitor (this, data); |
|
Space (); |
|
WriteKeyword ("on", QueryJoinClause.OnKeywordRole); |
|
Space (); |
|
queryJoinClause.OnExpression.AcceptVisitor (this, data); |
|
Space (); |
|
WriteKeyword ("equals", QueryJoinClause.EqualsKeywordRole); |
|
Space (); |
|
queryJoinClause.EqualsExpression.AcceptVisitor (this, data); |
|
if (queryJoinClause.IsGroupJoin) { |
|
Space (); |
|
WriteKeyword ("into", QueryJoinClause.IntoKeywordRole); |
|
WriteIdentifier (queryJoinClause.IntoIdentifier, QueryJoinClause.IntoIdentifierRole); |
|
} |
|
return EndNode (queryJoinClause); |
|
} |
|
|
|
public object VisitQueryOrderClause (QueryOrderClause queryOrderClause, object data) |
|
{ |
|
StartNode (queryOrderClause); |
|
WriteKeyword ("orderby"); |
|
Space (); |
|
WriteCommaSeparatedList (queryOrderClause.Orderings.SafeCast<QueryOrdering, AstNode> ()); |
|
return EndNode (queryOrderClause); |
|
} |
|
|
|
public object VisitQueryOrdering (QueryOrdering queryOrdering, object data) |
|
{ |
|
StartNode (queryOrdering); |
|
queryOrdering.Expression.AcceptVisitor (this, data); |
|
switch (queryOrdering.Direction) { |
|
case QueryOrderingDirection.Ascending: |
|
Space (); |
|
WriteKeyword ("ascending"); |
|
break; |
|
case QueryOrderingDirection.Descending: |
|
Space (); |
|
WriteKeyword ("descending"); |
|
break; |
|
} |
|
return EndNode (queryOrdering); |
|
} |
|
|
|
public object VisitQuerySelectClause (QuerySelectClause querySelectClause, object data) |
|
{ |
|
StartNode (querySelectClause); |
|
WriteKeyword ("select"); |
|
Space (); |
|
querySelectClause.Expression.AcceptVisitor (this, data); |
|
return EndNode (querySelectClause); |
|
} |
|
|
|
public object VisitQueryGroupClause (QueryGroupClause queryGroupClause, object data) |
|
{ |
|
StartNode (queryGroupClause); |
|
WriteKeyword ("group", QueryGroupClause.GroupKeywordRole); |
|
Space (); |
|
queryGroupClause.Projection.AcceptVisitor (this, data); |
|
Space (); |
|
WriteKeyword ("by", QueryGroupClause.ByKeywordRole); |
|
Space (); |
|
queryGroupClause.Key.AcceptVisitor (this, data); |
|
return EndNode (queryGroupClause); |
|
} |
|
|
|
#endregion |
|
|
|
#region GeneralScope |
|
public object VisitAttribute (Attribute attribute, object data) |
|
{ |
|
StartNode (attribute); |
|
attribute.Type.AcceptVisitor (this, data); |
|
Space (policy.SpaceBeforeMethodCallParentheses); |
|
if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole (AstNode.Roles.LPar).IsNull) |
|
WriteCommaSeparatedListInParenthesis (attribute.Arguments, policy.SpaceWithinMethodCallParentheses); |
|
return EndNode (attribute); |
|
} |
|
|
|
public object VisitAttributeSection (AttributeSection attributeSection, object data) |
|
{ |
|
StartNode (attributeSection); |
|
WriteToken ("[", AstNode.Roles.LBracket); |
|
if (!string.IsNullOrEmpty (attributeSection.AttributeTarget)) { |
|
WriteToken (attributeSection.AttributeTarget, AttributeSection.TargetRole); |
|
WriteToken (":", AttributeSection.Roles.Colon); |
|
Space (); |
|
} |
|
WriteCommaSeparatedList (attributeSection.Attributes.SafeCast<Attribute, AstNode> ()); |
|
WriteToken ("]", AstNode.Roles.RBracket); |
|
if (attributeSection.Parent is ParameterDeclaration || attributeSection.Parent is TypeParameterDeclaration) |
|
Space (); |
|
else |
|
NewLine (); |
|
return EndNode (attributeSection); |
|
} |
|
|
|
public object VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, object data) |
|
{ |
|
StartNode (delegateDeclaration); |
|
WriteAttributes (delegateDeclaration.Attributes); |
|
WriteModifiers (delegateDeclaration.ModifierTokens); |
|
WriteKeyword ("delegate"); |
|
delegateDeclaration.ReturnType.AcceptVisitor (this, data); |
|
Space (); |
|
WriteIdentifier (delegateDeclaration.Name); |
|
WriteTypeParameters (delegateDeclaration.TypeParameters); |
|
Space (policy.SpaceBeforeDelegateDeclarationParentheses); |
|
WriteCommaSeparatedListInParenthesis (delegateDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); |
|
foreach (Constraint constraint in delegateDeclaration.Constraints) { |
|
constraint.AcceptVisitor (this, data); |
|
} |
|
Semicolon (); |
|
return EndNode (delegateDeclaration); |
|
} |
|
|
|
public object VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration, object data) |
|
{ |
|
StartNode (namespaceDeclaration); |
|
WriteKeyword ("namespace"); |
|
WriteQualifiedIdentifier (namespaceDeclaration.Identifiers); |
|
OpenBrace (policy.NamespaceBraceStyle); |
|
foreach (var member in namespaceDeclaration.Members) |
|
member.AcceptVisitor (this, data); |
|
CloseBrace (policy.NamespaceBraceStyle); |
|
NewLine (); |
|
return EndNode (namespaceDeclaration); |
|
} |
|
|
|
public object VisitTypeDeclaration (TypeDeclaration typeDeclaration, object data) |
|
{ |
|
StartNode (typeDeclaration); |
|
WriteAttributes (typeDeclaration.Attributes); |
|
WriteModifiers (typeDeclaration.ModifierTokens); |
|
BraceStyle braceStyle; |
|
switch (typeDeclaration.ClassType) { |
|
case ClassType.Enum: |
|
WriteKeyword ("enum"); |
|
braceStyle = policy.EnumBraceStyle; |
|
break; |
|
case ClassType.Interface: |
|
WriteKeyword ("interface"); |
|
braceStyle = policy.InterfaceBraceStyle; |
|
break; |
|
case ClassType.Struct: |
|
WriteKeyword ("struct"); |
|
braceStyle = policy.StructBraceStyle; |
|
break; |
|
default: |
|
WriteKeyword ("class"); |
|
braceStyle = policy.ClassBraceStyle; |
|
break; |
|
} |
|
WriteIdentifier (typeDeclaration.Name); |
|
WriteTypeParameters (typeDeclaration.TypeParameters); |
|
if (typeDeclaration.BaseTypes.Any ()) { |
|
Space (); |
|
WriteToken (":", TypeDeclaration.ColonRole); |
|
Space (); |
|
WriteCommaSeparatedList (typeDeclaration.BaseTypes); |
|
} |
|
foreach (Constraint constraint in typeDeclaration.Constraints) { |
|
constraint.AcceptVisitor (this, data); |
|
} |
|
OpenBrace (braceStyle); |
|
if (typeDeclaration.ClassType == ClassType.Enum) { |
|
bool first = true; |
|
foreach (var member in typeDeclaration.Members) { |
|
if (first) { |
|
first = false; |
|
} else { |
|
Comma (member, noSpaceAfterComma: true); |
|
NewLine (); |
|
} |
|
member.AcceptVisitor (this, data); |
|
} |
|
NewLine (); |
|
} else { |
|
foreach (var member in typeDeclaration.Members) { |
|
member.AcceptVisitor (this, data); |
|
} |
|
} |
|
CloseBrace (braceStyle); |
|
NewLine (); |
|
return EndNode (typeDeclaration); |
|
} |
|
|
|
public object VisitUsingAliasDeclaration (UsingAliasDeclaration usingAliasDeclaration, object data) |
|
{ |
|
StartNode (usingAliasDeclaration); |
|
WriteKeyword ("using"); |
|
WriteIdentifier (usingAliasDeclaration.Alias, UsingAliasDeclaration.AliasRole); |
|
Space (policy.SpaceAroundEqualityOperator); |
|
WriteToken ("=", AstNode.Roles.Assign); |
|
Space (policy.SpaceAroundEqualityOperator); |
|
usingAliasDeclaration.Import.AcceptVisitor (this, data); |
|
Semicolon (); |
|
return EndNode (usingAliasDeclaration); |
|
} |
|
|
|
public object VisitUsingDeclaration (UsingDeclaration usingDeclaration, object data) |
|
{ |
|
StartNode (usingDeclaration); |
|
WriteKeyword ("using"); |
|
usingDeclaration.Import.AcceptVisitor (this, data); |
|
Semicolon (); |
|
return EndNode (usingDeclaration); |
|
} |
|
|
|
public object VisitExternAliasDeclaration (ExternAliasDeclaration externAliasDeclaration, object data) |
|
{ |
|
StartNode (externAliasDeclaration); |
|
WriteKeyword ("extern"); |
|
Space (); |
|
WriteKeyword ("alias"); |
|
Space (); |
|
externAliasDeclaration.NameToken.AcceptVisitor (this, data); |
|
Semicolon (); |
|
return EndNode (externAliasDeclaration); |
|
} |
|
|
|
#endregion |
|
|
|
#region Statements |
|
public object VisitBlockStatement (BlockStatement blockStatement, object data) |
|
{ |
|
StartNode (blockStatement); |
|
BraceStyle style; |
|
if (blockStatement.Parent is AnonymousMethodExpression || blockStatement.Parent is LambdaExpression) { |
|
style = policy.AnonymousMethodBraceStyle; |
|
} else if (blockStatement.Parent is ConstructorDeclaration) { |
|
style = policy.ConstructorBraceStyle; |
|
} else if (blockStatement.Parent is DestructorDeclaration) { |
|
style = policy.DestructorBraceStyle; |
|
} else if (blockStatement.Parent is MethodDeclaration) { |
|
style = policy.MethodBraceStyle; |
|
} else if (blockStatement.Parent is Accessor) { |
|
if (blockStatement.Parent.Role == PropertyDeclaration.GetterRole) |
|
style = policy.PropertyGetBraceStyle; |
|
else if (blockStatement.Parent.Role == PropertyDeclaration.SetterRole) |
|
style = policy.PropertySetBraceStyle; |
|
else if (blockStatement.Parent.Role == CustomEventDeclaration.AddAccessorRole) |
|
style = policy.EventAddBraceStyle; |
|
else if (blockStatement.Parent.Role == CustomEventDeclaration.RemoveAccessorRole) |
|
style = policy.EventRemoveBraceStyle; |
|
else |
|
throw new NotSupportedException ("Unknown type of accessor"); |
|
} else { |
|
style = policy.StatementBraceStyle; |
|
} |
|
OpenBrace (style); |
|
foreach (var node in blockStatement.Statements) { |
|
node.AcceptVisitor (this, data); |
|
} |
|
CloseBrace (style); |
|
NewLine (); |
|
return EndNode (blockStatement); |
|
} |
|
|
|
public object VisitBreakStatement (BreakStatement breakStatement, object data) |
|
{ |
|
StartNode (breakStatement); |
|
WriteKeyword ("break"); |
|
Semicolon (); |
|
return EndNode (breakStatement); |
|
} |
|
|
|
public object VisitCheckedStatement (CheckedStatement checkedStatement, object data) |
|
{ |
|
StartNode (checkedStatement); |
|
WriteKeyword ("checked"); |
|
checkedStatement.Body.AcceptVisitor (this, data); |
|
return EndNode (checkedStatement); |
|
} |
|
|
|
public object VisitContinueStatement (ContinueStatement continueStatement, object data) |
|
{ |
|
StartNode (continueStatement); |
|
WriteKeyword ("continue"); |
|
Semicolon (); |
|
return EndNode (continueStatement); |
|
} |
|
|
|
public object VisitDoWhileStatement (DoWhileStatement doWhileStatement, object data) |
|
{ |
|
StartNode (doWhileStatement); |
|
WriteKeyword ("do", DoWhileStatement.DoKeywordRole); |
|
WriteEmbeddedStatement (doWhileStatement.EmbeddedStatement); |
|
WriteKeyword ("while", DoWhileStatement.WhileKeywordRole); |
|
Space (policy.SpaceBeforeWhileParentheses); |
|
LPar (); |
|
Space (policy.SpacesWithinWhileParentheses); |
|
doWhileStatement.Condition.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinWhileParentheses); |
|
RPar (); |
|
Semicolon (); |
|
return EndNode (doWhileStatement); |
|
} |
|
|
|
public object VisitEmptyStatement (EmptyStatement emptyStatement, object data) |
|
{ |
|
StartNode (emptyStatement); |
|
Semicolon (); |
|
return EndNode (emptyStatement); |
|
} |
|
|
|
public object VisitExpressionStatement (ExpressionStatement expressionStatement, object data) |
|
{ |
|
StartNode (expressionStatement); |
|
expressionStatement.Expression.AcceptVisitor (this, data); |
|
Semicolon (); |
|
return EndNode (expressionStatement); |
|
} |
|
|
|
public object VisitFixedStatement (FixedStatement fixedStatement, object data) |
|
{ |
|
StartNode (fixedStatement); |
|
WriteKeyword ("fixed"); |
|
Space (policy.SpaceBeforeUsingParentheses); |
|
LPar (); |
|
Space (policy.SpacesWithinUsingParentheses); |
|
fixedStatement.Type.AcceptVisitor (this, data); |
|
Space (); |
|
WriteCommaSeparatedList (fixedStatement.Variables); |
|
Space (policy.SpacesWithinUsingParentheses); |
|
RPar (); |
|
WriteEmbeddedStatement (fixedStatement.EmbeddedStatement); |
|
return EndNode (fixedStatement); |
|
} |
|
|
|
public object VisitForeachStatement (ForeachStatement foreachStatement, object data) |
|
{ |
|
StartNode (foreachStatement); |
|
WriteKeyword ("foreach"); |
|
Space (policy.SpaceBeforeForeachParentheses); |
|
LPar (); |
|
Space (policy.SpacesWithinForeachParentheses); |
|
foreachStatement.VariableType.AcceptVisitor (this, data); |
|
Space (); |
|
WriteIdentifier (foreachStatement.VariableName); |
|
WriteKeyword ("in", ForeachStatement.Roles.InKeyword); |
|
Space (); |
|
foreachStatement.InExpression.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinForeachParentheses); |
|
RPar (); |
|
WriteEmbeddedStatement (foreachStatement.EmbeddedStatement); |
|
return EndNode (foreachStatement); |
|
} |
|
|
|
public object VisitForStatement (ForStatement forStatement, object data) |
|
{ |
|
StartNode (forStatement); |
|
WriteKeyword ("for"); |
|
Space (policy.SpaceBeforeForParentheses); |
|
LPar (); |
|
Space (policy.SpacesWithinForParentheses); |
|
|
|
WriteCommaSeparatedList (forStatement.Initializers.SafeCast<Statement, AstNode> ()); |
|
Space (policy.SpaceBeforeForSemicolon); |
|
WriteToken (";", AstNode.Roles.Semicolon); |
|
Space (policy.SpaceAfterForSemicolon); |
|
|
|
forStatement.Condition.AcceptVisitor (this, data); |
|
Space (policy.SpaceBeforeForSemicolon); |
|
WriteToken (";", AstNode.Roles.Semicolon); |
|
Space (policy.SpaceAfterForSemicolon); |
|
|
|
WriteCommaSeparatedList (forStatement.Iterators.SafeCast<Statement, AstNode> ()); |
|
|
|
Space (policy.SpacesWithinForParentheses); |
|
RPar (); |
|
WriteEmbeddedStatement (forStatement.EmbeddedStatement); |
|
return EndNode (forStatement); |
|
} |
|
|
|
public object VisitGotoCaseStatement (GotoCaseStatement gotoCaseStatement, object data) |
|
{ |
|
StartNode (gotoCaseStatement); |
|
WriteKeyword ("goto"); |
|
WriteKeyword ("case", GotoCaseStatement.CaseKeywordRole); |
|
Space (); |
|
gotoCaseStatement.LabelExpression.AcceptVisitor (this, data); |
|
Semicolon (); |
|
return EndNode (gotoCaseStatement); |
|
} |
|
|
|
public object VisitGotoDefaultStatement (GotoDefaultStatement gotoDefaultStatement, object data) |
|
{ |
|
StartNode (gotoDefaultStatement); |
|
WriteKeyword ("goto"); |
|
WriteKeyword ("default", GotoDefaultStatement.DefaultKeywordRole); |
|
Semicolon (); |
|
return EndNode (gotoDefaultStatement); |
|
} |
|
|
|
public object VisitGotoStatement (GotoStatement gotoStatement, object data) |
|
{ |
|
StartNode (gotoStatement); |
|
WriteKeyword ("goto"); |
|
WriteIdentifier (gotoStatement.Label); |
|
Semicolon (); |
|
return EndNode (gotoStatement); |
|
} |
|
|
|
public object VisitIfElseStatement (IfElseStatement ifElseStatement, object data) |
|
{ |
|
StartNode (ifElseStatement); |
|
WriteKeyword ("if", IfElseStatement.IfKeywordRole); |
|
Space (policy.SpaceBeforeIfParentheses); |
|
LPar (); |
|
Space (policy.SpacesWithinIfParentheses); |
|
ifElseStatement.Condition.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinIfParentheses); |
|
RPar (); |
|
WriteEmbeddedStatement (ifElseStatement.TrueStatement); |
|
if (!ifElseStatement.FalseStatement.IsNull) { |
|
WriteKeyword ("else", IfElseStatement.ElseKeywordRole); |
|
WriteEmbeddedStatement (ifElseStatement.FalseStatement); |
|
} |
|
return EndNode (ifElseStatement); |
|
} |
|
|
|
public object VisitLabelStatement (LabelStatement labelStatement, object data) |
|
{ |
|
StartNode (labelStatement); |
|
WriteIdentifier (labelStatement.Label); |
|
WriteToken (":", LabelStatement.Roles.Colon); |
|
bool foundLabelledStatement = false; |
|
for (AstNode tmp = labelStatement.NextSibling; tmp != null; tmp = tmp.NextSibling) { |
|
if (tmp.Role == labelStatement.Role) { |
|
foundLabelledStatement = true; |
|
} |
|
} |
|
if (!foundLabelledStatement) { |
|
// introduce an EmptyStatement so that the output becomes syntactically valid |
|
WriteToken(";", LabelStatement.Roles.Semicolon); |
|
} |
|
NewLine (); |
|
return EndNode (labelStatement); |
|
} |
|
|
|
public object VisitLockStatement (LockStatement lockStatement, object data) |
|
{ |
|
StartNode (lockStatement); |
|
WriteKeyword ("lock"); |
|
Space (policy.SpaceBeforeLockParentheses); |
|
LPar (); |
|
Space (policy.SpacesWithinLockParentheses); |
|
lockStatement.Expression.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinLockParentheses); |
|
RPar (); |
|
WriteEmbeddedStatement (lockStatement.EmbeddedStatement); |
|
return EndNode (lockStatement); |
|
} |
|
|
|
public object VisitReturnStatement (ReturnStatement returnStatement, object data) |
|
{ |
|
StartNode (returnStatement); |
|
WriteKeyword ("return"); |
|
if (!returnStatement.Expression.IsNull) { |
|
Space (); |
|
returnStatement.Expression.AcceptVisitor (this, data); |
|
} |
|
Semicolon (); |
|
return EndNode (returnStatement); |
|
} |
|
|
|
public object VisitSwitchStatement (SwitchStatement switchStatement, object data) |
|
{ |
|
StartNode (switchStatement); |
|
WriteKeyword ("switch"); |
|
Space (policy.SpaceBeforeSwitchParentheses); |
|
LPar (); |
|
Space (policy.SpacesWithinSwitchParentheses); |
|
switchStatement.Expression.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinSwitchParentheses); |
|
RPar (); |
|
OpenBrace (policy.StatementBraceStyle); |
|
if (!policy.IndentSwitchBody) |
|
formatter.Unindent (); |
|
|
|
foreach (var section in switchStatement.SwitchSections) |
|
section.AcceptVisitor (this, data); |
|
|
|
if (!policy.IndentSwitchBody) |
|
formatter.Indent (); |
|
CloseBrace (policy.StatementBraceStyle); |
|
NewLine (); |
|
return EndNode (switchStatement); |
|
} |
|
|
|
public object VisitSwitchSection (SwitchSection switchSection, object data) |
|
{ |
|
StartNode (switchSection); |
|
bool first = true; |
|
foreach (var label in switchSection.CaseLabels) { |
|
if (!first) |
|
NewLine (); |
|
label.AcceptVisitor (this, data); |
|
first = false; |
|
} |
|
if (policy.IndentCaseBody) |
|
formatter.Indent (); |
|
|
|
foreach (var statement in switchSection.Statements) { |
|
NewLine (); |
|
statement.AcceptVisitor (this, data); |
|
} |
|
|
|
if (policy.IndentCaseBody) |
|
formatter.Unindent (); |
|
|
|
return EndNode (switchSection); |
|
} |
|
|
|
public object VisitCaseLabel (CaseLabel caseLabel, object data) |
|
{ |
|
StartNode (caseLabel); |
|
if (caseLabel.Expression.IsNull) { |
|
WriteKeyword ("default"); |
|
} else { |
|
WriteKeyword ("case"); |
|
Space (); |
|
caseLabel.Expression.AcceptVisitor (this, data); |
|
} |
|
WriteToken (":", CaseLabel.Roles.Colon); |
|
return EndNode (caseLabel); |
|
} |
|
|
|
public object VisitThrowStatement (ThrowStatement throwStatement, object data) |
|
{ |
|
StartNode (throwStatement); |
|
WriteKeyword ("throw"); |
|
if (!throwStatement.Expression.IsNull) { |
|
Space (); |
|
throwStatement.Expression.AcceptVisitor (this, data); |
|
} |
|
Semicolon (); |
|
return EndNode (throwStatement); |
|
} |
|
|
|
public object VisitTryCatchStatement (TryCatchStatement tryCatchStatement, object data) |
|
{ |
|
StartNode (tryCatchStatement); |
|
WriteKeyword ("try", TryCatchStatement.TryKeywordRole); |
|
tryCatchStatement.TryBlock.AcceptVisitor (this, data); |
|
foreach (var catchClause in tryCatchStatement.CatchClauses) |
|
catchClause.AcceptVisitor (this, data); |
|
if (!tryCatchStatement.FinallyBlock.IsNull) { |
|
WriteKeyword ("finally", TryCatchStatement.FinallyKeywordRole); |
|
tryCatchStatement.FinallyBlock.AcceptVisitor (this, data); |
|
} |
|
return EndNode (tryCatchStatement); |
|
} |
|
|
|
public object VisitCatchClause (CatchClause catchClause, object data) |
|
{ |
|
StartNode (catchClause); |
|
WriteKeyword ("catch"); |
|
if (!catchClause.Type.IsNull) { |
|
Space (policy.SpaceBeforeCatchParentheses); |
|
LPar (); |
|
Space (policy.SpacesWithinCatchParentheses); |
|
catchClause.Type.AcceptVisitor (this, data); |
|
if (!string.IsNullOrEmpty(catchClause.VariableName)) { |
|
Space (); |
|
WriteIdentifier (catchClause.VariableName); |
|
} |
|
Space (policy.SpacesWithinCatchParentheses); |
|
RPar (); |
|
} |
|
catchClause.Body.AcceptVisitor (this, data); |
|
return EndNode (catchClause); |
|
} |
|
|
|
public object VisitUncheckedStatement (UncheckedStatement uncheckedStatement, object data) |
|
{ |
|
StartNode (uncheckedStatement); |
|
WriteKeyword ("unchecked"); |
|
uncheckedStatement.Body.AcceptVisitor (this, data); |
|
return EndNode (uncheckedStatement); |
|
} |
|
|
|
public object VisitUnsafeStatement (UnsafeStatement unsafeStatement, object data) |
|
{ |
|
StartNode (unsafeStatement); |
|
WriteKeyword ("unsafe"); |
|
unsafeStatement.Body.AcceptVisitor (this, data); |
|
return EndNode (unsafeStatement); |
|
} |
|
|
|
public object VisitUsingStatement (UsingStatement usingStatement, object data) |
|
{ |
|
StartNode (usingStatement); |
|
WriteKeyword ("using"); |
|
Space (policy.SpaceBeforeUsingParentheses); |
|
LPar (); |
|
Space (policy.SpacesWithinUsingParentheses); |
|
|
|
usingStatement.ResourceAcquisition.AcceptVisitor (this, data); |
|
|
|
Space (policy.SpacesWithinUsingParentheses); |
|
RPar (); |
|
|
|
WriteEmbeddedStatement (usingStatement.EmbeddedStatement); |
|
|
|
return EndNode (usingStatement); |
|
} |
|
|
|
public object VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, object data) |
|
{ |
|
StartNode (variableDeclarationStatement); |
|
variableDeclarationStatement.Type.AcceptVisitor (this, data); |
|
Space (); |
|
WriteCommaSeparatedList (variableDeclarationStatement.Variables); |
|
Semicolon (); |
|
return EndNode (variableDeclarationStatement); |
|
} |
|
|
|
public object VisitWhileStatement (WhileStatement whileStatement, object data) |
|
{ |
|
StartNode (whileStatement); |
|
WriteKeyword ("while", WhileStatement.WhileKeywordRole); |
|
Space (policy.SpaceBeforeWhileParentheses); |
|
LPar (); |
|
Space (policy.SpacesWithinWhileParentheses); |
|
whileStatement.Condition.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinWhileParentheses); |
|
RPar (); |
|
WriteEmbeddedStatement (whileStatement.EmbeddedStatement); |
|
return EndNode (whileStatement); |
|
} |
|
|
|
public object VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement, object data) |
|
{ |
|
StartNode (yieldBreakStatement); |
|
WriteKeyword ("yield", YieldBreakStatement.YieldKeywordRole); |
|
WriteKeyword ("break", YieldBreakStatement.BreakKeywordRole); |
|
Semicolon (); |
|
return EndNode (yieldBreakStatement); |
|
} |
|
|
|
public object VisitYieldStatement (YieldStatement yieldStatement, object data) |
|
{ |
|
StartNode (yieldStatement); |
|
WriteKeyword ("yield", YieldStatement.YieldKeywordRole); |
|
WriteKeyword ("return", YieldStatement.ReturnKeywordRole); |
|
Space (); |
|
yieldStatement.Expression.AcceptVisitor (this, data); |
|
Semicolon (); |
|
return EndNode (yieldStatement); |
|
} |
|
|
|
#endregion |
|
|
|
#region TypeMembers |
|
public object VisitAccessor (Accessor accessor, object data) |
|
{ |
|
StartNode (accessor); |
|
WriteAttributes (accessor.Attributes); |
|
WriteModifiers (accessor.ModifierTokens); |
|
if (accessor.Role == PropertyDeclaration.GetterRole) { |
|
WriteKeyword ("get"); |
|
} else if (accessor.Role == PropertyDeclaration.SetterRole) { |
|
WriteKeyword ("set"); |
|
} else if (accessor.Role == CustomEventDeclaration.AddAccessorRole) { |
|
WriteKeyword ("add"); |
|
} else if (accessor.Role == CustomEventDeclaration.RemoveAccessorRole) { |
|
WriteKeyword ("remove"); |
|
} |
|
WriteMethodBody (accessor.Body); |
|
return EndNode (accessor); |
|
} |
|
|
|
public object VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, object data) |
|
{ |
|
StartNode (constructorDeclaration); |
|
WriteAttributes (constructorDeclaration.Attributes); |
|
WriteModifiers (constructorDeclaration.ModifierTokens); |
|
TypeDeclaration type = constructorDeclaration.Parent as TypeDeclaration; |
|
WriteIdentifier (type != null ? type.Name : constructorDeclaration.Name); |
|
Space (policy.SpaceBeforeConstructorDeclarationParentheses); |
|
WriteCommaSeparatedListInParenthesis (constructorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); |
|
if (!constructorDeclaration.Initializer.IsNull) { |
|
Space (); |
|
constructorDeclaration.Initializer.AcceptVisitor (this, data); |
|
} |
|
WriteMethodBody (constructorDeclaration.Body); |
|
return EndNode (constructorDeclaration); |
|
} |
|
|
|
public object VisitConstructorInitializer (ConstructorInitializer constructorInitializer, object data) |
|
{ |
|
StartNode (constructorInitializer); |
|
WriteToken (":", ConstructorInitializer.Roles.Colon); |
|
Space (); |
|
if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.This) { |
|
WriteKeyword ("this"); |
|
} else { |
|
WriteKeyword ("base"); |
|
} |
|
Space (policy.SpaceBeforeMethodCallParentheses); |
|
WriteCommaSeparatedListInParenthesis (constructorInitializer.Arguments, policy.SpaceWithinMethodCallParentheses); |
|
return EndNode (constructorInitializer); |
|
} |
|
|
|
public object VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, object data) |
|
{ |
|
StartNode (destructorDeclaration); |
|
WriteAttributes (destructorDeclaration.Attributes); |
|
WriteModifiers (destructorDeclaration.ModifierTokens); |
|
WriteToken ("~", DestructorDeclaration.TildeRole); |
|
TypeDeclaration type = destructorDeclaration.Parent as TypeDeclaration; |
|
WriteIdentifier (type != null ? type.Name : destructorDeclaration.Name); |
|
Space (policy.SpaceBeforeConstructorDeclarationParentheses); |
|
LPar (); |
|
RPar (); |
|
WriteMethodBody (destructorDeclaration.Body); |
|
return EndNode (destructorDeclaration); |
|
} |
|
|
|
public object VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration, object data) |
|
{ |
|
StartNode (enumMemberDeclaration); |
|
WriteAttributes (enumMemberDeclaration.Attributes); |
|
WriteModifiers (enumMemberDeclaration.ModifierTokens); |
|
WriteIdentifier (enumMemberDeclaration.Name); |
|
if (!enumMemberDeclaration.Initializer.IsNull) { |
|
Space (policy.SpaceAroundAssignment); |
|
WriteToken ("=", EnumMemberDeclaration.Roles.Assign); |
|
Space (policy.SpaceAroundAssignment); |
|
enumMemberDeclaration.Initializer.AcceptVisitor (this, data); |
|
} |
|
return EndNode (enumMemberDeclaration); |
|
} |
|
|
|
public object VisitEventDeclaration (EventDeclaration eventDeclaration, object data) |
|
{ |
|
StartNode (eventDeclaration); |
|
WriteAttributes (eventDeclaration.Attributes); |
|
WriteModifiers (eventDeclaration.ModifierTokens); |
|
WriteKeyword ("event"); |
|
eventDeclaration.ReturnType.AcceptVisitor (this, data); |
|
Space (); |
|
WriteCommaSeparatedList (eventDeclaration.Variables); |
|
Semicolon (); |
|
return EndNode (eventDeclaration); |
|
} |
|
|
|
public object VisitCustomEventDeclaration (CustomEventDeclaration customEventDeclaration, object data) |
|
{ |
|
StartNode (customEventDeclaration); |
|
WriteAttributes (customEventDeclaration.Attributes); |
|
WriteModifiers (customEventDeclaration.ModifierTokens); |
|
WriteKeyword ("event"); |
|
customEventDeclaration.ReturnType.AcceptVisitor (this, data); |
|
Space (); |
|
WritePrivateImplementationType (customEventDeclaration.PrivateImplementationType); |
|
WriteIdentifier (customEventDeclaration.Name); |
|
OpenBrace (policy.EventBraceStyle); |
|
// output add/remove in their original order |
|
foreach (AstNode node in customEventDeclaration.Children) { |
|
if (node.Role == CustomEventDeclaration.AddAccessorRole || node.Role == CustomEventDeclaration.RemoveAccessorRole) { |
|
node.AcceptVisitor (this, data); |
|
} |
|
} |
|
CloseBrace (policy.EventBraceStyle); |
|
NewLine (); |
|
return EndNode (customEventDeclaration); |
|
} |
|
|
|
public object VisitFieldDeclaration (FieldDeclaration fieldDeclaration, object data) |
|
{ |
|
StartNode (fieldDeclaration); |
|
WriteAttributes (fieldDeclaration.Attributes); |
|
WriteModifiers (fieldDeclaration.ModifierTokens); |
|
fieldDeclaration.ReturnType.AcceptVisitor (this, data); |
|
Space (); |
|
WriteCommaSeparatedList (fieldDeclaration.Variables); |
|
Semicolon (); |
|
return EndNode (fieldDeclaration); |
|
} |
|
|
|
public object VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, object data) |
|
{ |
|
StartNode (fixedFieldDeclaration); |
|
WriteAttributes (fixedFieldDeclaration.Attributes); |
|
WriteModifiers (fixedFieldDeclaration.ModifierTokens); |
|
WriteKeyword ("fixed"); |
|
Space (); |
|
fixedFieldDeclaration.ReturnType.AcceptVisitor (this, data); |
|
Space (); |
|
WriteCommaSeparatedList (fixedFieldDeclaration.Variables); |
|
Semicolon (); |
|
return EndNode (fixedFieldDeclaration); |
|
} |
|
|
|
public object VisitFixedVariableInitializer (FixedVariableInitializer fixedVariableInitializer, object data) |
|
{ |
|
StartNode (fixedVariableInitializer); |
|
WriteIdentifier (fixedVariableInitializer.Name); |
|
if (!fixedVariableInitializer.CountExpression.IsNull) { |
|
WriteToken ("[", AstNode.Roles.LBracket); |
|
Space (policy.SpacesWithinBrackets); |
|
fixedVariableInitializer.CountExpression.AcceptVisitor (this, data); |
|
Space (policy.SpacesWithinBrackets); |
|
WriteToken ("]", AstNode.Roles.RBracket); |
|
} |
|
return EndNode (fixedVariableInitializer); |
|
} |
|
|
|
public object VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, object data) |
|
{ |
|
StartNode (indexerDeclaration); |
|
WriteAttributes (indexerDeclaration.Attributes); |
|
WriteModifiers (indexerDeclaration.ModifierTokens); |
|
indexerDeclaration.ReturnType.AcceptVisitor (this, data); |
|
WritePrivateImplementationType (indexerDeclaration.PrivateImplementationType); |
|
WriteKeyword ("this"); |
|
Space (policy.SpaceBeforeMethodDeclarationParentheses); |
|
WriteCommaSeparatedListInBrackets (indexerDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); |
|
OpenBrace (policy.PropertyBraceStyle); |
|
// output get/set in their original order |
|
foreach (AstNode node in indexerDeclaration.Children) { |
|
if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) { |
|
node.AcceptVisitor (this, data); |
|
} |
|
} |
|
CloseBrace (policy.PropertyBraceStyle); |
|
NewLine (); |
|
return EndNode (indexerDeclaration); |
|
} |
|
|
|
public object VisitMethodDeclaration (MethodDeclaration methodDeclaration, object data) |
|
{ |
|
StartNode (methodDeclaration); |
|
WriteAttributes (methodDeclaration.Attributes); |
|
WriteModifiers (methodDeclaration.ModifierTokens); |
|
methodDeclaration.ReturnType.AcceptVisitor (this, data); |
|
Space (); |
|
WritePrivateImplementationType (methodDeclaration.PrivateImplementationType); |
|
WriteIdentifier (methodDeclaration.Name); |
|
WriteTypeParameters (methodDeclaration.TypeParameters); |
|
Space (policy.SpaceBeforeMethodDeclarationParentheses); |
|
WriteCommaSeparatedListInParenthesis (methodDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); |
|
foreach (Constraint constraint in methodDeclaration.Constraints) { |
|
constraint.AcceptVisitor (this, data); |
|
} |
|
WriteMethodBody (methodDeclaration.Body); |
|
return EndNode (methodDeclaration); |
|
} |
|
|
|
public object VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, object data) |
|
{ |
|
StartNode (operatorDeclaration); |
|
WriteAttributes (operatorDeclaration.Attributes); |
|
WriteModifiers (operatorDeclaration.ModifierTokens); |
|
if (operatorDeclaration.OperatorType == OperatorType.Explicit) { |
|
WriteKeyword ("explicit", OperatorDeclaration.OperatorTypeRole); |
|
} else if (operatorDeclaration.OperatorType == OperatorType.Implicit) { |
|
WriteKeyword ("implicit", OperatorDeclaration.OperatorTypeRole); |
|
} else { |
|
operatorDeclaration.ReturnType.AcceptVisitor (this, data); |
|
} |
|
WriteKeyword ("operator", OperatorDeclaration.OperatorKeywordRole); |
|
Space (); |
|
if (operatorDeclaration.OperatorType == OperatorType.Explicit |
|
|| operatorDeclaration.OperatorType == OperatorType.Implicit) { |
|
operatorDeclaration.ReturnType.AcceptVisitor (this, data); |
|
} else { |
|
WriteToken (OperatorDeclaration.GetToken (operatorDeclaration.OperatorType), OperatorDeclaration.OperatorTypeRole); |
|
} |
|
Space (policy.SpaceBeforeMethodDeclarationParentheses); |
|
WriteCommaSeparatedListInParenthesis (operatorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); |
|
WriteMethodBody (operatorDeclaration.Body); |
|
return EndNode (operatorDeclaration); |
|
} |
|
|
|
public object VisitParameterDeclaration (ParameterDeclaration parameterDeclaration, object data) |
|
{ |
|
StartNode (parameterDeclaration); |
|
WriteAttributes (parameterDeclaration.Attributes); |
|
switch (parameterDeclaration.ParameterModifier) { |
|
case ParameterModifier.Ref: |
|
WriteKeyword ("ref", ParameterDeclaration.ModifierRole); |
|
break; |
|
case ParameterModifier.Out: |
|
WriteKeyword ("out", ParameterDeclaration.ModifierRole); |
|
break; |
|
case ParameterModifier.Params: |
|
WriteKeyword ("params", ParameterDeclaration.ModifierRole); |
|
break; |
|
case ParameterModifier.This: |
|
WriteKeyword ("this", ParameterDeclaration.ModifierRole); |
|
break; |
|
} |
|
parameterDeclaration.Type.AcceptVisitor (this, data); |
|
if (!parameterDeclaration.Type.IsNull && !string.IsNullOrEmpty (parameterDeclaration.Name)) |
|
Space (); |
|
if (!string.IsNullOrEmpty (parameterDeclaration.Name)) |
|
WriteIdentifier (parameterDeclaration.Name); |
|
if (!parameterDeclaration.DefaultExpression.IsNull) { |
|
Space (policy.SpaceAroundAssignment); |
|
WriteToken ("=", ParameterDeclaration.Roles.Assign); |
|
Space (policy.SpaceAroundAssignment); |
|
parameterDeclaration.DefaultExpression.AcceptVisitor (this, data); |
|
} |
|
return EndNode (parameterDeclaration); |
|
} |
|
|
|
public object VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, object data) |
|
{ |
|
StartNode (propertyDeclaration); |
|
WriteAttributes (propertyDeclaration.Attributes); |
|
WriteModifiers (propertyDeclaration.ModifierTokens); |
|
propertyDeclaration.ReturnType.AcceptVisitor (this, data); |
|
Space (); |
|
WritePrivateImplementationType (propertyDeclaration.PrivateImplementationType); |
|
WriteIdentifier (propertyDeclaration.Name); |
|
OpenBrace (policy.PropertyBraceStyle); |
|
// output get/set in their original order |
|
foreach (AstNode node in propertyDeclaration.Children) { |
|
if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) { |
|
node.AcceptVisitor (this, data); |
|
} |
|
} |
|
CloseBrace (policy.PropertyBraceStyle); |
|
NewLine (); |
|
return EndNode (propertyDeclaration); |
|
} |
|
|
|
#endregion |
|
|
|
#region Other nodes |
|
public object VisitVariableInitializer (VariableInitializer variableInitializer, object data) |
|
{ |
|
StartNode (variableInitializer); |
|
WriteIdentifier (variableInitializer.Name); |
|
if (!variableInitializer.Initializer.IsNull) { |
|
Space (policy.SpaceAroundAssignment); |
|
WriteToken ("=", VariableInitializer.Roles.Assign); |
|
Space (policy.SpaceAroundAssignment); |
|
variableInitializer.Initializer.AcceptVisitor (this, data); |
|
} |
|
return EndNode (variableInitializer); |
|
} |
|
|
|
public object VisitCompilationUnit (CompilationUnit compilationUnit, object data) |
|
{ |
|
// don't do node tracking as we visit all children directly |
|
foreach (AstNode node in compilationUnit.Children) |
|
node.AcceptVisitor (this, data); |
|
return null; |
|
} |
|
|
|
public object VisitSimpleType (SimpleType simpleType, object data) |
|
{ |
|
StartNode (simpleType); |
|
WriteIdentifier (simpleType.Identifier); |
|
WriteTypeArguments (simpleType.TypeArguments); |
|
return EndNode (simpleType); |
|
} |
|
|
|
public object VisitMemberType (MemberType memberType, object data) |
|
{ |
|
StartNode (memberType); |
|
memberType.Target.AcceptVisitor (this, data); |
|
if (memberType.IsDoubleColon) |
|
WriteToken ("::", MemberType.Roles.Dot); |
|
else |
|
WriteToken (".", MemberType.Roles.Dot); |
|
WriteIdentifier (memberType.MemberName); |
|
WriteTypeArguments (memberType.TypeArguments); |
|
return EndNode (memberType); |
|
} |
|
|
|
public object VisitComposedType (ComposedType composedType, object data) |
|
{ |
|
StartNode (composedType); |
|
composedType.BaseType.AcceptVisitor (this, data); |
|
if (composedType.HasNullableSpecifier) |
|
WriteToken ("?", ComposedType.NullableRole); |
|
for (int i = 0; i < composedType.PointerRank; i++) |
|
WriteToken ("*", ComposedType.PointerRole); |
|
foreach (var node in composedType.ArraySpecifiers) |
|
node.AcceptVisitor (this, data); |
|
return EndNode (composedType); |
|
} |
|
|
|
public object VisitArraySpecifier (ArraySpecifier arraySpecifier, object data) |
|
{ |
|
StartNode (arraySpecifier); |
|
WriteToken ("[", ArraySpecifier.Roles.LBracket); |
|
foreach (var comma in arraySpecifier.GetChildrenByRole(ArraySpecifier.Roles.Comma)) { |
|
WriteSpecialsUpToNode (comma); |
|
formatter.WriteToken (","); |
|
lastWritten = LastWritten.Other; |
|
} |
|
WriteToken ("]", ArraySpecifier.Roles.RBracket); |
|
return EndNode (arraySpecifier); |
|
} |
|
|
|
public object VisitPrimitiveType (PrimitiveType primitiveType, object data) |
|
{ |
|
StartNode (primitiveType); |
|
WriteKeyword (primitiveType.Keyword); |
|
if (primitiveType.Keyword == "new") { |
|
// new() constraint |
|
LPar (); |
|
RPar (); |
|
} |
|
return EndNode (primitiveType); |
|
} |
|
|
|
public object VisitComment (Comment comment, object data) |
|
{ |
|
if (lastWritten == LastWritten.Division) { |
|
// When there's a comment starting after a division operator |
|
// "1.0 / /*comment*/a", then we need to insert a space in front of the comment. |
|
formatter.Space (); |
|
} |
|
formatter.StartNode(comment); |
|
formatter.WriteComment (comment.CommentType, comment.Content); |
|
formatter.EndNode(comment); |
|
lastWritten = LastWritten.Whitespace; |
|
return null; |
|
} |
|
|
|
public object VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration, object data) |
|
{ |
|
StartNode (typeParameterDeclaration); |
|
WriteAttributes (typeParameterDeclaration.Attributes); |
|
switch (typeParameterDeclaration.Variance) { |
|
case VarianceModifier.Invariant: |
|
break; |
|
case VarianceModifier.Covariant: |
|
WriteKeyword ("out"); |
|
break; |
|
case VarianceModifier.Contravariant: |
|
WriteKeyword ("in"); |
|
break; |
|
default: |
|
throw new NotSupportedException ("Invalid value for VarianceModifier"); |
|
} |
|
WriteIdentifier (typeParameterDeclaration.Name); |
|
return EndNode (typeParameterDeclaration); |
|
} |
|
|
|
public object VisitConstraint (Constraint constraint, object data) |
|
{ |
|
StartNode (constraint); |
|
Space (); |
|
WriteKeyword ("where"); |
|
WriteIdentifier (constraint.TypeParameter); |
|
Space (); |
|
WriteToken (":", Constraint.ColonRole); |
|
Space (); |
|
WriteCommaSeparatedList (constraint.BaseTypes); |
|
return EndNode (constraint); |
|
} |
|
|
|
public object VisitCSharpTokenNode (CSharpTokenNode cSharpTokenNode, object data) |
|
{ |
|
CSharpModifierToken mod = cSharpTokenNode as CSharpModifierToken; |
|
if (mod != null) { |
|
StartNode (mod); |
|
WriteKeyword (CSharpModifierToken.GetModifierName (mod.Modifier)); |
|
return EndNode (mod); |
|
} else { |
|
throw new NotSupportedException ("Should never visit individual tokens"); |
|
} |
|
} |
|
|
|
public object VisitIdentifier (Identifier identifier, object data) |
|
{ |
|
StartNode (identifier); |
|
WriteIdentifier (identifier.Name); |
|
return EndNode (identifier); |
|
} |
|
|
|
#endregion |
|
|
|
#region Pattern Nodes |
|
public object VisitPatternPlaceholder (AstNode placeholder, PatternMatching.Pattern pattern, object data) |
|
{ |
|
StartNode (placeholder); |
|
pattern.AcceptVisitor (this, data); |
|
return EndNode (placeholder); |
|
} |
|
|
|
object IPatternAstVisitor<object, object>.VisitAnyNode (AnyNode anyNode, object data) |
|
{ |
|
if (!string.IsNullOrEmpty (anyNode.GroupName)) { |
|
WriteIdentifier (anyNode.GroupName); |
|
WriteToken (":", AstNode.Roles.Colon); |
|
} |
|
WriteKeyword ("anyNode"); |
|
return null; |
|
} |
|
|
|
object IPatternAstVisitor<object, object>.VisitBackreference (Backreference backreference, object data) |
|
{ |
|
WriteKeyword ("backreference"); |
|
LPar (); |
|
WriteIdentifier (backreference.ReferencedGroupName); |
|
RPar (); |
|
return null; |
|
} |
|
|
|
object IPatternAstVisitor<object, object>.VisitIdentifierExpressionBackreference (IdentifierExpressionBackreference identifierExpressionBackreference, object data) |
|
{ |
|
WriteKeyword ("identifierBackreference"); |
|
LPar (); |
|
WriteIdentifier (identifierExpressionBackreference.ReferencedGroupName); |
|
RPar (); |
|
return null; |
|
} |
|
|
|
object IPatternAstVisitor<object, object>.VisitChoice (Choice choice, object data) |
|
{ |
|
WriteKeyword ("choice"); |
|
Space (); |
|
LPar (); |
|
NewLine (); |
|
formatter.Indent (); |
|
foreach (INode alternative in choice) { |
|
VisitNodeInPattern (alternative, data); |
|
if (alternative != choice.Last ()) |
|
WriteToken (",", AstNode.Roles.Comma); |
|
NewLine (); |
|
} |
|
formatter.Unindent (); |
|
RPar (); |
|
return null; |
|
} |
|
|
|
object IPatternAstVisitor<object, object>.VisitNamedNode (NamedNode namedNode, object data) |
|
{ |
|
if (!string.IsNullOrEmpty (namedNode.GroupName)) { |
|
WriteIdentifier (namedNode.GroupName); |
|
WriteToken (":", AstNode.Roles.Colon); |
|
} |
|
VisitNodeInPattern (namedNode.ChildNode, data); |
|
return null; |
|
} |
|
|
|
object IPatternAstVisitor<object, object>.VisitRepeat (Repeat repeat, object data) |
|
{ |
|
WriteKeyword ("repeat"); |
|
LPar (); |
|
if (repeat.MinCount != 0 || repeat.MaxCount != int.MaxValue) { |
|
WriteIdentifier (repeat.MinCount.ToString ()); |
|
WriteToken (",", AstNode.Roles.Comma); |
|
WriteIdentifier (repeat.MaxCount.ToString ()); |
|
WriteToken (",", AstNode.Roles.Comma); |
|
} |
|
VisitNodeInPattern (repeat.ChildNode, data); |
|
RPar (); |
|
return null; |
|
} |
|
|
|
object IPatternAstVisitor<object, object>.VisitOptionalNode (OptionalNode optionalNode, object data) |
|
{ |
|
WriteKeyword ("optional"); |
|
LPar (); |
|
VisitNodeInPattern (optionalNode.ChildNode, data); |
|
RPar (); |
|
return null; |
|
} |
|
|
|
void VisitNodeInPattern (INode childNode, object data) |
|
{ |
|
AstNode astNode = childNode as AstNode; |
|
if (astNode != null) { |
|
astNode.AcceptVisitor (this, data); |
|
} else { |
|
Pattern pattern = childNode as Pattern; |
|
if (pattern != null) { |
|
pattern.AcceptVisitor (this, data); |
|
} else { |
|
throw new InvalidOperationException ("Unknown node type in pattern"); |
|
} |
|
} |
|
} |
|
#endregion |
|
} |
|
}
|
|
|