#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
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.
 
 
 
 
 
 

2526 lines
82 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 System.Threading.Tasks;
using ICSharpCode.NRefactory.PatternMatching;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp
{
/// <summary>
/// Outputs the AST.
/// </summary>
public class CSharpOutputVisitor : IAstVisitor
{
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 CSharpOutputVisitor (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 CSharpOutputVisitor (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
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);
formatter.StartNode (node);
}
void EndNode (AstNode node)
{
Debug.Assert (node == containerStack.Peek ());
AstNode pos = positionStack.Pop ();
Debug.Assert (pos == null || pos.Parent == node);
WriteSpecials (pos, null);
containerStack.Pop ();
formatter.EndNode (node);
}
#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 == Roles.Comment || pos.Role == Roles.PreProcessorDirective) {
pos.AcceptVisitor (this);
}
}
}
/// <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)
{
WriteSpecialsUpToRole (role, null);
}
void WriteSpecialsUpToRole (Role role, AstNode nextNode)
{
if (positionStack.Count == 0)
return;
// 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 == role) {
WriteSpecials (positionStack.Pop (), pos);
// Push the next sibling because the node matching the role is not a special,
// and should be considered to be already handled.
positionStack.Push (pos.NextSibling);
// This is necessary for OptionalComma() to work correctly.
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)
{
if (positionStack.Count == 0)
return;
for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) {
if (pos == node) {
WriteSpecials (positionStack.Pop (), pos);
// Push the next sibling because the node itself is not a special,
// and should be considered to be already handled.
positionStack.Push (pos.NextSibling);
// This is necessary for OptionalComma() to work correctly.
break;
}
}
}
#endregion
#region Comma
/// <summary>
/// Writes a comma.
/// </summary>
/// <param name="nextNode">The next node after the comma.</param>
/// <param name="noSpaceAfterComma">When set prevents printing a space after comma.</param>
void Comma (AstNode nextNode, bool noSpaceAfterComma = false)
{
WriteSpecialsUpToRole (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.
}
/// <summary>
/// Writes an optional comma, e.g. at the end of an enum declaration or in an array initializer
/// </summary>
void OptionalComma()
{
// Look if there's a comma after the current node, and insert it if it exists.
AstNode pos = positionStack.Peek();
while (pos != null && pos.NodeType == NodeType.Whitespace)
pos = pos.NextSibling;
if (pos != null && pos.Role == Roles.Comma)
Comma(null, noSpaceAfterComma: true);
}
/// <summary>
/// Writes an optional semicolon, e.g. at the end of a type or namespace declaration.
/// </summary>
void OptionalSemicolon()
{
// Look if there's a semicolon after the current node, and insert it if it exists.
AstNode pos = positionStack.Peek();
while (pos != null && pos.NodeType == NodeType.Whitespace)
pos = pos.NextSibling;
if (pos != null && pos.Role == Roles.Semicolon)
Semicolon();
}
void WriteCommaSeparatedList (IEnumerable<AstNode> list)
{
bool isFirst = true;
foreach (AstNode node in list) {
if (isFirst) {
isFirst = false;
} else {
Comma (node);
}
node.AcceptVisitor (this);
}
}
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 (Roles.LBracket);
if (list.Any ()) {
Space (spaceWithin);
WriteCommaSeparatedList (list);
Space (spaceWithin);
}
WriteToken (Roles.RBracket);
}
void WriteCommaSeparatedListInBrackets (IEnumerable<Expression> list)
{
WriteToken (Roles.LBracket);
if (list.Any ()) {
Space (policy.SpacesWithinBrackets);
WriteCommaSeparatedList (list);
Space (policy.SpacesWithinBrackets);
}
WriteToken (Roles.RBracket);
}
#endregion
#region Write tokens
/// <summary>
/// Writes a keyword, and all specials up to
/// </summary>
void WriteKeyword (TokenRole tokenRole)
{
WriteKeyword (tokenRole.Token, tokenRole);
}
void WriteKeyword (string token, Role tokenRole = null)
{
if (tokenRole != null)
WriteSpecialsUpToRole (tokenRole);
if (lastWritten == LastWritten.KeywordOrIdentifier)
formatter.Space ();
formatter.WriteKeyword (token);
lastWritten = LastWritten.KeywordOrIdentifier;
}
/* void WriteKeyword (string keyword, Role tokenRole)
{
WriteSpecialsUpToRole (tokenRole);
if (lastWritten == LastWritten.KeywordOrIdentifier)
formatter.Space ();
formatter.WriteKeyword (keyword);
lastWritten = LastWritten.KeywordOrIdentifier;
}*/
void WriteIdentifier (string identifier, Role<Identifier> identifierRole = null)
{
WriteSpecialsUpToRole (identifierRole ?? 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 (TokenRole tokenRole)
{
WriteToken (tokenRole.Token, tokenRole);
}
void WriteToken (string token, Role 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 (Roles.LPar);
}
void RPar ()
{
WriteToken (Roles.RPar);
}
/// <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 (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 (Roles.LBrace);
formatter.OpenBrace (style);
lastWritten = LastWritten.Other;
}
void CloseBrace (BraceStyle style)
{
WriteSpecialsUpToRole (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;
foreach (AstNode ancestor in context.Ancestors) {
if (ancestor is QueryExpression && queryKeywords.Contains (identifier))
return true;
if (identifier == "await") {
// with lambdas/anonymous methods,
if (ancestor is LambdaExpression)
return ((LambdaExpression)ancestor).IsAsync;
if (ancestor is AnonymousMethodExpression)
return ((AnonymousMethodExpression)ancestor).IsAsync;
if (ancestor is EntityDeclaration)
return (((EntityDeclaration)ancestor).Modifiers & Modifiers.Async) == Modifiers.Async;
}
}
return false;
}
#endregion
#region Write constructs
void WriteTypeArguments (IEnumerable<AstType> typeArguments)
{
if (typeArguments.Any ()) {
WriteToken (Roles.LChevron);
WriteCommaSeparatedList (typeArguments);
WriteToken (Roles.RChevron);
}
}
public void WriteTypeParameters (IEnumerable<TypeParameterDeclaration> typeParameters)
{
if (typeParameters.Any ()) {
WriteToken (Roles.LChevron);
WriteCommaSeparatedList (typeParameters);
WriteToken (Roles.RChevron);
}
}
void WriteModifiers (IEnumerable<CSharpModifierToken> modifierTokens)
{
foreach (CSharpModifierToken modifier in modifierTokens) {
modifier.AcceptVisitor (this);
}
}
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 (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);
else {
NewLine ();
formatter.Indent ();
embeddedStatement.AcceptVisitor (this);
formatter.Unindent ();
}
}
void WriteMethodBody (BlockStatement body)
{
if (body.IsNull)
Semicolon ();
else
VisitBlockStatement (body);
}
void WriteAttributes (IEnumerable<AttributeSection> attributes)
{
foreach (AttributeSection attr in attributes) {
attr.AcceptVisitor (this);
}
}
void WritePrivateImplementationType (AstType privateImplementationType)
{
if (!privateImplementationType.IsNull) {
privateImplementationType.AcceptVisitor (this);
WriteToken (Roles.Dot);
}
}
#endregion
#region Expressions
public void VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression)
{
StartNode (anonymousMethodExpression);
if (anonymousMethodExpression.IsAsync) {
WriteKeyword (AnonymousMethodExpression.AsyncModifierRole);
Space ();
}
WriteKeyword (AnonymousMethodExpression.DelegateKeywordRole);
if (anonymousMethodExpression.HasParameterList) {
Space (policy.SpaceBeforeMethodDeclarationParentheses);
WriteCommaSeparatedListInParenthesis (anonymousMethodExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
}
anonymousMethodExpression.Body.AcceptVisitor (this);
EndNode (anonymousMethodExpression);
}
public void VisitUndocumentedExpression (UndocumentedExpression undocumentedExpression)
{
StartNode (undocumentedExpression);
switch (undocumentedExpression.UndocumentedExpressionType) {
case UndocumentedExpressionType.ArgList:
case UndocumentedExpressionType.ArgListAccess:
WriteKeyword (UndocumentedExpression.ArglistKeywordRole);
break;
case UndocumentedExpressionType.MakeRef:
WriteKeyword (UndocumentedExpression.MakerefKeywordRole);
break;
case UndocumentedExpressionType.RefType:
WriteKeyword (UndocumentedExpression.ReftypeKeywordRole);
break;
case UndocumentedExpressionType.RefValue:
WriteKeyword (UndocumentedExpression.RefvalueKeywordRole);
break;
}
if (undocumentedExpression.Arguments.Count > 0) {
Space (policy.SpaceBeforeMethodCallParentheses);
WriteCommaSeparatedListInParenthesis (undocumentedExpression.Arguments, policy.SpaceWithinMethodCallParentheses);
}
EndNode (undocumentedExpression);
}
public void VisitArrayCreateExpression (ArrayCreateExpression arrayCreateExpression)
{
StartNode (arrayCreateExpression);
WriteKeyword (ArrayCreateExpression.NewKeywordRole);
arrayCreateExpression.Type.AcceptVisitor (this);
if (arrayCreateExpression.Arguments.Count > 0)
WriteCommaSeparatedListInBrackets (arrayCreateExpression.Arguments);
foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers)
specifier.AcceptVisitor (this);
arrayCreateExpression.Initializer.AcceptVisitor (this);
EndNode (arrayCreateExpression);
}
public void VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression)
{
StartNode (arrayInitializerExpression);
// "new List<int> { { 1 } }" and "new List<int> { 1 }" are the same semantically.
// We also use the same AST for both: we always use two nested ArrayInitializerExpressions
// for collection initializers, even if the user did not write nested brackets.
// The output visitor will output nested braces only if they are necessary,
// or if the braces tokens exist in the AST.
bool bracesAreOptional = arrayInitializerExpression.Elements.Count == 1
&& IsObjectOrCollectionInitializer(arrayInitializerExpression.Parent)
&& !CanBeConfusedWithObjectInitializer(arrayInitializerExpression.Elements.Single());
if (bracesAreOptional && arrayInitializerExpression.LBraceToken.IsNull) {
arrayInitializerExpression.Elements.Single().AcceptVisitor (this);
} else {
PrintInitializerElements(arrayInitializerExpression.Elements);
}
EndNode (arrayInitializerExpression);
}
bool CanBeConfusedWithObjectInitializer(Expression expr)
{
// "int a; new List<int> { a = 1 };" is an object initalizers and invalid, but
// "int a; new List<int> { { a = 1 } };" is a valid collection initializer.
AssignmentExpression ae = expr as AssignmentExpression;
return ae != null && ae.Operator == AssignmentOperatorType.Assign;
}
bool IsObjectOrCollectionInitializer(AstNode node)
{
if (!(node is ArrayInitializerExpression))
return false;
if (node.Parent is ObjectCreateExpression)
return node.Role == ObjectCreateExpression.InitializerRole;
if (node.Parent is NamedExpression)
return node.Role == Roles.Expression;
return false;
}
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);
}
OptionalComma();
NewLine();
CloseBrace(style);
}
public void VisitAsExpression (AsExpression asExpression)
{
StartNode (asExpression);
asExpression.Expression.AcceptVisitor (this);
Space ();
WriteKeyword (AsExpression.AsKeywordRole);
Space ();
asExpression.Type.AcceptVisitor (this);
EndNode (asExpression);
}
public void VisitAssignmentExpression (AssignmentExpression assignmentExpression)
{
StartNode (assignmentExpression);
assignmentExpression.Left.AcceptVisitor (this);
Space (policy.SpaceAroundAssignment);
WriteToken (AssignmentExpression.GetOperatorRole (assignmentExpression.Operator));
Space (policy.SpaceAroundAssignment);
assignmentExpression.Right.AcceptVisitor (this);
EndNode (assignmentExpression);
}
public void VisitBaseReferenceExpression (BaseReferenceExpression baseReferenceExpression)
{
StartNode (baseReferenceExpression);
WriteKeyword ("base", baseReferenceExpression.Role);
EndNode (baseReferenceExpression);
}
public void VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression)
{
StartNode (binaryOperatorExpression);
binaryOperatorExpression.Left.AcceptVisitor (this);
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.GetOperatorRole (binaryOperatorExpression.Operator));
Space (spacePolicy);
binaryOperatorExpression.Right.AcceptVisitor (this);
EndNode (binaryOperatorExpression);
}
public void VisitCastExpression (CastExpression castExpression)
{
StartNode (castExpression);
LPar ();
Space (policy.SpacesWithinCastParentheses);
castExpression.Type.AcceptVisitor (this);
Space (policy.SpacesWithinCastParentheses);
RPar ();
Space (policy.SpaceAfterTypecast);
castExpression.Expression.AcceptVisitor (this);
EndNode (castExpression);
}
public void VisitCheckedExpression (CheckedExpression checkedExpression)
{
StartNode (checkedExpression);
WriteKeyword (CheckedExpression.CheckedKeywordRole);
LPar ();
Space (policy.SpacesWithinCheckedExpressionParantheses);
checkedExpression.Expression.AcceptVisitor (this);
Space (policy.SpacesWithinCheckedExpressionParantheses);
RPar ();
EndNode (checkedExpression);
}
public void VisitConditionalExpression (ConditionalExpression conditionalExpression)
{
StartNode (conditionalExpression);
conditionalExpression.Condition.AcceptVisitor (this);
Space (policy.SpaceBeforeConditionalOperatorCondition);
WriteToken (ConditionalExpression.QuestionMarkRole);
Space (policy.SpaceAfterConditionalOperatorCondition);
conditionalExpression.TrueExpression.AcceptVisitor (this);
Space (policy.SpaceBeforeConditionalOperatorSeparator);
WriteToken (ConditionalExpression.ColonRole);
Space (policy.SpaceAfterConditionalOperatorSeparator);
conditionalExpression.FalseExpression.AcceptVisitor (this);
EndNode (conditionalExpression);
}
public void VisitDefaultValueExpression (DefaultValueExpression defaultValueExpression)
{
StartNode (defaultValueExpression);
WriteKeyword (DefaultValueExpression.DefaultKeywordRole);
LPar ();
Space (policy.SpacesWithinTypeOfParentheses);
defaultValueExpression.Type.AcceptVisitor (this);
Space (policy.SpacesWithinTypeOfParentheses);
RPar ();
EndNode (defaultValueExpression);
}
public void VisitDirectionExpression (DirectionExpression directionExpression)
{
StartNode (directionExpression);
switch (directionExpression.FieldDirection) {
case FieldDirection.Out:
WriteKeyword (DirectionExpression.OutKeywordRole);
break;
case FieldDirection.Ref:
WriteKeyword (DirectionExpression.RefKeywordRole);
break;
default:
throw new NotSupportedException ("Invalid value for FieldDirection");
}
Space ();
directionExpression.Expression.AcceptVisitor (this);
EndNode (directionExpression);
}
public void VisitIdentifierExpression (IdentifierExpression identifierExpression)
{
StartNode (identifierExpression);
WriteIdentifier (identifierExpression.Identifier);
WriteTypeArguments (identifierExpression.TypeArguments);
EndNode (identifierExpression);
}
public void VisitIndexerExpression (IndexerExpression indexerExpression)
{
StartNode (indexerExpression);
indexerExpression.Target.AcceptVisitor (this);
Space (policy.SpaceBeforeMethodCallParentheses);
WriteCommaSeparatedListInBrackets (indexerExpression.Arguments);
EndNode (indexerExpression);
}
public void VisitInvocationExpression (InvocationExpression invocationExpression)
{
StartNode (invocationExpression);
invocationExpression.Target.AcceptVisitor (this);
Space (policy.SpaceBeforeMethodCallParentheses);
WriteCommaSeparatedListInParenthesis (invocationExpression.Arguments, policy.SpaceWithinMethodCallParentheses);
EndNode (invocationExpression);
}
public void VisitIsExpression (IsExpression isExpression)
{
StartNode (isExpression);
isExpression.Expression.AcceptVisitor (this);
Space ();
WriteKeyword (IsExpression.IsKeywordRole);
isExpression.Type.AcceptVisitor (this);
EndNode (isExpression);
}
public void VisitLambdaExpression (LambdaExpression lambdaExpression)
{
StartNode (lambdaExpression);
if (lambdaExpression.IsAsync) {
WriteKeyword (LambdaExpression.AsyncModifierRole);
Space ();
}
if (LambdaNeedsParenthesis (lambdaExpression)) {
WriteCommaSeparatedListInParenthesis (lambdaExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
} else {
lambdaExpression.Parameters.Single ().AcceptVisitor (this);
}
Space ();
WriteToken (LambdaExpression.ArrowRole);
Space ();
lambdaExpression.Body.AcceptVisitor (this);
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 void VisitMemberReferenceExpression (MemberReferenceExpression memberReferenceExpression)
{
StartNode (memberReferenceExpression);
memberReferenceExpression.Target.AcceptVisitor (this);
WriteToken (Roles.Dot);
WriteIdentifier (memberReferenceExpression.MemberName);
WriteTypeArguments (memberReferenceExpression.TypeArguments);
EndNode (memberReferenceExpression);
}
public void VisitNamedArgumentExpression (NamedArgumentExpression namedArgumentExpression)
{
StartNode (namedArgumentExpression);
WriteIdentifier (namedArgumentExpression.Identifier);
WriteToken(Roles.Colon);
Space ();
namedArgumentExpression.Expression.AcceptVisitor (this);
EndNode (namedArgumentExpression);
}
public void VisitNamedExpression (NamedExpression namedExpression)
{
StartNode (namedExpression);
WriteIdentifier (namedExpression.Identifier);
Space();
WriteToken(Roles.Assign);
Space ();
namedExpression.Expression.AcceptVisitor (this);
EndNode (namedExpression);
}
public void VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression)
{
StartNode (nullReferenceExpression);
WriteKeyword ("null", nullReferenceExpression.Role);
EndNode (nullReferenceExpression);
}
public void VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression)
{
StartNode (objectCreateExpression);
WriteKeyword (ObjectCreateExpression.NewKeywordRole);
objectCreateExpression.Type.AcceptVisitor (this);
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);
EndNode (objectCreateExpression);
}
public void VisitAnonymousTypeCreateExpression (AnonymousTypeCreateExpression anonymousTypeCreateExpression)
{
StartNode (anonymousTypeCreateExpression);
WriteKeyword (AnonymousTypeCreateExpression.NewKeywordRole);
PrintInitializerElements(anonymousTypeCreateExpression.Initializers);
EndNode (anonymousTypeCreateExpression);
}
public void VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression)
{
StartNode (parenthesizedExpression);
LPar ();
Space (policy.SpacesWithinParentheses);
parenthesizedExpression.Expression.AcceptVisitor (this);
Space (policy.SpacesWithinParentheses);
RPar ();
EndNode (parenthesizedExpression);
}
public void VisitPointerReferenceExpression (PointerReferenceExpression pointerReferenceExpression)
{
StartNode (pointerReferenceExpression);
pointerReferenceExpression.Target.AcceptVisitor (this);
WriteToken (PointerReferenceExpression.ArrowRole);
WriteIdentifier (pointerReferenceExpression.MemberName);
WriteTypeArguments (pointerReferenceExpression.TypeArguments);
EndNode (pointerReferenceExpression);
}
public void VisitEmptyExpression (EmptyExpression emptyExpression)
{
StartNode (emptyExpression);
EndNode (emptyExpression);
}
#region VisitPrimitiveExpression
public void VisitPrimitiveExpression (PrimitiveExpression primitiveExpression)
{
StartNode (primitiveExpression);
if (!string.IsNullOrEmpty (primitiveExpression.LiteralValue)) {
formatter.WriteToken (primitiveExpression.LiteralValue);
} else {
WritePrimitiveValue (primitiveExpression.Value);
}
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 (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 (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 void VisitSizeOfExpression (SizeOfExpression sizeOfExpression)
{
StartNode (sizeOfExpression);
WriteKeyword (SizeOfExpression.SizeofKeywordRole);
LPar ();
Space (policy.SpacesWithinSizeOfParentheses);
sizeOfExpression.Type.AcceptVisitor (this);
Space (policy.SpacesWithinSizeOfParentheses);
RPar ();
EndNode (sizeOfExpression);
}
public void VisitStackAllocExpression (StackAllocExpression stackAllocExpression)
{
StartNode (stackAllocExpression);
WriteKeyword (StackAllocExpression.StackallocKeywordRole);
stackAllocExpression.Type.AcceptVisitor (this);
WriteCommaSeparatedListInBrackets (new[] { stackAllocExpression.CountExpression });
EndNode (stackAllocExpression);
}
public void VisitThisReferenceExpression (ThisReferenceExpression thisReferenceExpression)
{
StartNode (thisReferenceExpression);
WriteKeyword ("this", thisReferenceExpression.Role);
EndNode (thisReferenceExpression);
}
public void VisitTypeOfExpression (TypeOfExpression typeOfExpression)
{
StartNode (typeOfExpression);
WriteKeyword (TypeOfExpression.TypeofKeywordRole);
LPar ();
Space (policy.SpacesWithinTypeOfParentheses);
typeOfExpression.Type.AcceptVisitor (this);
Space (policy.SpacesWithinTypeOfParentheses);
RPar ();
EndNode (typeOfExpression);
}
public void VisitTypeReferenceExpression (TypeReferenceExpression typeReferenceExpression)
{
StartNode (typeReferenceExpression);
typeReferenceExpression.Type.AcceptVisitor (this);
EndNode (typeReferenceExpression);
}
public void VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression)
{
StartNode (unaryOperatorExpression);
UnaryOperatorType opType = unaryOperatorExpression.Operator;
var opSymbol = UnaryOperatorExpression.GetOperatorRole (opType);
if (opType == UnaryOperatorType.Await) {
WriteKeyword (opSymbol);
} else if (!(opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)) {
WriteToken (opSymbol);
}
unaryOperatorExpression.Expression.AcceptVisitor (this);
if (opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)
WriteToken (opSymbol);
EndNode (unaryOperatorExpression);
}
public void VisitUncheckedExpression (UncheckedExpression uncheckedExpression)
{
StartNode (uncheckedExpression);
WriteKeyword (UncheckedExpression.UncheckedKeywordRole);
LPar ();
Space (policy.SpacesWithinCheckedExpressionParantheses);
uncheckedExpression.Expression.AcceptVisitor (this);
Space (policy.SpacesWithinCheckedExpressionParantheses);
RPar ();
EndNode (uncheckedExpression);
}
#endregion
#region Query Expressions
public void VisitQueryExpression (QueryExpression queryExpression)
{
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);
}
if (indent)
formatter.Unindent();
EndNode (queryExpression);
}
public void VisitQueryContinuationClause (QueryContinuationClause queryContinuationClause)
{
StartNode (queryContinuationClause);
queryContinuationClause.PrecedingQuery.AcceptVisitor (this);
Space ();
WriteKeyword (QueryContinuationClause.IntoKeywordRole);
Space ();
WriteIdentifier (queryContinuationClause.Identifier);
EndNode (queryContinuationClause);
}
public void VisitQueryFromClause (QueryFromClause queryFromClause)
{
StartNode (queryFromClause);
WriteKeyword (QueryFromClause.FromKeywordRole);
queryFromClause.Type.AcceptVisitor (this);
Space ();
WriteIdentifier (queryFromClause.Identifier);
Space ();
WriteKeyword (QueryFromClause.InKeywordRole);
Space ();
queryFromClause.Expression.AcceptVisitor (this);
EndNode (queryFromClause);
}
public void VisitQueryLetClause (QueryLetClause queryLetClause)
{
StartNode (queryLetClause);
WriteKeyword (QueryLetClause.LetKeywordRole);
Space ();
WriteIdentifier (queryLetClause.Identifier);
Space (policy.SpaceAroundAssignment);
WriteToken (Roles.Assign);
Space (policy.SpaceAroundAssignment);
queryLetClause.Expression.AcceptVisitor (this);
EndNode (queryLetClause);
}
public void VisitQueryWhereClause (QueryWhereClause queryWhereClause)
{
StartNode (queryWhereClause);
WriteKeyword (QueryWhereClause.WhereKeywordRole);
Space ();
queryWhereClause.Condition.AcceptVisitor (this);
EndNode (queryWhereClause);
}
public void VisitQueryJoinClause (QueryJoinClause queryJoinClause)
{
StartNode (queryJoinClause);
WriteKeyword (QueryJoinClause.JoinKeywordRole);
queryJoinClause.Type.AcceptVisitor (this);
Space ();
WriteIdentifier (queryJoinClause.JoinIdentifier, QueryJoinClause.JoinIdentifierRole);
Space ();
WriteKeyword (QueryJoinClause.InKeywordRole);
Space ();
queryJoinClause.InExpression.AcceptVisitor (this);
Space ();
WriteKeyword (QueryJoinClause.OnKeywordRole);
Space ();
queryJoinClause.OnExpression.AcceptVisitor (this);
Space ();
WriteKeyword (QueryJoinClause.EqualsKeywordRole);
Space ();
queryJoinClause.EqualsExpression.AcceptVisitor (this);
if (queryJoinClause.IsGroupJoin) {
Space ();
WriteKeyword (QueryJoinClause.IntoKeywordRole);
WriteIdentifier (queryJoinClause.IntoIdentifier, QueryJoinClause.IntoIdentifierRole);
}
EndNode (queryJoinClause);
}
public void VisitQueryOrderClause (QueryOrderClause queryOrderClause)
{
StartNode (queryOrderClause);
WriteKeyword (QueryOrderClause.OrderbyKeywordRole);
Space ();
WriteCommaSeparatedList (queryOrderClause.Orderings);
EndNode (queryOrderClause);
}
public void VisitQueryOrdering (QueryOrdering queryOrdering)
{
StartNode (queryOrdering);
queryOrdering.Expression.AcceptVisitor (this);
switch (queryOrdering.Direction) {
case QueryOrderingDirection.Ascending:
Space ();
WriteKeyword (QueryOrdering.AscendingKeywordRole);
break;
case QueryOrderingDirection.Descending:
Space ();
WriteKeyword (QueryOrdering.DescendingKeywordRole);
break;
}
EndNode (queryOrdering);
}
public void VisitQuerySelectClause (QuerySelectClause querySelectClause)
{
StartNode (querySelectClause);
WriteKeyword (QuerySelectClause.SelectKeywordRole);
Space ();
querySelectClause.Expression.AcceptVisitor (this);
EndNode (querySelectClause);
}
public void VisitQueryGroupClause (QueryGroupClause queryGroupClause)
{
StartNode (queryGroupClause);
WriteKeyword (QueryGroupClause.GroupKeywordRole);
Space ();
queryGroupClause.Projection.AcceptVisitor (this);
Space ();
WriteKeyword (QueryGroupClause.ByKeywordRole);
Space ();
queryGroupClause.Key.AcceptVisitor (this);
EndNode (queryGroupClause);
}
#endregion
#region GeneralScope
public void VisitAttribute (Attribute attribute)
{
StartNode (attribute);
attribute.Type.AcceptVisitor (this);
if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole (Roles.LPar).IsNull) {
Space (policy.SpaceBeforeMethodCallParentheses);
WriteCommaSeparatedListInParenthesis (attribute.Arguments, policy.SpaceWithinMethodCallParentheses);
}
EndNode (attribute);
}
public void VisitAttributeSection (AttributeSection attributeSection)
{
StartNode (attributeSection);
WriteToken (Roles.LBracket);
if (!string.IsNullOrEmpty (attributeSection.AttributeTarget)) {
WriteToken (attributeSection.AttributeTarget, Roles.AttributeTargetRole);
WriteToken (Roles.Colon);
Space ();
}
WriteCommaSeparatedList (attributeSection.Attributes);
WriteToken (Roles.RBracket);
if (attributeSection.Parent is ParameterDeclaration || attributeSection.Parent is TypeParameterDeclaration)
Space ();
else
NewLine ();
EndNode (attributeSection);
}
public void VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration)
{
StartNode (delegateDeclaration);
WriteAttributes (delegateDeclaration.Attributes);
WriteModifiers (delegateDeclaration.ModifierTokens);
WriteKeyword (Roles.DelegateKeyword);
delegateDeclaration.ReturnType.AcceptVisitor (this);
Space ();
WriteIdentifier (delegateDeclaration.Name);
WriteTypeParameters (delegateDeclaration.TypeParameters);
Space (policy.SpaceBeforeDelegateDeclarationParentheses);
WriteCommaSeparatedListInParenthesis (delegateDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
foreach (Constraint constraint in delegateDeclaration.Constraints) {
constraint.AcceptVisitor (this);
}
Semicolon ();
EndNode (delegateDeclaration);
}
public void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
{
StartNode(namespaceDeclaration);
WriteKeyword(Roles.NamespaceKeyword);
WriteQualifiedIdentifier (namespaceDeclaration.Identifiers);
OpenBrace (policy.NamespaceBraceStyle);
foreach (var member in namespaceDeclaration.Members)
member.AcceptVisitor (this);
CloseBrace (policy.NamespaceBraceStyle);
OptionalSemicolon ();
NewLine ();
EndNode (namespaceDeclaration);
}
public void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{
StartNode(typeDeclaration);
WriteAttributes(typeDeclaration.Attributes);
WriteModifiers(typeDeclaration.ModifierTokens);
BraceStyle braceStyle;
switch (typeDeclaration.ClassType) {
case ClassType.Enum:
WriteKeyword(Roles.EnumKeyword);
braceStyle = policy.EnumBraceStyle;
break;
case ClassType.Interface:
WriteKeyword(Roles.InterfaceKeyword);
braceStyle = policy.InterfaceBraceStyle;
break;
case ClassType.Struct:
WriteKeyword(Roles.StructKeyword);
braceStyle = policy.StructBraceStyle;
break;
default:
WriteKeyword(Roles.ClassKeyword);
braceStyle = policy.ClassBraceStyle;
break;
}
WriteIdentifier(typeDeclaration.Name);
WriteTypeParameters(typeDeclaration.TypeParameters);
if (typeDeclaration.BaseTypes.Any()) {
Space();
WriteToken(Roles.Colon);
Space ();
WriteCommaSeparatedList (typeDeclaration.BaseTypes);
}
foreach (Constraint constraint in typeDeclaration.Constraints) {
constraint.AcceptVisitor (this);
}
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);
}
OptionalComma();
NewLine ();
} else {
foreach (var member in typeDeclaration.Members) {
member.AcceptVisitor (this);
}
}
CloseBrace (braceStyle);
OptionalSemicolon ();
NewLine ();
EndNode (typeDeclaration);
}
public void VisitUsingAliasDeclaration (UsingAliasDeclaration usingAliasDeclaration)
{
StartNode (usingAliasDeclaration);
WriteKeyword (UsingAliasDeclaration.UsingKeywordRole);
WriteIdentifier (usingAliasDeclaration.Alias, UsingAliasDeclaration.AliasRole);
Space (policy.SpaceAroundEqualityOperator);
WriteToken (Roles.Assign);
Space (policy.SpaceAroundEqualityOperator);
usingAliasDeclaration.Import.AcceptVisitor (this);
Semicolon ();
EndNode (usingAliasDeclaration);
}
public void VisitUsingDeclaration (UsingDeclaration usingDeclaration)
{
StartNode (usingDeclaration);
WriteKeyword (UsingDeclaration.UsingKeywordRole);
usingDeclaration.Import.AcceptVisitor (this);
Semicolon ();
EndNode (usingDeclaration);
}
public void VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration)
{
StartNode(externAliasDeclaration);
WriteKeyword(Roles.ExternKeyword);
Space ();
WriteKeyword (Roles.AliasKeyword);
Space ();
externAliasDeclaration.NameToken.AcceptVisitor (this);
Semicolon ();
EndNode (externAliasDeclaration);
}
#endregion
#region Statements
public void VisitBlockStatement (BlockStatement blockStatement)
{
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
style = policy.StatementBraceStyle;
} else {
style = policy.StatementBraceStyle;
}
OpenBrace (style);
foreach (var node in blockStatement.Statements) {
node.AcceptVisitor (this);
}
CloseBrace (style);
NewLine ();
EndNode (blockStatement);
}
public void VisitBreakStatement (BreakStatement breakStatement)
{
StartNode (breakStatement);
WriteKeyword ("break");
Semicolon ();
EndNode (breakStatement);
}
public void VisitCheckedStatement (CheckedStatement checkedStatement)
{
StartNode (checkedStatement);
WriteKeyword (CheckedStatement.CheckedKeywordRole);
checkedStatement.Body.AcceptVisitor (this);
EndNode (checkedStatement);
}
public void VisitContinueStatement (ContinueStatement continueStatement)
{
StartNode (continueStatement);
WriteKeyword ("continue");
Semicolon ();
EndNode (continueStatement);
}
public void VisitDoWhileStatement (DoWhileStatement doWhileStatement)
{
StartNode (doWhileStatement);
WriteKeyword (DoWhileStatement.DoKeywordRole);
WriteEmbeddedStatement (doWhileStatement.EmbeddedStatement);
WriteKeyword (DoWhileStatement.WhileKeywordRole);
Space (policy.SpaceBeforeWhileParentheses);
LPar ();
Space (policy.SpacesWithinWhileParentheses);
doWhileStatement.Condition.AcceptVisitor (this);
Space (policy.SpacesWithinWhileParentheses);
RPar ();
Semicolon ();
EndNode (doWhileStatement);
}
public void VisitEmptyStatement (EmptyStatement emptyStatement)
{
StartNode (emptyStatement);
Semicolon ();
EndNode (emptyStatement);
}
public void VisitExpressionStatement (ExpressionStatement expressionStatement)
{
StartNode (expressionStatement);
expressionStatement.Expression.AcceptVisitor (this);
Semicolon ();
EndNode (expressionStatement);
}
public void VisitFixedStatement (FixedStatement fixedStatement)
{
StartNode (fixedStatement);
WriteKeyword (FixedStatement.FixedKeywordRole);
Space (policy.SpaceBeforeUsingParentheses);
LPar ();
Space (policy.SpacesWithinUsingParentheses);
fixedStatement.Type.AcceptVisitor (this);
Space ();
WriteCommaSeparatedList (fixedStatement.Variables);
Space (policy.SpacesWithinUsingParentheses);
RPar ();
WriteEmbeddedStatement (fixedStatement.EmbeddedStatement);
EndNode (fixedStatement);
}
public void VisitForeachStatement (ForeachStatement foreachStatement)
{
StartNode (foreachStatement);
WriteKeyword (ForeachStatement.ForeachKeywordRole);
Space (policy.SpaceBeforeForeachParentheses);
LPar ();
Space (policy.SpacesWithinForeachParentheses);
foreachStatement.VariableType.AcceptVisitor (this);
Space ();
WriteIdentifier (foreachStatement.VariableName);
WriteKeyword (ForeachStatement.InKeywordRole);
Space ();
foreachStatement.InExpression.AcceptVisitor (this);
Space (policy.SpacesWithinForeachParentheses);
RPar ();
WriteEmbeddedStatement (foreachStatement.EmbeddedStatement);
EndNode (foreachStatement);
}
public void VisitForStatement (ForStatement forStatement)
{
StartNode (forStatement);
WriteKeyword (ForStatement.ForKeywordRole);
Space (policy.SpaceBeforeForParentheses);
LPar ();
Space (policy.SpacesWithinForParentheses);
WriteCommaSeparatedList (forStatement.Initializers);
Space (policy.SpaceBeforeForSemicolon);
WriteToken (Roles.Semicolon);
Space (policy.SpaceAfterForSemicolon);
forStatement.Condition.AcceptVisitor (this);
Space (policy.SpaceBeforeForSemicolon);
WriteToken (Roles.Semicolon);
Space (policy.SpaceAfterForSemicolon);
WriteCommaSeparatedList (forStatement.Iterators);
Space (policy.SpacesWithinForParentheses);
RPar ();
WriteEmbeddedStatement (forStatement.EmbeddedStatement);
EndNode (forStatement);
}
public void VisitGotoCaseStatement (GotoCaseStatement gotoCaseStatement)
{
StartNode (gotoCaseStatement);
WriteKeyword (GotoCaseStatement.GotoKeywordRole);
WriteKeyword (GotoCaseStatement.CaseKeywordRole);
Space ();
gotoCaseStatement.LabelExpression.AcceptVisitor (this);
Semicolon ();
EndNode (gotoCaseStatement);
}
public void VisitGotoDefaultStatement (GotoDefaultStatement gotoDefaultStatement)
{
StartNode (gotoDefaultStatement);
WriteKeyword (GotoDefaultStatement.GotoKeywordRole);
WriteKeyword (GotoDefaultStatement.DefaultKeywordRole);
Semicolon ();
EndNode (gotoDefaultStatement);
}
public void VisitGotoStatement (GotoStatement gotoStatement)
{
StartNode (gotoStatement);
WriteKeyword (GotoStatement.GotoKeywordRole);
WriteIdentifier (gotoStatement.Label);
Semicolon ();
EndNode (gotoStatement);
}
public void VisitIfElseStatement (IfElseStatement ifElseStatement)
{
StartNode (ifElseStatement);
WriteKeyword (IfElseStatement.IfKeywordRole);
Space (policy.SpaceBeforeIfParentheses);
LPar ();
Space (policy.SpacesWithinIfParentheses);
ifElseStatement.Condition.AcceptVisitor (this);
Space (policy.SpacesWithinIfParentheses);
RPar ();
WriteEmbeddedStatement (ifElseStatement.TrueStatement);
if (!ifElseStatement.FalseStatement.IsNull) {
WriteKeyword (IfElseStatement.ElseKeywordRole);
WriteEmbeddedStatement (ifElseStatement.FalseStatement);
}
EndNode (ifElseStatement);
}
public void VisitLabelStatement (LabelStatement labelStatement)
{
StartNode (labelStatement);
WriteIdentifier (labelStatement.Label);
WriteToken (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(Roles.Semicolon);
}
NewLine ();
EndNode (labelStatement);
}
public void VisitLockStatement (LockStatement lockStatement)
{
StartNode (lockStatement);
WriteKeyword (LockStatement.LockKeywordRole);
Space (policy.SpaceBeforeLockParentheses);
LPar ();
Space (policy.SpacesWithinLockParentheses);
lockStatement.Expression.AcceptVisitor (this);
Space (policy.SpacesWithinLockParentheses);
RPar ();
WriteEmbeddedStatement (lockStatement.EmbeddedStatement);
EndNode (lockStatement);
}
public void VisitReturnStatement (ReturnStatement returnStatement)
{
StartNode (returnStatement);
WriteKeyword (ReturnStatement.ReturnKeywordRole);
if (!returnStatement.Expression.IsNull) {
Space ();
returnStatement.Expression.AcceptVisitor (this);
}
Semicolon ();
EndNode (returnStatement);
}
public void VisitSwitchStatement (SwitchStatement switchStatement)
{
StartNode (switchStatement);
WriteKeyword (SwitchStatement.SwitchKeywordRole);
Space (policy.SpaceBeforeSwitchParentheses);
LPar ();
Space (policy.SpacesWithinSwitchParentheses);
switchStatement.Expression.AcceptVisitor (this);
Space (policy.SpacesWithinSwitchParentheses);
RPar ();
OpenBrace (policy.StatementBraceStyle);
if (!policy.IndentSwitchBody)
formatter.Unindent ();
foreach (var section in switchStatement.SwitchSections)
section.AcceptVisitor (this);
if (!policy.IndentSwitchBody)
formatter.Indent ();
CloseBrace (policy.StatementBraceStyle);
NewLine ();
EndNode (switchStatement);
}
public void VisitSwitchSection (SwitchSection switchSection)
{
StartNode (switchSection);
bool first = true;
foreach (var label in switchSection.CaseLabels) {
if (!first)
NewLine ();
label.AcceptVisitor (this);
first = false;
}
if (policy.IndentCaseBody)
formatter.Indent ();
foreach (var statement in switchSection.Statements) {
NewLine ();
statement.AcceptVisitor (this);
}
if (policy.IndentCaseBody)
formatter.Unindent ();
EndNode (switchSection);
}
public void VisitCaseLabel (CaseLabel caseLabel)
{
StartNode (caseLabel);
if (caseLabel.Expression.IsNull) {
WriteKeyword (CaseLabel.DefaultKeywordRole);
} else {
WriteKeyword (CaseLabel.CaseKeywordRole);
Space ();
caseLabel.Expression.AcceptVisitor (this);
}
WriteToken (Roles.Colon);
EndNode (caseLabel);
}
public void VisitThrowStatement (ThrowStatement throwStatement)
{
StartNode (throwStatement);
WriteKeyword (ThrowStatement.ThrowKeywordRole);
if (!throwStatement.Expression.IsNull) {
Space ();
throwStatement.Expression.AcceptVisitor (this);
}
Semicolon ();
EndNode (throwStatement);
}
public void VisitTryCatchStatement (TryCatchStatement tryCatchStatement)
{
StartNode (tryCatchStatement);
WriteKeyword (TryCatchStatement.TryKeywordRole);
tryCatchStatement.TryBlock.AcceptVisitor (this);
foreach (var catchClause in tryCatchStatement.CatchClauses)
catchClause.AcceptVisitor (this);
if (!tryCatchStatement.FinallyBlock.IsNull) {
WriteKeyword (TryCatchStatement.FinallyKeywordRole);
tryCatchStatement.FinallyBlock.AcceptVisitor (this);
}
EndNode (tryCatchStatement);
}
public void VisitCatchClause (CatchClause catchClause)
{
StartNode (catchClause);
WriteKeyword (CatchClause.CatchKeywordRole);
if (!catchClause.Type.IsNull) {
Space (policy.SpaceBeforeCatchParentheses);
LPar ();
Space (policy.SpacesWithinCatchParentheses);
catchClause.Type.AcceptVisitor (this);
if (!string.IsNullOrEmpty(catchClause.VariableName)) {
Space ();
WriteIdentifier (catchClause.VariableName);
}
Space (policy.SpacesWithinCatchParentheses);
RPar ();
}
catchClause.Body.AcceptVisitor (this);
EndNode (catchClause);
}
public void VisitUncheckedStatement (UncheckedStatement uncheckedStatement)
{
StartNode (uncheckedStatement);
WriteKeyword (UncheckedStatement.UncheckedKeywordRole);
uncheckedStatement.Body.AcceptVisitor (this);
EndNode (uncheckedStatement);
}
public void VisitUnsafeStatement (UnsafeStatement unsafeStatement)
{
StartNode (unsafeStatement);
WriteKeyword (UnsafeStatement.UnsafeKeywordRole);
unsafeStatement.Body.AcceptVisitor (this);
EndNode (unsafeStatement);
}
public void VisitUsingStatement (UsingStatement usingStatement)
{
StartNode (usingStatement);
WriteKeyword (UsingStatement.UsingKeywordRole);
Space (policy.SpaceBeforeUsingParentheses);
LPar ();
Space (policy.SpacesWithinUsingParentheses);
usingStatement.ResourceAcquisition.AcceptVisitor (this);
Space (policy.SpacesWithinUsingParentheses);
RPar ();
WriteEmbeddedStatement (usingStatement.EmbeddedStatement);
EndNode (usingStatement);
}
public void VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement)
{
StartNode (variableDeclarationStatement);
WriteModifiers (variableDeclarationStatement.GetChildrenByRole (VariableDeclarationStatement.ModifierRole));
variableDeclarationStatement.Type.AcceptVisitor (this);
Space ();
WriteCommaSeparatedList (variableDeclarationStatement.Variables);
Semicolon ();
EndNode (variableDeclarationStatement);
}
public void VisitWhileStatement (WhileStatement whileStatement)
{
StartNode (whileStatement);
WriteKeyword (WhileStatement.WhileKeywordRole);
Space (policy.SpaceBeforeWhileParentheses);
LPar ();
Space (policy.SpacesWithinWhileParentheses);
whileStatement.Condition.AcceptVisitor (this);
Space (policy.SpacesWithinWhileParentheses);
RPar ();
WriteEmbeddedStatement (whileStatement.EmbeddedStatement);
EndNode (whileStatement);
}
public void VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement)
{
StartNode (yieldBreakStatement);
WriteKeyword (YieldBreakStatement.YieldKeywordRole);
WriteKeyword (YieldBreakStatement.BreakKeywordRole);
Semicolon ();
EndNode (yieldBreakStatement);
}
public void VisitYieldReturnStatement (YieldReturnStatement yieldReturnStatement)
{
StartNode (yieldReturnStatement);
WriteKeyword (YieldReturnStatement.YieldKeywordRole);
WriteKeyword (YieldReturnStatement.ReturnKeywordRole);
Space ();
yieldReturnStatement.Expression.AcceptVisitor (this);
Semicolon ();
EndNode (yieldReturnStatement);
}
#endregion
#region TypeMembers
public void VisitAccessor (Accessor accessor)
{
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);
EndNode (accessor);
}
public void VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration)
{
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);
}
WriteMethodBody (constructorDeclaration.Body);
EndNode (constructorDeclaration);
}
public void VisitConstructorInitializer (ConstructorInitializer constructorInitializer)
{
StartNode (constructorInitializer);
WriteToken (Roles.Colon);
Space ();
if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.This) {
WriteKeyword (ConstructorInitializer.ThisKeywordRole);
} else {
WriteKeyword (ConstructorInitializer.BaseKeywordRole);
}
Space (policy.SpaceBeforeMethodCallParentheses);
WriteCommaSeparatedListInParenthesis (constructorInitializer.Arguments, policy.SpaceWithinMethodCallParentheses);
EndNode (constructorInitializer);
}
public void VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration)
{
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);
EndNode (destructorDeclaration);
}
public void VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration)
{
StartNode (enumMemberDeclaration);
WriteAttributes (enumMemberDeclaration.Attributes);
WriteModifiers (enumMemberDeclaration.ModifierTokens);
WriteIdentifier (enumMemberDeclaration.Name);
if (!enumMemberDeclaration.Initializer.IsNull) {
Space (policy.SpaceAroundAssignment);
WriteToken (Roles.Assign);
Space (policy.SpaceAroundAssignment);
enumMemberDeclaration.Initializer.AcceptVisitor (this);
}
EndNode (enumMemberDeclaration);
}
public void VisitEventDeclaration (EventDeclaration eventDeclaration)
{
StartNode (eventDeclaration);
WriteAttributes (eventDeclaration.Attributes);
WriteModifiers (eventDeclaration.ModifierTokens);
WriteKeyword (EventDeclaration.EventKeywordRole);
eventDeclaration.ReturnType.AcceptVisitor (this);
Space ();
WriteCommaSeparatedList (eventDeclaration.Variables);
Semicolon ();
EndNode (eventDeclaration);
}
public void VisitCustomEventDeclaration (CustomEventDeclaration customEventDeclaration)
{
StartNode (customEventDeclaration);
WriteAttributes (customEventDeclaration.Attributes);
WriteModifiers (customEventDeclaration.ModifierTokens);
WriteKeyword (CustomEventDeclaration.EventKeywordRole);
customEventDeclaration.ReturnType.AcceptVisitor (this);
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);
}
}
CloseBrace (policy.EventBraceStyle);
NewLine ();
EndNode (customEventDeclaration);
}
public void VisitFieldDeclaration (FieldDeclaration fieldDeclaration)
{
StartNode (fieldDeclaration);
WriteAttributes (fieldDeclaration.Attributes);
WriteModifiers (fieldDeclaration.ModifierTokens);
fieldDeclaration.ReturnType.AcceptVisitor (this);
Space ();
WriteCommaSeparatedList (fieldDeclaration.Variables);
Semicolon ();
EndNode (fieldDeclaration);
}
public void VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration)
{
StartNode (fixedFieldDeclaration);
WriteAttributes (fixedFieldDeclaration.Attributes);
WriteModifiers (fixedFieldDeclaration.ModifierTokens);
WriteKeyword (FixedFieldDeclaration.FixedKeywordRole);
Space ();
fixedFieldDeclaration.ReturnType.AcceptVisitor (this);
Space ();
WriteCommaSeparatedList (fixedFieldDeclaration.Variables);
Semicolon ();
EndNode (fixedFieldDeclaration);
}
public void VisitFixedVariableInitializer (FixedVariableInitializer fixedVariableInitializer)
{
StartNode (fixedVariableInitializer);
WriteIdentifier (fixedVariableInitializer.Name);
if (!fixedVariableInitializer.CountExpression.IsNull) {
WriteToken (Roles.LBracket);
Space (policy.SpacesWithinBrackets);
fixedVariableInitializer.CountExpression.AcceptVisitor (this);
Space (policy.SpacesWithinBrackets);
WriteToken (Roles.RBracket);
}
EndNode (fixedVariableInitializer);
}
public void VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration)
{
StartNode (indexerDeclaration);
WriteAttributes (indexerDeclaration.Attributes);
WriteModifiers (indexerDeclaration.ModifierTokens);
indexerDeclaration.ReturnType.AcceptVisitor (this);
WritePrivateImplementationType (indexerDeclaration.PrivateImplementationType);
WriteKeyword (IndexerDeclaration.ThisKeywordRole);
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);
}
}
CloseBrace (policy.PropertyBraceStyle);
NewLine ();
EndNode (indexerDeclaration);
}
public void VisitMethodDeclaration (MethodDeclaration methodDeclaration)
{
StartNode (methodDeclaration);
WriteAttributes (methodDeclaration.Attributes);
WriteModifiers (methodDeclaration.ModifierTokens);
methodDeclaration.ReturnType.AcceptVisitor (this);
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);
}
WriteMethodBody (methodDeclaration.Body);
EndNode (methodDeclaration);
}
public void VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration)
{
StartNode (operatorDeclaration);
WriteAttributes (operatorDeclaration.Attributes);
WriteModifiers (operatorDeclaration.ModifierTokens);
if (operatorDeclaration.OperatorType == OperatorType.Explicit) {
WriteKeyword (OperatorDeclaration.ExplicitRole);
} else if (operatorDeclaration.OperatorType == OperatorType.Implicit) {
WriteKeyword (OperatorDeclaration.ImplicitRole);
} else {
operatorDeclaration.ReturnType.AcceptVisitor (this);
}
WriteKeyword (OperatorDeclaration.OperatorKeywordRole);
Space ();
if (operatorDeclaration.OperatorType == OperatorType.Explicit
|| operatorDeclaration.OperatorType == OperatorType.Implicit) {
operatorDeclaration.ReturnType.AcceptVisitor (this);
} else {
WriteToken (OperatorDeclaration.GetToken (operatorDeclaration.OperatorType), OperatorDeclaration.GetRole (operatorDeclaration.OperatorType));
}
Space (policy.SpaceBeforeMethodDeclarationParentheses);
WriteCommaSeparatedListInParenthesis (operatorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
WriteMethodBody (operatorDeclaration.Body);
EndNode (operatorDeclaration);
}
public void VisitParameterDeclaration (ParameterDeclaration parameterDeclaration)
{
StartNode (parameterDeclaration);
WriteAttributes (parameterDeclaration.Attributes);
switch (parameterDeclaration.ParameterModifier) {
case ParameterModifier.Ref:
WriteKeyword (ParameterDeclaration.RefModifierRole);
break;
case ParameterModifier.Out:
WriteKeyword (ParameterDeclaration.OutModifierRole);
break;
case ParameterModifier.Params:
WriteKeyword (ParameterDeclaration.ParamsModifierRole);
break;
case ParameterModifier.This:
WriteKeyword (ParameterDeclaration.ThisModifierRole);
break;
}
parameterDeclaration.Type.AcceptVisitor (this);
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 (Roles.Assign);
Space (policy.SpaceAroundAssignment);
parameterDeclaration.DefaultExpression.AcceptVisitor (this);
}
EndNode (parameterDeclaration);
}
public void VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration)
{
StartNode (propertyDeclaration);
WriteAttributes (propertyDeclaration.Attributes);
WriteModifiers (propertyDeclaration.ModifierTokens);
propertyDeclaration.ReturnType.AcceptVisitor (this);
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);
}
}
CloseBrace (policy.PropertyBraceStyle);
NewLine ();
EndNode (propertyDeclaration);
}
#endregion
#region Other nodes
public void VisitVariableInitializer (VariableInitializer variableInitializer)
{
StartNode (variableInitializer);
WriteIdentifier (variableInitializer.Name);
if (!variableInitializer.Initializer.IsNull) {
Space (policy.SpaceAroundAssignment);
WriteToken (Roles.Assign);
Space (policy.SpaceAroundAssignment);
variableInitializer.Initializer.AcceptVisitor (this);
}
EndNode (variableInitializer);
}
public void VisitCompilationUnit (CompilationUnit compilationUnit)
{
// don't do node tracking as we visit all children directly
foreach (AstNode node in compilationUnit.Children)
node.AcceptVisitor (this);
}
public void VisitSimpleType (SimpleType simpleType)
{
StartNode (simpleType);
WriteIdentifier (simpleType.Identifier);
WriteTypeArguments (simpleType.TypeArguments);
EndNode (simpleType);
}
public void VisitMemberType (MemberType memberType)
{
StartNode (memberType);
memberType.Target.AcceptVisitor (this);
if (memberType.IsDoubleColon)
WriteToken (Roles.DoubleColon);
else
WriteToken (Roles.Dot);
WriteIdentifier (memberType.MemberName);
WriteTypeArguments (memberType.TypeArguments);
EndNode (memberType);
}
public void VisitComposedType (ComposedType composedType)
{
StartNode (composedType);
composedType.BaseType.AcceptVisitor (this);
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);
EndNode (composedType);
}
public void VisitArraySpecifier (ArraySpecifier arraySpecifier)
{
StartNode (arraySpecifier);
WriteToken (Roles.LBracket);
foreach (var comma in arraySpecifier.GetChildrenByRole(Roles.Comma)) {
WriteSpecialsUpToNode (comma);
formatter.WriteToken (",");
lastWritten = LastWritten.Other;
}
WriteToken (Roles.RBracket);
EndNode (arraySpecifier);
}
public void VisitPrimitiveType (PrimitiveType primitiveType)
{
StartNode (primitiveType);
WriteKeyword (primitiveType.Keyword);
if (primitiveType.Keyword == "new") {
// new() constraint
LPar ();
RPar ();
}
EndNode (primitiveType);
}
public void VisitComment (Comment comment)
{
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;
}
public void VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective)
{
formatter.StartNode (preProcessorDirective);
formatter.WritePreProcessorDirective(preProcessorDirective.Type, preProcessorDirective.Argument);
formatter.EndNode (preProcessorDirective);
lastWritten = LastWritten.Whitespace;
}
public void VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration)
{
StartNode (typeParameterDeclaration);
WriteAttributes (typeParameterDeclaration.Attributes);
switch (typeParameterDeclaration.Variance) {
case VarianceModifier.Invariant:
break;
case VarianceModifier.Covariant:
WriteKeyword (TypeParameterDeclaration.OutVarianceKeywordRole);
break;
case VarianceModifier.Contravariant:
WriteKeyword (TypeParameterDeclaration.InVarianceKeywordRole);
break;
default:
throw new NotSupportedException ("Invalid value for VarianceModifier");
}
WriteIdentifier (typeParameterDeclaration.Name);
EndNode (typeParameterDeclaration);
}
public void VisitConstraint(Constraint constraint)
{
StartNode(constraint);
Space();
WriteKeyword(Roles.WhereKeyword);
WriteIdentifier(constraint.TypeParameter.Identifier);
Space();
WriteToken(Roles.Colon);
Space ();
WriteCommaSeparatedList (constraint.BaseTypes);
EndNode (constraint);
}
public void VisitCSharpTokenNode (CSharpTokenNode cSharpTokenNode)
{
CSharpModifierToken mod = cSharpTokenNode as CSharpModifierToken;
if (mod != null) {
StartNode (mod);
WriteKeyword (CSharpModifierToken.GetModifierName (mod.Modifier));
EndNode (mod);
} else {
throw new NotSupportedException ("Should never visit individual tokens");
}
}
public void VisitIdentifier (Identifier identifier)
{
StartNode (identifier);
WriteIdentifier (identifier.Name);
EndNode (identifier);
}
#endregion
#region Pattern Nodes
public void VisitPatternPlaceholder (AstNode placeholder, PatternMatching.Pattern pattern)
{
StartNode (placeholder);
VisitNodeInPattern(pattern);
EndNode (placeholder);
}
void VisitAnyNode (AnyNode anyNode)
{
if (!string.IsNullOrEmpty (anyNode.GroupName)) {
WriteIdentifier (anyNode.GroupName);
WriteToken (Roles.Colon);
}
}
void VisitBackreference (Backreference backreference)
{
WriteKeyword ("backreference");
LPar ();
WriteIdentifier (backreference.ReferencedGroupName);
RPar ();
}
void VisitIdentifierExpressionBackreference (IdentifierExpressionBackreference identifierExpressionBackreference)
{
WriteKeyword ("identifierBackreference");
LPar ();
WriteIdentifier (identifierExpressionBackreference.ReferencedGroupName);
RPar ();
}
void VisitChoice (Choice choice)
{
WriteKeyword ("choice");
Space ();
LPar ();
NewLine ();
formatter.Indent ();
foreach (INode alternative in choice) {
VisitNodeInPattern (alternative);
if (alternative != choice.Last ())
WriteToken (Roles.Comma);
NewLine ();
}
formatter.Unindent ();
RPar ();
}
void VisitNamedNode (NamedNode namedNode)
{
if (!string.IsNullOrEmpty (namedNode.GroupName)) {
WriteIdentifier (namedNode.GroupName);
WriteToken (Roles.Colon);
}
VisitNodeInPattern (namedNode.ChildNode);
}
void VisitRepeat (Repeat repeat)
{
WriteKeyword ("repeat");
LPar ();
if (repeat.MinCount != 0 || repeat.MaxCount != int.MaxValue) {
WriteIdentifier (repeat.MinCount.ToString ());
WriteToken (Roles.Comma);
WriteIdentifier (repeat.MaxCount.ToString ());
WriteToken (Roles.Comma);
}
VisitNodeInPattern (repeat.ChildNode);
RPar ();
}
void VisitOptionalNode (OptionalNode optionalNode)
{
WriteKeyword ("optional");
LPar ();
VisitNodeInPattern (optionalNode.ChildNode);
RPar ();
}
void VisitNodeInPattern (INode childNode)
{
if (childNode is AstNode) {
((AstNode)childNode).AcceptVisitor (this);
} else if (childNode is IdentifierExpressionBackreference) {
VisitIdentifierExpressionBackreference((IdentifierExpressionBackreference)childNode);
} else if (childNode is Choice) {
VisitChoice((Choice)childNode);
} else if (childNode is AnyNode) {
VisitAnyNode((AnyNode)childNode);
} else if (childNode is Backreference) {
VisitBackreference((Backreference)childNode);
} else if (childNode is NamedNode) {
VisitNamedNode((NamedNode)childNode);
} else if (childNode is OptionalNode) {
VisitOptionalNode((OptionalNode)childNode);
} else if (childNode is Repeat) {
VisitRepeat((Repeat)childNode);
} else {
WritePrimitiveValue(childNode);
}
}
#endregion
#region Documentation Reference
public void VisitDocumentationReference (DocumentationReference documentationReference)
{
StartNode(documentationReference);
if (!documentationReference.DeclaringType.IsNull) {
documentationReference.DeclaringType.AcceptVisitor (this);
if (documentationReference.EntityType != EntityType.TypeDefinition)
WriteToken(Roles.Dot);
}
switch (documentationReference.EntityType) {
case EntityType.TypeDefinition:
// we already printed the DeclaringType
break;
case EntityType.Indexer:
WriteKeyword(IndexerDeclaration.ThisKeywordRole);
break;
case EntityType.Operator:
var opType = documentationReference.OperatorType;
if (opType == OperatorType.Explicit) {
WriteKeyword (OperatorDeclaration.ExplicitRole);
} else if (opType == OperatorType.Implicit) {
WriteKeyword (OperatorDeclaration.ImplicitRole);
}
WriteKeyword (OperatorDeclaration.OperatorKeywordRole);
Space ();
if (opType == OperatorType.Explicit || opType == OperatorType.Implicit) {
documentationReference.ConversionOperatorReturnType.AcceptVisitor (this);
} else {
WriteToken (OperatorDeclaration.GetToken (opType), OperatorDeclaration.GetRole (opType));
}
break;
default:
WriteIdentifier(documentationReference.MemberName);
break;
}
WriteTypeArguments(documentationReference.TypeArguments);
if (documentationReference.HasParameterList) {
Space(policy.SpaceBeforeMethodDeclarationParentheses);
if (documentationReference.EntityType == EntityType.Indexer)
WriteCommaSeparatedListInBrackets(documentationReference.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
else
WriteCommaSeparatedListInParenthesis(documentationReference.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
}
EndNode(documentationReference);
}
#endregion
}
}