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.
2637 lines
83 KiB
2637 lines
83 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.NewLine || 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) {
|
|
NewLine();
|
|
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.ArrayInitializerWrapping == Wrapping.WrapAlways) {
|
|
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);
|
|
namedArgumentExpression.NameToken.AcceptVisitor(this);
|
|
WriteToken(Roles.Colon);
|
|
Space();
|
|
namedArgumentExpression.Expression.AcceptVisitor(this);
|
|
EndNode(namedArgumentExpression);
|
|
}
|
|
|
|
public void VisitNamedExpression(NamedExpression namedExpression)
|
|
{
|
|
StartNode(namedExpression);
|
|
namedExpression.NameToken.AcceptVisitor(this);
|
|
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);
|
|
}
|
|
|
|
public static string PrintPrimitiveValue(object val)
|
|
{
|
|
StringWriter writer = new StringWriter();
|
|
CSharpOutputVisitor visitor = new CSharpOutputVisitor(writer, new CSharpFormattingOptions());
|
|
visitor.WritePrimitiveValue(val);
|
|
return writer.ToString();
|
|
}
|
|
|
|
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;
|
|
}
|
|
if (f == 0 && 1 / f == double.NegativeInfinity) {
|
|
// negative zero is a special case
|
|
// (again, not a primitive expression, but it's better to handle
|
|
// the special case here than to do it in all code generators)
|
|
formatter.WriteToken("-");
|
|
}
|
|
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;
|
|
}
|
|
if (f == 0 && 1 / f == double.NegativeInfinity) {
|
|
// negative zero is a special case
|
|
// (again, not a primitive expression, but it's better to handle
|
|
// the special case here than to do it in all code generators)
|
|
formatter.WriteToken("-");
|
|
}
|
|
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();
|
|
queryContinuationClause.IdentifierToken.AcceptVisitor(this);
|
|
EndNode(queryContinuationClause);
|
|
}
|
|
|
|
public void VisitQueryFromClause(QueryFromClause queryFromClause)
|
|
{
|
|
StartNode(queryFromClause);
|
|
WriteKeyword(QueryFromClause.FromKeywordRole);
|
|
queryFromClause.Type.AcceptVisitor(this);
|
|
Space();
|
|
queryFromClause.IdentifierToken.AcceptVisitor(this);
|
|
Space();
|
|
WriteKeyword(QueryFromClause.InKeywordRole);
|
|
Space();
|
|
queryFromClause.Expression.AcceptVisitor(this);
|
|
EndNode(queryFromClause);
|
|
}
|
|
|
|
public void VisitQueryLetClause(QueryLetClause queryLetClause)
|
|
{
|
|
StartNode(queryLetClause);
|
|
WriteKeyword(QueryLetClause.LetKeywordRole);
|
|
Space();
|
|
queryLetClause.IdentifierToken.AcceptVisitor(this);
|
|
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();
|
|
delegateDeclaration.NameToken.AcceptVisitor(this);
|
|
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;
|
|
}
|
|
typeDeclaration.NameToken.AcceptVisitor(this);
|
|
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);
|
|
if (!(blockStatement.Parent is Expression))
|
|
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();
|
|
foreachStatement.VariableNameToken.AcceptVisitor(this);
|
|
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);
|
|
if (forStatement.Iterators.Any()) {
|
|
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;
|
|
}
|
|
bool isBlock = switchSection.Statements.Count == 1 && switchSection.Statements.Single() is BlockStatement;
|
|
if (policy.IndentCaseBody && !isBlock) {
|
|
formatter.Indent();
|
|
}
|
|
|
|
if (!isBlock)
|
|
NewLine();
|
|
|
|
foreach (var statement in switchSection.Statements) {
|
|
statement.AcceptVisitor(this);
|
|
}
|
|
|
|
if (policy.IndentCaseBody && !isBlock) {
|
|
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();
|
|
catchClause.VariableNameToken.AcceptVisitor(this);
|
|
}
|
|
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;
|
|
StartNode(constructorDeclaration.NameToken);
|
|
WriteIdentifier(type != null ? type.Name : constructorDeclaration.Name);
|
|
EndNode(constructorDeclaration.NameToken);
|
|
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;
|
|
StartNode(destructorDeclaration.NameToken);
|
|
WriteIdentifier(type != null ? type.Name : destructorDeclaration.Name);
|
|
EndNode(destructorDeclaration.NameToken);
|
|
Space(policy.SpaceBeforeConstructorDeclarationParentheses);
|
|
LPar();
|
|
RPar();
|
|
WriteMethodBody(destructorDeclaration.Body);
|
|
EndNode(destructorDeclaration);
|
|
}
|
|
|
|
public void VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration)
|
|
{
|
|
StartNode(enumMemberDeclaration);
|
|
WriteAttributes(enumMemberDeclaration.Attributes);
|
|
WriteModifiers(enumMemberDeclaration.ModifierTokens);
|
|
enumMemberDeclaration.NameToken.AcceptVisitor(this);
|
|
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);
|
|
customEventDeclaration.NameToken.AcceptVisitor(this);
|
|
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);
|
|
fixedVariableInitializer.NameToken.AcceptVisitor(this);
|
|
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);
|
|
Space();
|
|
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);
|
|
methodDeclaration.NameToken.AcceptVisitor(this);
|
|
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)) {
|
|
parameterDeclaration.NameToken.AcceptVisitor(this);
|
|
}
|
|
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);
|
|
propertyDeclaration.NameToken.AcceptVisitor(this);
|
|
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);
|
|
variableInitializer.NameToken.AcceptVisitor(this);
|
|
if (!variableInitializer.Initializer.IsNull) {
|
|
Space(policy.SpaceAroundAssignment);
|
|
WriteToken(Roles.Assign);
|
|
Space(policy.SpaceAroundAssignment);
|
|
variableInitializer.Initializer.AcceptVisitor(this);
|
|
}
|
|
EndNode(variableInitializer);
|
|
}
|
|
|
|
public void VisitSyntaxTree(SyntaxTree syntaxTree)
|
|
{
|
|
// don't do node tracking as we visit all children directly
|
|
foreach (AstNode node in syntaxTree.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 VisitNewLine(NewLineNode newLineNode)
|
|
{
|
|
formatter.StartNode(newLineNode);
|
|
formatter.NewLine();
|
|
formatter.EndNode(newLineNode);
|
|
}
|
|
|
|
public void VisitWhitespace(WhitespaceNode whitespaceNode)
|
|
{
|
|
// unused
|
|
}
|
|
|
|
public void VisitText(TextNode textNode)
|
|
{
|
|
// unused
|
|
}
|
|
|
|
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");
|
|
}
|
|
typeParameterDeclaration.NameToken.AcceptVisitor(this);
|
|
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
|
|
}
|
|
}
|