mirror of
https://github.com/icsharpcode/ILSpy.git
synced 2026-10-12 02:15:58 +00:00
2642 lines
78 KiB
C#
2642 lines
78 KiB
C#
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
using ICSharpCode.NRefactory.PatternMatching;
|
|
using ICSharpCode.NRefactory.VB.Ast;
|
|
|
|
namespace ICSharpCode.NRefactory.VB
|
|
{
|
|
/// <summary>
|
|
/// Description of OutputVisitor.
|
|
/// </summary>
|
|
public class OutputVisitor : IAstVisitor<object, object>
|
|
{
|
|
readonly IOutputFormatter formatter;
|
|
readonly VBFormattingOptions 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
|
|
}
|
|
|
|
public OutputVisitor(TextWriter textWriter, VBFormattingOptions formattingPolicy)
|
|
{
|
|
if (textWriter == null)
|
|
throw new ArgumentNullException("textWriter");
|
|
if (formattingPolicy == null)
|
|
throw new ArgumentNullException("formattingPolicy");
|
|
this.formatter = new TextWriterOutputFormatter(textWriter);
|
|
this.policy = formattingPolicy;
|
|
}
|
|
|
|
public OutputVisitor(IOutputFormatter formatter, VBFormattingOptions formattingPolicy)
|
|
{
|
|
if (formatter == null)
|
|
throw new ArgumentNullException("formatter");
|
|
if (formattingPolicy == null)
|
|
throw new ArgumentNullException("formattingPolicy");
|
|
this.formatter = formatter;
|
|
this.policy = formattingPolicy;
|
|
}
|
|
|
|
public object VisitCompilationUnit(CompilationUnit compilationUnit, object data)
|
|
{
|
|
// don't do node tracking as we visit all children directly
|
|
foreach (AstNode node in compilationUnit.Children)
|
|
node.AcceptVisitor(this, data);
|
|
return null;
|
|
}
|
|
|
|
public object VisitBlockStatement(BlockStatement blockStatement, object data)
|
|
{
|
|
// prepare new block
|
|
NewLine();
|
|
Indent();
|
|
|
|
StartNode(blockStatement);
|
|
foreach (var stmt in blockStatement) {
|
|
stmt.AcceptVisitor(this, data);
|
|
NewLine();
|
|
}
|
|
// finish block
|
|
Unindent();
|
|
return EndNode(blockStatement);
|
|
}
|
|
|
|
public object VisitPatternPlaceholder(AstNode placeholder, Pattern pattern, object data)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public object VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, object data)
|
|
{
|
|
StartNode(typeParameterDeclaration);
|
|
|
|
switch (typeParameterDeclaration.Variance) {
|
|
case ICSharpCode.NRefactory.TypeSystem.VarianceModifier.Invariant:
|
|
break;
|
|
case ICSharpCode.NRefactory.TypeSystem.VarianceModifier.Covariant:
|
|
WriteKeyword("Out");
|
|
break;
|
|
case ICSharpCode.NRefactory.TypeSystem.VarianceModifier.Contravariant:
|
|
WriteKeyword("In");
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for VarianceModifier");
|
|
}
|
|
|
|
WriteIdentifier(typeParameterDeclaration.Name);
|
|
if (typeParameterDeclaration.Constraints.Any()) {
|
|
WriteKeyword("As");
|
|
if (typeParameterDeclaration.Constraints.Count > 1)
|
|
WriteToken("{", TypeParameterDeclaration.Roles.LBrace);
|
|
WriteCommaSeparatedList(typeParameterDeclaration.Constraints);
|
|
if (typeParameterDeclaration.Constraints.Count > 1)
|
|
WriteToken("}", TypeParameterDeclaration.Roles.RBrace);
|
|
}
|
|
|
|
return EndNode(typeParameterDeclaration);
|
|
}
|
|
|
|
public object VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, object data)
|
|
{
|
|
StartNode(parameterDeclaration);
|
|
WriteAttributes(parameterDeclaration.Attributes);
|
|
WriteModifiers(parameterDeclaration.ModifierTokens);
|
|
WriteIdentifier(parameterDeclaration.Name.Name);
|
|
if (!parameterDeclaration.Type.IsNull) {
|
|
WriteKeyword("As");
|
|
parameterDeclaration.Type.AcceptVisitor(this, data);
|
|
}
|
|
if (!parameterDeclaration.OptionalValue.IsNull) {
|
|
WriteToken("=", ParameterDeclaration.Roles.Assign);
|
|
parameterDeclaration.OptionalValue.AcceptVisitor(this, data);
|
|
}
|
|
return EndNode(parameterDeclaration);
|
|
}
|
|
|
|
public object VisitVBTokenNode(VBTokenNode vBTokenNode, object data)
|
|
{
|
|
var mod = vBTokenNode as VBModifierToken;
|
|
if (mod != null) {
|
|
StartNode(vBTokenNode);
|
|
WriteKeyword(VBModifierToken.GetModifierName(mod.Modifier));
|
|
return EndNode(vBTokenNode);
|
|
} else {
|
|
throw new NotSupportedException("Should never visit individual tokens");
|
|
}
|
|
}
|
|
|
|
public object VisitAliasImportsClause(AliasImportsClause aliasImportsClause, object data)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public object VisitAttribute(ICSharpCode.NRefactory.VB.Ast.Attribute attribute, object data)
|
|
{
|
|
StartNode(attribute);
|
|
|
|
if (attribute.Target != AttributeTarget.None) {
|
|
switch (attribute.Target) {
|
|
case AttributeTarget.None:
|
|
break;
|
|
case AttributeTarget.Assembly:
|
|
WriteKeyword("Assembly");
|
|
break;
|
|
case AttributeTarget.Module:
|
|
WriteKeyword("Module");
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for AttributeTarget");
|
|
}
|
|
WriteToken(":", Ast.Attribute.Roles.Colon);
|
|
Space();
|
|
}
|
|
attribute.Type.AcceptVisitor(this, data);
|
|
WriteCommaSeparatedListInParenthesis(attribute.Arguments, false);
|
|
|
|
return EndNode(attribute);
|
|
}
|
|
|
|
public object VisitAttributeBlock(AttributeBlock attributeBlock, object data)
|
|
{
|
|
StartNode(attributeBlock);
|
|
|
|
WriteToken("<", AttributeBlock.Roles.LChevron);
|
|
WriteCommaSeparatedList(attributeBlock.Attributes);
|
|
WriteToken(">", AttributeBlock.Roles.RChevron);
|
|
if (attributeBlock.Parent is ParameterDeclaration)
|
|
Space();
|
|
else
|
|
NewLine();
|
|
|
|
return EndNode(attributeBlock);
|
|
}
|
|
|
|
public object VisitImportsStatement(ImportsStatement importsStatement, object data)
|
|
{
|
|
StartNode(importsStatement);
|
|
|
|
WriteKeyword("Imports", AstNode.Roles.Keyword);
|
|
Space();
|
|
WriteCommaSeparatedList(importsStatement.ImportsClauses);
|
|
NewLine();
|
|
|
|
return EndNode(importsStatement);
|
|
}
|
|
|
|
public object VisitMemberImportsClause(MemberImportsClause memberImportsClause, object data)
|
|
{
|
|
StartNode(memberImportsClause);
|
|
memberImportsClause.Member.AcceptVisitor(this, data);
|
|
return EndNode(memberImportsClause);
|
|
}
|
|
|
|
public object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data)
|
|
{
|
|
StartNode(namespaceDeclaration);
|
|
NewLine();
|
|
WriteKeyword("Namespace");
|
|
bool isFirst = true;
|
|
foreach (Identifier node in namespaceDeclaration.Identifiers) {
|
|
if (isFirst) {
|
|
isFirst = false;
|
|
} else {
|
|
WriteToken(".", NamespaceDeclaration.Roles.Dot);
|
|
}
|
|
node.AcceptVisitor(this, null);
|
|
}
|
|
NewLine();
|
|
WriteMembers(namespaceDeclaration.Members);
|
|
WriteKeyword("End");
|
|
WriteKeyword("Namespace");
|
|
NewLine();
|
|
return EndNode(namespaceDeclaration);
|
|
}
|
|
|
|
public object VisitOptionStatement(OptionStatement optionStatement, object data)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
|
|
{
|
|
StartNode(typeDeclaration);
|
|
WriteAttributes(typeDeclaration.Attributes);
|
|
WriteModifiers(typeDeclaration.ModifierTokens);
|
|
WriteClassTypeKeyword(typeDeclaration);
|
|
WriteIdentifier(typeDeclaration.Name.Name);
|
|
MarkFoldStart();
|
|
NewLine();
|
|
|
|
if (!typeDeclaration.InheritsType.IsNull) {
|
|
Indent();
|
|
WriteKeyword("Inherits");
|
|
typeDeclaration.InheritsType.AcceptVisitor(this, data);
|
|
Unindent();
|
|
NewLine();
|
|
}
|
|
if (typeDeclaration.ImplementsTypes.Any()) {
|
|
Indent();
|
|
WriteImplementsClause(typeDeclaration.ImplementsTypes);
|
|
Unindent();
|
|
NewLine();
|
|
}
|
|
|
|
if (!typeDeclaration.InheritsType.IsNull || typeDeclaration.ImplementsTypes.Any())
|
|
NewLine();
|
|
|
|
WriteMembers(typeDeclaration.Members);
|
|
|
|
WriteKeyword("End");
|
|
WriteClassTypeKeyword(typeDeclaration);
|
|
MarkFoldEnd();
|
|
NewLine();
|
|
return EndNode(typeDeclaration);
|
|
}
|
|
|
|
void WriteClassTypeKeyword(TypeDeclaration typeDeclaration)
|
|
{
|
|
switch (typeDeclaration.ClassType) {
|
|
case ClassType.Class:
|
|
WriteKeyword("Class");
|
|
break;
|
|
case ClassType.Interface:
|
|
WriteKeyword("Interface");
|
|
break;
|
|
case ClassType.Struct:
|
|
WriteKeyword("Structure");
|
|
break;
|
|
case ClassType.Module:
|
|
WriteKeyword("Module");
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for ClassType");
|
|
}
|
|
}
|
|
|
|
public object VisitXmlNamespaceImportsClause(XmlNamespaceImportsClause xmlNamespaceImportsClause, object data)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public object VisitEnumDeclaration(EnumDeclaration enumDeclaration, object data)
|
|
{
|
|
StartNode(enumDeclaration);
|
|
|
|
WriteAttributes(enumDeclaration.Attributes);
|
|
WriteModifiers(enumDeclaration.ModifierTokens);
|
|
WriteKeyword("Enum");
|
|
WriteIdentifier(enumDeclaration.Name.Name);
|
|
if (!enumDeclaration.UnderlyingType.IsNull) {
|
|
Space();
|
|
WriteKeyword("As");
|
|
enumDeclaration.UnderlyingType.AcceptVisitor(this, data);
|
|
}
|
|
MarkFoldStart();
|
|
NewLine();
|
|
|
|
Indent();
|
|
foreach (var member in enumDeclaration.Members) {
|
|
member.AcceptVisitor(this, null);
|
|
}
|
|
Unindent();
|
|
|
|
WriteKeyword("End");
|
|
WriteKeyword("Enum");
|
|
MarkFoldEnd();
|
|
NewLine();
|
|
|
|
return EndNode(enumDeclaration);
|
|
}
|
|
|
|
public object VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data)
|
|
{
|
|
StartNode(enumMemberDeclaration);
|
|
|
|
WriteAttributes(enumMemberDeclaration.Attributes);
|
|
WriteIdentifier(enumMemberDeclaration.Name.Name);
|
|
|
|
if (!enumMemberDeclaration.Value.IsNull) {
|
|
Space();
|
|
WriteToken("=", EnumMemberDeclaration.Roles.Assign);
|
|
Space();
|
|
enumMemberDeclaration.Value.AcceptVisitor(this, data);
|
|
}
|
|
NewLine();
|
|
|
|
return EndNode(enumMemberDeclaration);
|
|
}
|
|
|
|
public object VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data)
|
|
{
|
|
StartNode(delegateDeclaration);
|
|
|
|
WriteAttributes(delegateDeclaration.Attributes);
|
|
WriteModifiers(delegateDeclaration.ModifierTokens);
|
|
WriteKeyword("Delegate");
|
|
if (delegateDeclaration.IsSub)
|
|
WriteKeyword("Sub");
|
|
else
|
|
WriteKeyword("Function");
|
|
WriteIdentifier(delegateDeclaration.Name.Name);
|
|
WriteTypeParameters(delegateDeclaration.TypeParameters);
|
|
WriteCommaSeparatedListInParenthesis(delegateDeclaration.Parameters, false);
|
|
if (!delegateDeclaration.IsSub) {
|
|
Space();
|
|
WriteKeyword("As");
|
|
WriteAttributes(delegateDeclaration.ReturnTypeAttributes);
|
|
delegateDeclaration.ReturnType.AcceptVisitor(this, data);
|
|
}
|
|
NewLine();
|
|
|
|
return EndNode(delegateDeclaration);
|
|
}
|
|
|
|
public object VisitIdentifier(Identifier identifier, object data)
|
|
{
|
|
StartNode(identifier);
|
|
WriteIdentifier(identifier.Name);
|
|
WriteTypeCharacter(identifier.TypeCharacter);
|
|
return EndNode(identifier);
|
|
}
|
|
|
|
public object VisitXmlIdentifier(XmlIdentifier xmlIdentifier, object data)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public object VisitXmlLiteralString(XmlLiteralString xmlLiteralString, object data)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public object VisitSimpleNameExpression(SimpleNameExpression simpleNameExpression, object data)
|
|
{
|
|
StartNode(simpleNameExpression);
|
|
|
|
simpleNameExpression.Identifier.AcceptVisitor(this, data);
|
|
WriteTypeArguments(simpleNameExpression.TypeArguments);
|
|
|
|
return EndNode(simpleNameExpression);
|
|
}
|
|
|
|
public object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data)
|
|
{
|
|
StartNode(primitiveExpression);
|
|
|
|
if (lastWritten == LastWritten.KeywordOrIdentifier)
|
|
Space();
|
|
WritePrimitiveValue(primitiveExpression.Value);
|
|
|
|
return EndNode(primitiveExpression);
|
|
}
|
|
|
|
public object VisitInstanceExpression(InstanceExpression instanceExpression, object data)
|
|
{
|
|
StartNode(instanceExpression);
|
|
|
|
switch (instanceExpression.Type) {
|
|
case InstanceExpressionType.Me:
|
|
WriteKeyword("Me");
|
|
break;
|
|
case InstanceExpressionType.MyBase:
|
|
WriteKeyword("MyBase");
|
|
break;
|
|
case InstanceExpressionType.MyClass:
|
|
WriteKeyword("MyClass");
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for InstanceExpressionType");
|
|
}
|
|
|
|
return EndNode(instanceExpression);
|
|
}
|
|
|
|
public object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
|
|
{
|
|
StartNode(parenthesizedExpression);
|
|
|
|
LPar();
|
|
parenthesizedExpression.Expression.AcceptVisitor(this, data);
|
|
RPar();
|
|
|
|
return EndNode(parenthesizedExpression);
|
|
}
|
|
|
|
public object VisitGetTypeExpression(GetTypeExpression getTypeExpression, object data)
|
|
{
|
|
StartNode(getTypeExpression);
|
|
|
|
WriteKeyword("GetType");
|
|
LPar();
|
|
getTypeExpression.Type.AcceptVisitor(this, data);
|
|
RPar();
|
|
|
|
return EndNode(getTypeExpression);
|
|
}
|
|
|
|
public object VisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, object data)
|
|
{
|
|
StartNode(typeOfIsExpression);
|
|
|
|
WriteKeyword("TypeOf");
|
|
typeOfIsExpression.TypeOfExpression.AcceptVisitor(this, data);
|
|
WriteKeyword("Is");
|
|
typeOfIsExpression.Type.AcceptVisitor(this, data);
|
|
|
|
return EndNode(typeOfIsExpression);
|
|
}
|
|
|
|
public object VisitGetXmlNamespaceExpression(GetXmlNamespaceExpression getXmlNamespaceExpression, object data)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public object VisitMemberAccessExpression(MemberAccessExpression memberAccessExpression, object data)
|
|
{
|
|
StartNode(memberAccessExpression);
|
|
|
|
memberAccessExpression.Target.AcceptVisitor(this, data);
|
|
WriteToken(".", MemberAccessExpression.Roles.Dot);
|
|
memberAccessExpression.MemberName.AcceptVisitor(this, data);
|
|
WriteTypeArguments(memberAccessExpression.TypeArguments);
|
|
|
|
return EndNode(memberAccessExpression);
|
|
}
|
|
|
|
public object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data)
|
|
{
|
|
StartNode(typeReferenceExpression);
|
|
|
|
typeReferenceExpression.Type.AcceptVisitor(this, data);
|
|
|
|
return EndNode(typeReferenceExpression);
|
|
}
|
|
|
|
public object VisitEventMemberSpecifier(EventMemberSpecifier eventMemberSpecifier, object data)
|
|
{
|
|
StartNode(eventMemberSpecifier);
|
|
|
|
eventMemberSpecifier.Target.AcceptVisitor(this, data);
|
|
WriteToken(".", EventMemberSpecifier.Roles.Dot);
|
|
eventMemberSpecifier.Member.AcceptVisitor(this, data);
|
|
|
|
return EndNode(eventMemberSpecifier);
|
|
}
|
|
|
|
public object VisitInterfaceMemberSpecifier(InterfaceMemberSpecifier interfaceMemberSpecifier, object data)
|
|
{
|
|
StartNode(interfaceMemberSpecifier);
|
|
|
|
interfaceMemberSpecifier.Target.AcceptVisitor(this, data);
|
|
WriteToken(".", EventMemberSpecifier.Roles.Dot);
|
|
interfaceMemberSpecifier.Member.AcceptVisitor(this, data);
|
|
|
|
return EndNode(interfaceMemberSpecifier);
|
|
}
|
|
|
|
#region TypeMembers
|
|
public object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
|
|
{
|
|
StartNode(constructorDeclaration);
|
|
|
|
WriteAttributes(constructorDeclaration.Attributes);
|
|
WriteModifiers(constructorDeclaration.ModifierTokens);
|
|
WriteKeyword("Sub");
|
|
WriteKeyword("New");
|
|
WriteCommaSeparatedListInParenthesis(constructorDeclaration.Parameters, false);
|
|
MarkFoldStart();
|
|
WriteBlock(constructorDeclaration.Body);
|
|
WriteKeyword("End");
|
|
WriteKeyword("Sub");
|
|
MarkFoldEnd();
|
|
NewLine();
|
|
|
|
return EndNode(constructorDeclaration);
|
|
}
|
|
|
|
public object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
|
|
{
|
|
StartNode(methodDeclaration);
|
|
|
|
WriteAttributes(methodDeclaration.Attributes);
|
|
WriteModifiers(methodDeclaration.ModifierTokens);
|
|
if (methodDeclaration.IsSub)
|
|
WriteKeyword("Sub");
|
|
else
|
|
WriteKeyword("Function");
|
|
methodDeclaration.Name.AcceptVisitor(this, data);
|
|
WriteTypeParameters(methodDeclaration.TypeParameters);
|
|
WriteCommaSeparatedListInParenthesis(methodDeclaration.Parameters, false);
|
|
if (!methodDeclaration.IsSub && !methodDeclaration.ReturnType.IsNull) {
|
|
Space();
|
|
WriteKeyword("As");
|
|
WriteAttributes(methodDeclaration.ReturnTypeAttributes);
|
|
methodDeclaration.ReturnType.AcceptVisitor(this, data);
|
|
}
|
|
WriteHandlesClause(methodDeclaration.HandlesClause);
|
|
WriteImplementsClause(methodDeclaration.ImplementsClause);
|
|
if (!methodDeclaration.Body.IsNull) {
|
|
MarkFoldStart();
|
|
WriteBlock(methodDeclaration.Body);
|
|
WriteKeyword("End");
|
|
if (methodDeclaration.IsSub)
|
|
WriteKeyword("Sub");
|
|
else
|
|
WriteKeyword("Function");
|
|
MarkFoldEnd();
|
|
}
|
|
NewLine();
|
|
|
|
return EndNode(methodDeclaration);
|
|
}
|
|
|
|
public object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data)
|
|
{
|
|
StartNode(fieldDeclaration);
|
|
|
|
WriteAttributes(fieldDeclaration.Attributes);
|
|
WriteModifiers(fieldDeclaration.ModifierTokens);
|
|
WriteCommaSeparatedList(fieldDeclaration.Variables);
|
|
NewLine();
|
|
|
|
return EndNode(fieldDeclaration);
|
|
}
|
|
|
|
public object VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data)
|
|
{
|
|
StartNode(propertyDeclaration);
|
|
|
|
WriteAttributes(propertyDeclaration.Attributes);
|
|
WriteModifiers(propertyDeclaration.ModifierTokens);
|
|
WriteKeyword("Property");
|
|
WriteIdentifier(propertyDeclaration.Name.Name);
|
|
WriteCommaSeparatedListInParenthesis(propertyDeclaration.Parameters, false);
|
|
if (!propertyDeclaration.ReturnType.IsNull) {
|
|
Space();
|
|
WriteKeyword("As");
|
|
WriteAttributes(propertyDeclaration.ReturnTypeAttributes);
|
|
propertyDeclaration.ReturnType.AcceptVisitor(this, data);
|
|
}
|
|
|
|
bool needsBody = !propertyDeclaration.Getter.Body.IsNull || !propertyDeclaration.Setter.Body.IsNull;
|
|
|
|
if (needsBody) {
|
|
MarkFoldStart();
|
|
NewLine();
|
|
Indent();
|
|
|
|
if (!propertyDeclaration.Getter.Body.IsNull) {
|
|
propertyDeclaration.Getter.AcceptVisitor(this, data);
|
|
}
|
|
|
|
if (!propertyDeclaration.Setter.Body.IsNull) {
|
|
propertyDeclaration.Setter.AcceptVisitor(this, data);
|
|
}
|
|
Unindent();
|
|
|
|
WriteKeyword("End");
|
|
WriteKeyword("Property");
|
|
MarkFoldEnd();
|
|
}
|
|
NewLine();
|
|
|
|
return EndNode(propertyDeclaration);
|
|
}
|
|
#endregion
|
|
|
|
#region TypeName
|
|
public object VisitPrimitiveType(PrimitiveType primitiveType, object data)
|
|
{
|
|
StartNode(primitiveType);
|
|
|
|
WriteKeyword(primitiveType.Keyword);
|
|
|
|
return EndNode(primitiveType);
|
|
}
|
|
|
|
public object VisitQualifiedType(QualifiedType qualifiedType, object data)
|
|
{
|
|
StartNode(qualifiedType);
|
|
|
|
qualifiedType.Target.AcceptVisitor(this, data);
|
|
WriteToken(".", AstNode.Roles.Dot);
|
|
WriteIdentifier(qualifiedType.Name);
|
|
WriteTypeArguments(qualifiedType.TypeArguments);
|
|
|
|
return EndNode(qualifiedType);
|
|
}
|
|
|
|
public object VisitComposedType(ComposedType composedType, object data)
|
|
{
|
|
StartNode(composedType);
|
|
|
|
composedType.BaseType.AcceptVisitor(this, data);
|
|
if (composedType.HasNullableSpecifier)
|
|
WriteToken("?", ComposedType.Roles.QuestionMark);
|
|
WriteArraySpecifiers(composedType.ArraySpecifiers);
|
|
|
|
return EndNode(composedType);
|
|
}
|
|
|
|
public object VisitArraySpecifier(ArraySpecifier arraySpecifier, object data)
|
|
{
|
|
StartNode(arraySpecifier);
|
|
|
|
LPar();
|
|
for (int i = 0; i < arraySpecifier.Dimensions - 1; i++) {
|
|
WriteToken(",", ArraySpecifier.Roles.Comma);
|
|
}
|
|
RPar();
|
|
|
|
return EndNode(arraySpecifier);
|
|
}
|
|
|
|
public object VisitSimpleType(SimpleType simpleType, object data)
|
|
{
|
|
StartNode(simpleType);
|
|
|
|
WriteIdentifier(simpleType.Identifier);
|
|
WriteTypeArguments(simpleType.TypeArguments);
|
|
|
|
return EndNode(simpleType);
|
|
}
|
|
#endregion
|
|
|
|
#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());
|
|
if (positionStack.Count > 0)
|
|
WriteSpecialsUpToNode(node);
|
|
containerStack.Push(node);
|
|
positionStack.Push(node.FirstChild);
|
|
formatter.StartNode(node);
|
|
}
|
|
|
|
object EndNode(AstNode node)
|
|
{
|
|
Debug.Assert(node == containerStack.Peek());
|
|
AstNode pos = positionStack.Pop();
|
|
Debug.Assert(pos == null || pos.Parent == node);
|
|
WriteSpecials(pos, null);
|
|
containerStack.Pop();
|
|
formatter.EndNode(node);
|
|
return null;
|
|
}
|
|
#endregion
|
|
|
|
#region WriteSpecials
|
|
/// <summary>
|
|
/// Writes all specials from start to end (exclusive). Does not touch the positionStack.
|
|
/// </summary>
|
|
void WriteSpecials(AstNode start, AstNode end)
|
|
{
|
|
for (AstNode pos = start; pos != end; pos = pos.NextSibling) {
|
|
if (pos.Role == AstNode.Roles.Comment) {
|
|
pos.AcceptVisitor(this, null);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes all specials between the current position (in the positionStack) and the next
|
|
/// node with the specified role. Advances the current position.
|
|
/// </summary>
|
|
void WriteSpecialsUpToRole(Role role)
|
|
{
|
|
for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) {
|
|
if (pos.Role == role) {
|
|
WriteSpecials(positionStack.Pop(), pos);
|
|
positionStack.Push(pos);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes all specials between the current position (in the positionStack) and the specified node.
|
|
/// Advances the current position.
|
|
/// </summary>
|
|
void WriteSpecialsUpToNode(AstNode node)
|
|
{
|
|
for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) {
|
|
if (pos == node) {
|
|
WriteSpecials(positionStack.Pop(), pos);
|
|
positionStack.Push(pos);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void WriteSpecialsUpToRole(Role role, AstNode nextNode)
|
|
{
|
|
// Look for the role between the current position and the nextNode.
|
|
for (AstNode pos = positionStack.Peek(); pos != null && pos != nextNode; pos = pos.NextSibling) {
|
|
if (pos.Role == AstNode.Roles.Comma) {
|
|
WriteSpecials(positionStack.Pop(), pos);
|
|
positionStack.Push(pos);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Comma
|
|
/// <summary>
|
|
/// Writes a comma.
|
|
/// </summary>
|
|
/// <param name="nextNode">The next node after the comma.</param>
|
|
/// <param name="noSpacesAfterComma">When set prevents printing a space after comma.</param>
|
|
void Comma(AstNode nextNode, bool noSpaceAfterComma = false)
|
|
{
|
|
WriteSpecialsUpToRole(AstNode.Roles.Comma, nextNode);
|
|
formatter.WriteToken(",");
|
|
lastWritten = LastWritten.Other;
|
|
Space(!noSpaceAfterComma); // TODO: Comma policy has changed.
|
|
}
|
|
|
|
void WriteCommaSeparatedList(IEnumerable<AstNode> list)
|
|
{
|
|
bool isFirst = true;
|
|
foreach (AstNode node in list) {
|
|
if (isFirst) {
|
|
isFirst = false;
|
|
} else {
|
|
Comma(node);
|
|
}
|
|
node.AcceptVisitor(this, null);
|
|
}
|
|
}
|
|
|
|
void WriteCommaSeparatedListInParenthesis(IEnumerable<AstNode> list, bool spaceWithin)
|
|
{
|
|
LPar();
|
|
if (list.Any()) {
|
|
Space(spaceWithin);
|
|
WriteCommaSeparatedList(list);
|
|
Space(spaceWithin);
|
|
}
|
|
RPar();
|
|
}
|
|
|
|
#if DOTNET35
|
|
void WriteCommaSeparatedList(IEnumerable<VariableInitializer> list)
|
|
{
|
|
WriteCommaSeparatedList(list);
|
|
}
|
|
|
|
void WriteCommaSeparatedList(IEnumerable<AstType> list)
|
|
{
|
|
WriteCommaSeparatedList(list);
|
|
}
|
|
|
|
void WriteCommaSeparatedListInParenthesis(IEnumerable<Expression> list, bool spaceWithin)
|
|
{
|
|
WriteCommaSeparatedListInParenthesis(list.SafeCast<Expression, AstNode>(), spaceWithin);
|
|
}
|
|
|
|
void WriteCommaSeparatedListInParenthesis(IEnumerable<ParameterDeclaration> list, bool spaceWithin)
|
|
{
|
|
WriteCommaSeparatedListInParenthesis(list.SafeCast<ParameterDeclaration, AstNode>(), spaceWithin);
|
|
}
|
|
|
|
#endif
|
|
|
|
void WriteCommaSeparatedListInBrackets(IEnumerable<ParameterDeclaration> list, bool spaceWithin)
|
|
{
|
|
WriteToken("[", AstNode.Roles.LBracket);
|
|
if (list.Any()) {
|
|
Space(spaceWithin);
|
|
WriteCommaSeparatedList(list);
|
|
Space(spaceWithin);
|
|
}
|
|
WriteToken("]", AstNode.Roles.RBracket);
|
|
}
|
|
#endregion
|
|
|
|
#region Write tokens
|
|
/// <summary>
|
|
/// Writes a keyword, and all specials up to
|
|
/// </summary>
|
|
void WriteKeyword(string keyword, Role<VBTokenNode> tokenRole = null)
|
|
{
|
|
WriteSpecialsUpToRole(tokenRole ?? AstNode.Roles.Keyword);
|
|
if (lastWritten == LastWritten.KeywordOrIdentifier)
|
|
formatter.Space();
|
|
formatter.WriteKeyword(keyword);
|
|
lastWritten = LastWritten.KeywordOrIdentifier;
|
|
}
|
|
|
|
void WriteIdentifier(string identifier, Role<Identifier> identifierRole = null)
|
|
{
|
|
WriteSpecialsUpToRole(identifierRole ?? AstNode.Roles.Identifier);
|
|
|
|
if (lastWritten == LastWritten.KeywordOrIdentifier)
|
|
Space(); // this space is not strictly required, so we call Space()
|
|
|
|
if (IsKeyword(identifier, containerStack.Peek()))
|
|
formatter.WriteToken("[");
|
|
|
|
formatter.WriteIdentifier(identifier);
|
|
if (IsKeyword(identifier, containerStack.Peek()))
|
|
formatter.WriteToken("]");
|
|
|
|
lastWritten = LastWritten.KeywordOrIdentifier;
|
|
}
|
|
|
|
void WriteToken(string token, Role<VBTokenNode> 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 WriteTypeCharacter(TypeCode typeCharacter)
|
|
{
|
|
switch (typeCharacter) {
|
|
case TypeCode.Empty:
|
|
case TypeCode.Object:
|
|
case TypeCode.DBNull:
|
|
case TypeCode.Boolean:
|
|
case TypeCode.Char:
|
|
|
|
break;
|
|
case TypeCode.SByte:
|
|
|
|
break;
|
|
case TypeCode.Byte:
|
|
|
|
break;
|
|
case TypeCode.Int16:
|
|
|
|
break;
|
|
case TypeCode.UInt16:
|
|
|
|
break;
|
|
case TypeCode.Int32:
|
|
WriteToken("%", null);
|
|
break;
|
|
case TypeCode.UInt32:
|
|
|
|
break;
|
|
case TypeCode.Int64:
|
|
WriteToken("&", null);
|
|
break;
|
|
case TypeCode.UInt64:
|
|
|
|
break;
|
|
case TypeCode.Single:
|
|
WriteToken("!", null);
|
|
break;
|
|
case TypeCode.Double:
|
|
WriteToken("#", null);
|
|
break;
|
|
case TypeCode.Decimal:
|
|
WriteToken("@", null);
|
|
break;
|
|
case TypeCode.DateTime:
|
|
|
|
break;
|
|
case TypeCode.String:
|
|
WriteToken("$", null);
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for TypeCode");
|
|
}
|
|
}
|
|
|
|
void LPar()
|
|
{
|
|
WriteToken("(", AstNode.Roles.LPar);
|
|
}
|
|
|
|
void RPar()
|
|
{
|
|
WriteToken(")", AstNode.Roles.LPar);
|
|
}
|
|
|
|
/// <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 Indent()
|
|
{
|
|
formatter.Indent();
|
|
}
|
|
|
|
void Unindent()
|
|
{
|
|
formatter.Unindent();
|
|
}
|
|
|
|
void MarkFoldStart()
|
|
{
|
|
formatter.MarkFoldStart();
|
|
}
|
|
|
|
void MarkFoldEnd()
|
|
{
|
|
formatter.MarkFoldEnd();
|
|
}
|
|
#endregion
|
|
|
|
#region IsKeyword Test
|
|
static readonly HashSet<string> unconditionalKeywords = new HashSet<string>(StringComparer.OrdinalIgnoreCase) {
|
|
"AddHandler", "AddressOf", "Alias", "And", "AndAlso", "As", "Boolean", "ByRef", "Byte",
|
|
"ByVal", "Call", "Case", "Catch", "CBool", "CByte", "CChar", "CInt", "Class", "CLng",
|
|
"CObj", "Const", "Continue", "CSByte", "CShort", "CSng", "CStr", "CType", "CUInt",
|
|
"CULng", "CUShort", "Date", "Decimal", "Declare", "Default", "Delegate", "Dim",
|
|
"DirectCast", "Do", "Double", "Each", "Else", "ElseIf", "End", "EndIf", "Enum", "Erase",
|
|
"Error", "Event", "Exit", "False", "Finally", "For", "Friend", "Function", "Get",
|
|
"GetType", "GetXmlNamespace", "Global", "GoSub", "GoTo", "Handles", "If", "Implements",
|
|
"Imports", "In", "Inherits", "Integer", "Interface", "Is", "IsNot", "Let", "Lib", "Like",
|
|
"Long", "Loop", "Me", "Mod", "Module", "MustInherit", "MustOverride", "MyBase", "MyClass",
|
|
"Namespace", "Narrowing", "Next", "Not", "Nothing", "NotInheritable", "NotOverridable",
|
|
"Object", "Of", "On", "Operator", "Option", "Optional", "Or", "OrElse", "Overloads",
|
|
"Overridable", "Overrides", "ParamArray", "Partial", "Private", "Property", "Protected",
|
|
"Public", "RaiseEvent", "ReadOnly", "ReDim", "REM", "RemoveHandler", "Resume", "Return",
|
|
"SByte", "Select", "Set", "Shadows", "Shared", "Short", "Single", "Static", "Step", "Stop",
|
|
"String", "Structure", "Sub", "SyncLock", "Then", "Throw", "To", "True", "Try", "TryCast",
|
|
"TypeOf", "UInteger", "ULong", "UShort", "Using", "Variant", "Wend", "When", "While",
|
|
"Widening", "With", "WithEvents", "WriteOnly", "Xor"
|
|
};
|
|
|
|
static readonly HashSet<string> queryKeywords = new HashSet<string> {
|
|
|
|
};
|
|
|
|
/// <summary>
|
|
/// Determines whether the specified identifier is a keyword in the given context.
|
|
/// </summary>
|
|
public static bool IsKeyword(string identifier, AstNode context)
|
|
{
|
|
if (identifier == "New") {
|
|
if (context.PrevSibling is InstanceExpression)
|
|
return false;
|
|
return true;
|
|
}
|
|
if (unconditionalKeywords.Contains(identifier))
|
|
return true;
|
|
// if (context.Ancestors.Any(a => a is QueryExpression)) {
|
|
// if (queryKeywords.Contains(identifier))
|
|
// return true;
|
|
// }
|
|
return false;
|
|
}
|
|
#endregion
|
|
|
|
#region Write constructs
|
|
void WriteTypeArguments(IEnumerable<AstType> typeArguments)
|
|
{
|
|
if (typeArguments.Any()) {
|
|
LPar();
|
|
WriteKeyword("Of");
|
|
WriteCommaSeparatedList(typeArguments);
|
|
RPar();
|
|
}
|
|
}
|
|
|
|
void WriteTypeParameters(IEnumerable<TypeParameterDeclaration> typeParameters)
|
|
{
|
|
if (typeParameters.Any()) {
|
|
LPar();
|
|
WriteKeyword("Of");
|
|
WriteCommaSeparatedList(typeParameters);
|
|
RPar();
|
|
}
|
|
}
|
|
|
|
void WriteModifiers(IEnumerable<VBModifierToken> modifierTokens)
|
|
{
|
|
foreach (VBModifierToken modifier in modifierTokens) {
|
|
modifier.AcceptVisitor(this, null);
|
|
}
|
|
}
|
|
|
|
void WriteArraySpecifiers(IEnumerable<ArraySpecifier> arraySpecifiers)
|
|
{
|
|
foreach (ArraySpecifier specifier in arraySpecifiers) {
|
|
specifier.AcceptVisitor(this, null);
|
|
}
|
|
}
|
|
|
|
void WriteQualifiedIdentifier(IEnumerable<Identifier> identifiers)
|
|
{
|
|
bool first = true;
|
|
foreach (Identifier ident in identifiers) {
|
|
if (first) {
|
|
first = false;
|
|
if (lastWritten == LastWritten.KeywordOrIdentifier)
|
|
formatter.Space();
|
|
} else {
|
|
WriteSpecialsUpToRole(AstNode.Roles.Dot, ident);
|
|
formatter.WriteToken(".");
|
|
lastWritten = LastWritten.Other;
|
|
}
|
|
WriteSpecialsUpToNode(ident);
|
|
formatter.WriteIdentifier(ident.Name);
|
|
lastWritten = LastWritten.KeywordOrIdentifier;
|
|
}
|
|
}
|
|
|
|
void WriteEmbeddedStatement(Statement embeddedStatement)
|
|
{
|
|
if (embeddedStatement.IsNull)
|
|
return;
|
|
BlockStatement block = embeddedStatement as BlockStatement;
|
|
if (block != null)
|
|
VisitBlockStatement(block, null);
|
|
else
|
|
embeddedStatement.AcceptVisitor(this, null);
|
|
}
|
|
|
|
void WriteBlock(BlockStatement body)
|
|
{
|
|
if (body.IsNull) {
|
|
NewLine();
|
|
Indent();
|
|
NewLine();
|
|
Unindent();
|
|
} else
|
|
VisitBlockStatement(body, null);
|
|
}
|
|
|
|
void WriteMembers(IEnumerable<AstNode> members)
|
|
{
|
|
Indent();
|
|
bool isFirst = true;
|
|
foreach (var member in members) {
|
|
if (isFirst) {
|
|
isFirst = false;
|
|
} else {
|
|
NewLine();
|
|
}
|
|
member.AcceptVisitor(this, null);
|
|
}
|
|
Unindent();
|
|
}
|
|
|
|
void WriteAttributes(IEnumerable<AttributeBlock> attributes)
|
|
{
|
|
foreach (AttributeBlock attr in attributes) {
|
|
attr.AcceptVisitor(this, null);
|
|
}
|
|
}
|
|
|
|
void WritePrivateImplementationType(AstType privateImplementationType)
|
|
{
|
|
if (!privateImplementationType.IsNull) {
|
|
privateImplementationType.AcceptVisitor(this, null);
|
|
WriteToken(".", AstNode.Roles.Dot);
|
|
}
|
|
}
|
|
|
|
void WriteImplementsClause(AstNodeCollection<InterfaceMemberSpecifier> implementsClause)
|
|
{
|
|
if (implementsClause.Any()) {
|
|
Space();
|
|
WriteKeyword("Implements");
|
|
WriteCommaSeparatedList(implementsClause);
|
|
}
|
|
}
|
|
|
|
void WriteImplementsClause(AstNodeCollection<AstType> implementsClause)
|
|
{
|
|
if (implementsClause.Any()) {
|
|
WriteKeyword("Implements");
|
|
WriteCommaSeparatedList(implementsClause);
|
|
}
|
|
}
|
|
|
|
void WriteHandlesClause(AstNodeCollection<EventMemberSpecifier> handlesClause)
|
|
{
|
|
if (handlesClause.Any()) {
|
|
Space();
|
|
WriteKeyword("Handles");
|
|
WriteCommaSeparatedList(handlesClause);
|
|
}
|
|
}
|
|
|
|
void WritePrimitiveValue(object val)
|
|
{
|
|
if (val == null) {
|
|
WriteKeyword("Nothing");
|
|
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) + "\"c");
|
|
lastWritten = LastWritten.Other;
|
|
} else if (val is decimal) {
|
|
formatter.WriteToken(((decimal)val).ToString(NumberFormatInfo.InvariantInfo) + "D");
|
|
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("Single");
|
|
WriteToken(".", AstNode.Roles.Dot);
|
|
if (float.IsPositiveInfinity(f))
|
|
WriteIdentifier("PositiveInfinity");
|
|
else if (float.IsNegativeInfinity(f))
|
|
WriteIdentifier("NegativeInfinity");
|
|
else
|
|
WriteIdentifier("NaN");
|
|
return;
|
|
}
|
|
formatter.WriteToken(f.ToString("R", NumberFormatInfo.InvariantInfo) + "F");
|
|
lastWritten = LastWritten.Other;
|
|
} else if (val is double) {
|
|
double f = (double)val;
|
|
if (double.IsInfinity(f) || double.IsNaN(f)) {
|
|
// Strictly speaking, these aren't PrimitiveExpressions;
|
|
// but we still support writing these to make life easier for code generators.
|
|
WriteKeyword("Double");
|
|
WriteToken(".", AstNode.Roles.Dot);
|
|
if (double.IsPositiveInfinity(f))
|
|
WriteIdentifier("PositiveInfinity");
|
|
else if (double.IsNegativeInfinity(f))
|
|
WriteIdentifier("NegativeInfinity");
|
|
else
|
|
WriteIdentifier("NaN");
|
|
return;
|
|
}
|
|
string number = f.ToString("R", NumberFormatInfo.InvariantInfo);
|
|
if (number.IndexOf('.') < 0 && number.IndexOf('E') < 0)
|
|
number += ".0";
|
|
formatter.WriteToken(number);
|
|
// needs space if identifier follows number; this avoids mistaking the following identifier as type suffix
|
|
lastWritten = LastWritten.KeywordOrIdentifier;
|
|
} else if (val is IFormattable) {
|
|
StringBuilder b = new StringBuilder();
|
|
// if (primitiveExpression.LiteralFormat == LiteralFormat.HexadecimalNumber) {
|
|
// b.Append("0x");
|
|
// b.Append(((IFormattable)val).ToString("x", NumberFormatInfo.InvariantInfo));
|
|
// } else {
|
|
b.Append(((IFormattable)val).ToString(null, NumberFormatInfo.InvariantInfo));
|
|
// }
|
|
if (val is uint || val is ulong) {
|
|
b.Append("U");
|
|
}
|
|
if (val is long || val is ulong) {
|
|
b.Append("L");
|
|
}
|
|
formatter.WriteToken(b.ToString());
|
|
// needs space if identifier follows number; this avoids mistaking the following identifier as type suffix
|
|
lastWritten = LastWritten.KeywordOrIdentifier;
|
|
} else {
|
|
formatter.WriteToken(val.ToString());
|
|
lastWritten = LastWritten.Other;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region ConvertLiteral
|
|
static string ConvertCharLiteral(char ch)
|
|
{
|
|
if (ch == '"') return "\"\"";
|
|
return ch.ToString();
|
|
}
|
|
|
|
static string ConvertString(string str)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
foreach (char ch in str) {
|
|
sb.Append(ConvertCharLiteral(ch));
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
#endregion
|
|
|
|
public object VisitVariableIdentifier(VariableIdentifier variableIdentifier, object data)
|
|
{
|
|
StartNode(variableIdentifier);
|
|
|
|
WriteIdentifier(variableIdentifier.Name.Name);
|
|
if (variableIdentifier.HasNullableSpecifier)
|
|
WriteToken("?", VariableIdentifier.Roles.QuestionMark);
|
|
if (variableIdentifier.ArraySizeSpecifiers.Count > 0)
|
|
WriteCommaSeparatedListInParenthesis(variableIdentifier.ArraySizeSpecifiers, false);
|
|
WriteArraySpecifiers(variableIdentifier.ArraySpecifiers);
|
|
|
|
return EndNode(variableIdentifier);
|
|
}
|
|
|
|
public object VisitAccessor(Accessor accessor, object data)
|
|
{
|
|
StartNode(accessor);
|
|
WriteAttributes(accessor.Attributes);
|
|
WriteModifiers(accessor.ModifierTokens);
|
|
if (accessor.Role == PropertyDeclaration.GetterRole) {
|
|
WriteKeyword("Get");
|
|
} else if (accessor.Role == PropertyDeclaration.SetterRole) {
|
|
WriteKeyword("Set");
|
|
} else if (accessor.Role == EventDeclaration.AddHandlerRole) {
|
|
WriteKeyword("AddHandler");
|
|
} else if (accessor.Role == EventDeclaration.RemoveHandlerRole) {
|
|
WriteKeyword("RemoveHandler");
|
|
} else if (accessor.Role == EventDeclaration.RaiseEventRole) {
|
|
WriteKeyword("RaiseEvent");
|
|
}
|
|
if (accessor.Parameters.Any())
|
|
WriteCommaSeparatedListInParenthesis(accessor.Parameters, false);
|
|
WriteBlock(accessor.Body);
|
|
WriteKeyword("End");
|
|
|
|
if (accessor.Role == PropertyDeclaration.GetterRole) {
|
|
WriteKeyword("Get");
|
|
} else if (accessor.Role == PropertyDeclaration.SetterRole) {
|
|
WriteKeyword("Set");
|
|
} else if (accessor.Role == EventDeclaration.AddHandlerRole) {
|
|
WriteKeyword("AddHandler");
|
|
} else if (accessor.Role == EventDeclaration.RemoveHandlerRole) {
|
|
WriteKeyword("RemoveHandler");
|
|
} else if (accessor.Role == EventDeclaration.RaiseEventRole) {
|
|
WriteKeyword("RaiseEvent");
|
|
}
|
|
NewLine();
|
|
|
|
return EndNode(accessor);
|
|
}
|
|
|
|
|
|
public object VisitLabelDeclarationStatement(LabelDeclarationStatement labelDeclarationStatement, object data)
|
|
{
|
|
StartNode(labelDeclarationStatement);
|
|
|
|
labelDeclarationStatement.Label.AcceptVisitor(this, data);
|
|
WriteToken(":", LabelDeclarationStatement.Roles.Colon);
|
|
|
|
return EndNode(labelDeclarationStatement);
|
|
}
|
|
|
|
public object VisitLocalDeclarationStatement(LocalDeclarationStatement localDeclarationStatement, object data)
|
|
{
|
|
StartNode(localDeclarationStatement);
|
|
|
|
if (localDeclarationStatement.ModifierToken != null && !localDeclarationStatement.ModifierToken.IsNull)
|
|
WriteModifiers(new [] { localDeclarationStatement.ModifierToken });
|
|
WriteCommaSeparatedList(localDeclarationStatement.Variables);
|
|
|
|
return EndNode(localDeclarationStatement);
|
|
}
|
|
|
|
public object VisitWithStatement(WithStatement withStatement, object data)
|
|
{
|
|
StartNode(withStatement);
|
|
WriteKeyword("With");
|
|
withStatement.Expression.AcceptVisitor(this, data);
|
|
withStatement.Body.AcceptVisitor(this, data);
|
|
WriteKeyword("End");
|
|
WriteKeyword("With");
|
|
return EndNode(withStatement);
|
|
}
|
|
|
|
public object VisitSyncLockStatement(SyncLockStatement syncLockStatement, object data)
|
|
{
|
|
StartNode(syncLockStatement);
|
|
WriteKeyword("SyncLock");
|
|
syncLockStatement.Expression.AcceptVisitor(this, data);
|
|
syncLockStatement.Body.AcceptVisitor(this, data);
|
|
WriteKeyword("End");
|
|
WriteKeyword("SyncLock");
|
|
return EndNode(syncLockStatement);
|
|
}
|
|
|
|
public object VisitTryStatement(TryStatement tryStatement, object data)
|
|
{
|
|
StartNode(tryStatement);
|
|
WriteKeyword("Try");
|
|
tryStatement.Body.AcceptVisitor(this, data);
|
|
foreach (var clause in tryStatement.CatchBlocks) {
|
|
clause.AcceptVisitor(this, data);
|
|
}
|
|
if (!tryStatement.FinallyBlock.IsNull) {
|
|
WriteKeyword("Finally");
|
|
tryStatement.FinallyBlock.AcceptVisitor(this, data);
|
|
}
|
|
WriteKeyword("End");
|
|
WriteKeyword("Try");
|
|
return EndNode(tryStatement);
|
|
}
|
|
|
|
public object VisitCatchBlock(CatchBlock catchBlock, object data)
|
|
{
|
|
StartNode(catchBlock);
|
|
WriteKeyword("Catch");
|
|
catchBlock.ExceptionVariable.AcceptVisitor(this, data);
|
|
if (!catchBlock.ExceptionType.IsNull) {
|
|
WriteKeyword("As");
|
|
catchBlock.ExceptionType.AcceptVisitor(this, data);
|
|
}
|
|
NewLine();
|
|
Indent();
|
|
foreach (var stmt in catchBlock) {
|
|
stmt.AcceptVisitor(this, data);
|
|
NewLine();
|
|
}
|
|
Unindent();
|
|
return EndNode(catchBlock);
|
|
}
|
|
|
|
public object VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
|
|
{
|
|
StartNode(expressionStatement);
|
|
expressionStatement.Expression.AcceptVisitor(this, data);
|
|
return EndNode(expressionStatement);
|
|
}
|
|
|
|
public object VisitThrowStatement(ThrowStatement throwStatement, object data)
|
|
{
|
|
StartNode(throwStatement);
|
|
|
|
WriteKeyword("Throw");
|
|
throwStatement.Expression.AcceptVisitor(this, data);
|
|
|
|
return EndNode(throwStatement);
|
|
}
|
|
|
|
public object VisitIfElseStatement(IfElseStatement ifElseStatement, object data)
|
|
{
|
|
StartNode(ifElseStatement);
|
|
WriteKeyword("If");
|
|
ifElseStatement.Condition.AcceptVisitor(this, data);
|
|
Space();
|
|
WriteKeyword("Then");
|
|
bool needsEndIf = ifElseStatement.Body is BlockStatement;
|
|
ifElseStatement.Body.AcceptVisitor(this, data);
|
|
if (!ifElseStatement.ElseBlock.IsNull) {
|
|
WriteKeyword("Else");
|
|
needsEndIf = ifElseStatement.ElseBlock is BlockStatement;
|
|
ifElseStatement.ElseBlock.AcceptVisitor(this, data);
|
|
}
|
|
if (needsEndIf) {
|
|
WriteKeyword("End");
|
|
WriteKeyword("If");
|
|
}
|
|
return EndNode(ifElseStatement);
|
|
}
|
|
|
|
public object VisitReturnStatement(ReturnStatement returnStatement, object data)
|
|
{
|
|
StartNode(returnStatement);
|
|
WriteKeyword("Return");
|
|
returnStatement.Expression.AcceptVisitor(this, data);
|
|
return EndNode(returnStatement);
|
|
}
|
|
|
|
public object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
|
|
{
|
|
StartNode(binaryOperatorExpression);
|
|
binaryOperatorExpression.Left.AcceptVisitor(this, data);
|
|
Space();
|
|
switch (binaryOperatorExpression.Operator) {
|
|
case BinaryOperatorType.BitwiseAnd:
|
|
WriteKeyword("And");
|
|
break;
|
|
case BinaryOperatorType.BitwiseOr:
|
|
WriteKeyword("Or");
|
|
break;
|
|
case BinaryOperatorType.LogicalAnd:
|
|
WriteKeyword("AndAlso");
|
|
break;
|
|
case BinaryOperatorType.LogicalOr:
|
|
WriteKeyword("OrElse");
|
|
break;
|
|
case BinaryOperatorType.ExclusiveOr:
|
|
WriteKeyword("Xor");
|
|
break;
|
|
case BinaryOperatorType.GreaterThan:
|
|
WriteToken(">", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.GreaterThanOrEqual:
|
|
WriteToken(">=", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.Equality:
|
|
WriteToken("=", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.InEquality:
|
|
WriteToken("<>", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.LessThan:
|
|
WriteToken("<", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.LessThanOrEqual:
|
|
WriteToken("<=", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.Add:
|
|
WriteToken("+", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.Subtract:
|
|
WriteToken("-", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.Multiply:
|
|
WriteToken("*", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.Divide:
|
|
WriteToken("/", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.Modulus:
|
|
WriteKeyword("Mod");
|
|
break;
|
|
case BinaryOperatorType.DivideInteger:
|
|
WriteToken("\\", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.Power:
|
|
WriteToken("*", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.Concat:
|
|
WriteToken("&", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.ShiftLeft:
|
|
WriteToken("<<", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.ShiftRight:
|
|
WriteToken(">>", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case BinaryOperatorType.ReferenceEquality:
|
|
WriteKeyword("Is");
|
|
break;
|
|
case BinaryOperatorType.ReferenceInequality:
|
|
WriteKeyword("IsNot");
|
|
break;
|
|
case BinaryOperatorType.Like:
|
|
WriteKeyword("Like");
|
|
break;
|
|
case BinaryOperatorType.DictionaryAccess:
|
|
WriteToken("!", BinaryOperatorExpression.OperatorRole);
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for BinaryOperatorType: " + binaryOperatorExpression.Operator);
|
|
}
|
|
Space();
|
|
binaryOperatorExpression.Right.AcceptVisitor(this, data);
|
|
return EndNode(binaryOperatorExpression);
|
|
}
|
|
|
|
public object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
|
|
{
|
|
StartNode(identifierExpression);
|
|
identifierExpression.Identifier.AcceptVisitor(this, data);
|
|
WriteTypeArguments(identifierExpression.TypeArguments);
|
|
return EndNode(identifierExpression);
|
|
}
|
|
|
|
public object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data)
|
|
{
|
|
StartNode(assignmentExpression);
|
|
assignmentExpression.Left.AcceptVisitor(this, data);
|
|
Space();
|
|
switch (assignmentExpression.Operator) {
|
|
case AssignmentOperatorType.Assign:
|
|
WriteToken("=", AssignmentExpression.OperatorRole);
|
|
break;
|
|
case AssignmentOperatorType.Add:
|
|
WriteToken("+=", AssignmentExpression.OperatorRole);
|
|
break;
|
|
case AssignmentOperatorType.Subtract:
|
|
WriteToken("-=", AssignmentExpression.OperatorRole);
|
|
break;
|
|
case AssignmentOperatorType.Multiply:
|
|
WriteToken("*=", AssignmentExpression.OperatorRole);
|
|
break;
|
|
case AssignmentOperatorType.Divide:
|
|
WriteToken("/=", AssignmentExpression.OperatorRole);
|
|
break;
|
|
case AssignmentOperatorType.Power:
|
|
WriteToken("^=", AssignmentExpression.OperatorRole);
|
|
break;
|
|
case AssignmentOperatorType.DivideInteger:
|
|
WriteToken("\\=", AssignmentExpression.OperatorRole);
|
|
break;
|
|
case AssignmentOperatorType.ConcatString:
|
|
WriteToken("&=", AssignmentExpression.OperatorRole);
|
|
break;
|
|
case AssignmentOperatorType.ShiftLeft:
|
|
WriteToken("<<=", AssignmentExpression.OperatorRole);
|
|
break;
|
|
case AssignmentOperatorType.ShiftRight:
|
|
WriteToken(">>=", AssignmentExpression.OperatorRole);
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for AssignmentOperatorType: " + assignmentExpression.Operator);
|
|
}
|
|
Space();
|
|
assignmentExpression.Right.AcceptVisitor(this, data);
|
|
return EndNode(assignmentExpression);
|
|
}
|
|
|
|
public object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
|
|
{
|
|
StartNode(invocationExpression);
|
|
invocationExpression.Target.AcceptVisitor(this, data);
|
|
WriteCommaSeparatedListInParenthesis(invocationExpression.Arguments, false);
|
|
return EndNode(invocationExpression);
|
|
}
|
|
|
|
public object VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, object data)
|
|
{
|
|
StartNode(arrayInitializerExpression);
|
|
WriteToken("{", ArrayInitializerExpression.Roles.LBrace);
|
|
Space();
|
|
WriteCommaSeparatedList(arrayInitializerExpression.Elements);
|
|
Space();
|
|
WriteToken("}", ArrayInitializerExpression.Roles.RBrace);
|
|
return EndNode(arrayInitializerExpression);
|
|
}
|
|
|
|
public object VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data)
|
|
{
|
|
StartNode(arrayCreateExpression);
|
|
WriteKeyword("New");
|
|
Space();
|
|
arrayCreateExpression.Type.AcceptVisitor(this, data);
|
|
WriteCommaSeparatedListInParenthesis(arrayCreateExpression.Arguments, false);
|
|
foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers) {
|
|
specifier.AcceptVisitor(this, data);
|
|
}
|
|
if (lastWritten != LastWritten.Whitespace)
|
|
Space();
|
|
if (arrayCreateExpression.Initializer.IsNull) {
|
|
WriteToken("{", ArrayInitializerExpression.Roles.LBrace);
|
|
WriteToken("}", ArrayInitializerExpression.Roles.RBrace);
|
|
} else {
|
|
arrayCreateExpression.Initializer.AcceptVisitor(this, data);
|
|
}
|
|
return EndNode(arrayCreateExpression);
|
|
}
|
|
|
|
public object VisitObjectCreationExpression(ObjectCreationExpression objectCreationExpression, object data)
|
|
{
|
|
StartNode(objectCreationExpression);
|
|
|
|
WriteKeyword("New");
|
|
objectCreationExpression.Type.AcceptVisitor(this, data);
|
|
WriteCommaSeparatedListInParenthesis(objectCreationExpression.Arguments, false);
|
|
if (!objectCreationExpression.Initializer.IsNull) {
|
|
Space();
|
|
if (objectCreationExpression.Initializer.Elements.Any(x => x is FieldInitializerExpression))
|
|
WriteKeyword("With");
|
|
else
|
|
WriteKeyword("From");
|
|
Space();
|
|
objectCreationExpression.Initializer.AcceptVisitor(this, data);
|
|
}
|
|
|
|
return EndNode(objectCreationExpression);
|
|
}
|
|
|
|
public object VisitCastExpression(CastExpression castExpression, object data)
|
|
{
|
|
StartNode(castExpression);
|
|
|
|
switch (castExpression.CastType) {
|
|
case CastType.DirectCast:
|
|
WriteKeyword("DirectCast");
|
|
break;
|
|
case CastType.TryCast:
|
|
WriteKeyword("TryCast");
|
|
break;
|
|
case CastType.CType:
|
|
WriteKeyword("CType");
|
|
break;
|
|
case CastType.CBool:
|
|
WriteKeyword("CBool");
|
|
break;
|
|
case CastType.CByte:
|
|
WriteKeyword("CByte");
|
|
break;
|
|
case CastType.CChar:
|
|
WriteKeyword("CChar");
|
|
break;
|
|
case CastType.CDate:
|
|
WriteKeyword("CDate");
|
|
break;
|
|
case CastType.CDec:
|
|
WriteKeyword("CType");
|
|
break;
|
|
case CastType.CDbl:
|
|
WriteKeyword("CDec");
|
|
break;
|
|
case CastType.CInt:
|
|
WriteKeyword("CInt");
|
|
break;
|
|
case CastType.CLng:
|
|
WriteKeyword("CLng");
|
|
break;
|
|
case CastType.CObj:
|
|
WriteKeyword("CObj");
|
|
break;
|
|
case CastType.CSByte:
|
|
WriteKeyword("CSByte");
|
|
break;
|
|
case CastType.CShort:
|
|
WriteKeyword("CShort");
|
|
break;
|
|
case CastType.CSng:
|
|
WriteKeyword("CSng");
|
|
break;
|
|
case CastType.CStr:
|
|
WriteKeyword("CStr");
|
|
break;
|
|
case CastType.CUInt:
|
|
WriteKeyword("CUInt");
|
|
break;
|
|
case CastType.CULng:
|
|
WriteKeyword("CULng");
|
|
break;
|
|
case CastType.CUShort:
|
|
WriteKeyword("CUShort");
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for CastType");
|
|
}
|
|
|
|
WriteToken("(", CastExpression.Roles.LPar);
|
|
castExpression.Expression.AcceptVisitor(this, data);
|
|
|
|
if (castExpression.CastType == CastType.CType ||
|
|
castExpression.CastType == CastType.DirectCast ||
|
|
castExpression.CastType == CastType.TryCast) {
|
|
WriteToken(",", CastExpression.Roles.Comma);
|
|
Space();
|
|
castExpression.Type.AcceptVisitor(this, data);
|
|
}
|
|
|
|
WriteToken(")", CastExpression.Roles.RPar);
|
|
|
|
return EndNode(castExpression);
|
|
}
|
|
|
|
public object VisitComment(Comment comment, object data)
|
|
{
|
|
formatter.WriteComment(comment.IsDocumentationComment, comment.Content);
|
|
return null;
|
|
}
|
|
|
|
public object VisitEventDeclaration(EventDeclaration eventDeclaration, object data)
|
|
{
|
|
StartNode(eventDeclaration);
|
|
|
|
WriteAttributes(eventDeclaration.Attributes);
|
|
WriteModifiers(eventDeclaration.ModifierTokens);
|
|
if (eventDeclaration.IsCustom)
|
|
WriteKeyword("Custom");
|
|
WriteKeyword("Event");
|
|
WriteIdentifier(eventDeclaration.Name.Name);
|
|
if (!eventDeclaration.IsCustom && eventDeclaration.ReturnType.IsNull)
|
|
WriteCommaSeparatedListInParenthesis(eventDeclaration.Parameters, false);
|
|
if (!eventDeclaration.ReturnType.IsNull) {
|
|
Space();
|
|
WriteKeyword("As");
|
|
eventDeclaration.ReturnType.AcceptVisitor(this, data);
|
|
}
|
|
WriteImplementsClause(eventDeclaration.ImplementsClause);
|
|
|
|
if (eventDeclaration.IsCustom) {
|
|
MarkFoldStart();
|
|
NewLine();
|
|
Indent();
|
|
|
|
eventDeclaration.AddHandlerBlock.AcceptVisitor(this, data);
|
|
eventDeclaration.RemoveHandlerBlock.AcceptVisitor(this, data);
|
|
eventDeclaration.RaiseEventBlock.AcceptVisitor(this, data);
|
|
|
|
Unindent();
|
|
WriteKeyword("End");
|
|
WriteKeyword("Event");
|
|
MarkFoldEnd();
|
|
}
|
|
NewLine();
|
|
|
|
return EndNode(eventDeclaration);
|
|
}
|
|
|
|
public object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
|
|
{
|
|
StartNode(unaryOperatorExpression);
|
|
|
|
switch (unaryOperatorExpression.Operator) {
|
|
case UnaryOperatorType.Not:
|
|
WriteKeyword("Not");
|
|
break;
|
|
case UnaryOperatorType.Minus:
|
|
WriteToken("-", UnaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case UnaryOperatorType.Plus:
|
|
WriteToken("+", UnaryOperatorExpression.OperatorRole);
|
|
break;
|
|
case UnaryOperatorType.AddressOf:
|
|
WriteKeyword("AddressOf");
|
|
break;
|
|
case UnaryOperatorType.Await:
|
|
WriteKeyword("Await");
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for UnaryOperatorType");
|
|
}
|
|
|
|
unaryOperatorExpression.Expression.AcceptVisitor(this, data);
|
|
|
|
return EndNode(unaryOperatorExpression);
|
|
}
|
|
|
|
public object VisitFieldInitializerExpression(FieldInitializerExpression fieldInitializerExpression, object data)
|
|
{
|
|
StartNode(fieldInitializerExpression);
|
|
|
|
if (fieldInitializerExpression.IsKey && fieldInitializerExpression.Parent is AnonymousObjectCreationExpression) {
|
|
WriteKeyword("Key");
|
|
Space();
|
|
}
|
|
|
|
WriteToken(".", FieldInitializerExpression.Roles.Dot);
|
|
fieldInitializerExpression.Identifier.AcceptVisitor(this, data);
|
|
|
|
Space();
|
|
WriteToken("=", FieldInitializerExpression.Roles.Assign);
|
|
Space();
|
|
fieldInitializerExpression.Expression.AcceptVisitor(this, data);
|
|
|
|
return EndNode(fieldInitializerExpression);
|
|
}
|
|
|
|
public object VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public object VisitConditionalExpression(ConditionalExpression conditionalExpression, object data)
|
|
{
|
|
StartNode(conditionalExpression);
|
|
|
|
WriteKeyword("If");
|
|
WriteToken("(", ConditionalExpression.Roles.LPar);
|
|
|
|
conditionalExpression.ConditionExpression.AcceptVisitor(this, data);
|
|
WriteToken(",", ConditionalExpression.Roles.Comma);
|
|
Space();
|
|
|
|
if (!conditionalExpression.TrueExpression.IsNull) {
|
|
conditionalExpression.TrueExpression.AcceptVisitor(this, data);
|
|
WriteToken(",", ConditionalExpression.Roles.Comma);
|
|
Space();
|
|
}
|
|
|
|
conditionalExpression.FalseExpression.AcceptVisitor(this, data);
|
|
|
|
WriteToken(")", ConditionalExpression.Roles.RPar);
|
|
|
|
return EndNode(conditionalExpression);
|
|
}
|
|
|
|
public object VisitWhileStatement(WhileStatement whileStatement, object data)
|
|
{
|
|
StartNode(whileStatement);
|
|
|
|
WriteKeyword("While");
|
|
Space();
|
|
whileStatement.Condition.AcceptVisitor(this, data);
|
|
whileStatement.Body.AcceptVisitor(this, data);
|
|
WriteKeyword("End");
|
|
WriteKeyword("While");
|
|
|
|
return EndNode(whileStatement);
|
|
}
|
|
|
|
public object VisitExitStatement(ExitStatement exitStatement, object data)
|
|
{
|
|
StartNode(exitStatement);
|
|
|
|
WriteKeyword("Exit");
|
|
|
|
switch (exitStatement.ExitKind) {
|
|
case ExitKind.Sub:
|
|
WriteKeyword("Sub");
|
|
break;
|
|
case ExitKind.Function:
|
|
WriteKeyword("Function");
|
|
break;
|
|
case ExitKind.Property:
|
|
WriteKeyword("Property");
|
|
break;
|
|
case ExitKind.Do:
|
|
WriteKeyword("Do");
|
|
break;
|
|
case ExitKind.For:
|
|
WriteKeyword("For");
|
|
break;
|
|
case ExitKind.While:
|
|
WriteKeyword("While");
|
|
break;
|
|
case ExitKind.Select:
|
|
WriteKeyword("Select");
|
|
break;
|
|
case ExitKind.Try:
|
|
WriteKeyword("Try");
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for ExitKind");
|
|
}
|
|
|
|
return EndNode(exitStatement);
|
|
}
|
|
|
|
public object VisitForStatement(ForStatement forStatement, object data)
|
|
{
|
|
StartNode(forStatement);
|
|
|
|
WriteKeyword("For");
|
|
forStatement.Variable.AcceptVisitor(this, data);
|
|
WriteKeyword("To");
|
|
forStatement.ToExpression.AcceptVisitor(this, data);
|
|
if (!forStatement.StepExpression.IsNull) {
|
|
WriteKeyword("Step");
|
|
Space();
|
|
forStatement.StepExpression.AcceptVisitor(this, data);
|
|
}
|
|
forStatement.Body.AcceptVisitor(this, data);
|
|
WriteKeyword("Next");
|
|
|
|
return EndNode(forStatement);
|
|
}
|
|
|
|
public object VisitForEachStatement(ForEachStatement forEachStatement, object data)
|
|
{
|
|
StartNode(forEachStatement);
|
|
|
|
WriteKeyword("For");
|
|
WriteKeyword("Each");
|
|
forEachStatement.Variable.AcceptVisitor(this, data);
|
|
Space();
|
|
WriteKeyword("In");
|
|
forEachStatement.InExpression.AcceptVisitor(this, data);
|
|
forEachStatement.Body.AcceptVisitor(this, data);
|
|
WriteKeyword("Next");
|
|
|
|
return EndNode(forEachStatement);
|
|
}
|
|
|
|
public object VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data)
|
|
{
|
|
StartNode(operatorDeclaration);
|
|
|
|
WriteAttributes(operatorDeclaration.Attributes);
|
|
WriteModifiers(operatorDeclaration.ModifierTokens);
|
|
WriteKeyword("Operator");
|
|
switch (operatorDeclaration.Operator) {
|
|
case OverloadableOperatorType.Add:
|
|
case OverloadableOperatorType.UnaryPlus:
|
|
WriteToken("+", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.Subtract:
|
|
case OverloadableOperatorType.UnaryMinus:
|
|
WriteToken("-", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.Multiply:
|
|
WriteToken("*", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.Divide:
|
|
WriteToken("/", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.Modulus:
|
|
WriteKeyword("Mod");
|
|
break;
|
|
case OverloadableOperatorType.Concat:
|
|
WriteToken("&", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.Not:
|
|
WriteKeyword("Not");
|
|
break;
|
|
case OverloadableOperatorType.BitwiseAnd:
|
|
WriteKeyword("And");
|
|
break;
|
|
case OverloadableOperatorType.BitwiseOr:
|
|
WriteKeyword("Or");
|
|
break;
|
|
case OverloadableOperatorType.ExclusiveOr:
|
|
WriteKeyword("Xor");
|
|
break;
|
|
case OverloadableOperatorType.ShiftLeft:
|
|
WriteToken("<<", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.ShiftRight:
|
|
WriteToken(">>", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.GreaterThan:
|
|
WriteToken(">", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.GreaterThanOrEqual:
|
|
WriteToken(">=", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.Equality:
|
|
WriteToken("=", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.InEquality:
|
|
WriteToken("<>", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.LessThan:
|
|
WriteToken("<", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.LessThanOrEqual:
|
|
WriteToken("<=", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.IsTrue:
|
|
WriteKeyword("IsTrue");
|
|
break;
|
|
case OverloadableOperatorType.IsFalse:
|
|
WriteKeyword("IsFalse");
|
|
break;
|
|
case OverloadableOperatorType.Like:
|
|
WriteKeyword("Like");
|
|
break;
|
|
case OverloadableOperatorType.Power:
|
|
WriteToken("^", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
case OverloadableOperatorType.CType:
|
|
WriteKeyword("CType");
|
|
break;
|
|
case OverloadableOperatorType.DivideInteger:
|
|
WriteToken("\\", OperatorDeclaration.Roles.Keyword);
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for OverloadableOperatorType");
|
|
}
|
|
WriteCommaSeparatedListInParenthesis(operatorDeclaration.Parameters, false);
|
|
if (!operatorDeclaration.ReturnType.IsNull) {
|
|
Space();
|
|
WriteKeyword("As");
|
|
WriteAttributes(operatorDeclaration.ReturnTypeAttributes);
|
|
operatorDeclaration.ReturnType.AcceptVisitor(this, data);
|
|
}
|
|
if (!operatorDeclaration.Body.IsNull) {
|
|
MarkFoldStart();
|
|
WriteBlock(operatorDeclaration.Body);
|
|
WriteKeyword("End");
|
|
WriteKeyword("Operator");
|
|
MarkFoldEnd();
|
|
}
|
|
NewLine();
|
|
|
|
return EndNode(operatorDeclaration);
|
|
}
|
|
|
|
public object VisitSelectStatement(SelectStatement selectStatement, object data)
|
|
{
|
|
StartNode(selectStatement);
|
|
|
|
WriteKeyword("Select");
|
|
WriteKeyword("Case");
|
|
selectStatement.Expression.AcceptVisitor(this, data);
|
|
NewLine();
|
|
Indent();
|
|
|
|
foreach (CaseStatement stmt in selectStatement.Cases) {
|
|
stmt.AcceptVisitor(this, data);
|
|
}
|
|
|
|
Unindent();
|
|
WriteKeyword("End");
|
|
WriteKeyword("Select");
|
|
|
|
return EndNode(selectStatement);
|
|
}
|
|
|
|
public object VisitCaseStatement(CaseStatement caseStatement, object data)
|
|
{
|
|
StartNode(caseStatement);
|
|
|
|
WriteKeyword("Case");
|
|
if (caseStatement.Clauses.Count == 1 && caseStatement.Clauses.First().Expression.IsNull)
|
|
WriteKeyword("Else");
|
|
else {
|
|
Space();
|
|
WriteCommaSeparatedList(caseStatement.Clauses);
|
|
}
|
|
caseStatement.Body.AcceptVisitor(this, data);
|
|
|
|
return EndNode(caseStatement);
|
|
}
|
|
|
|
public object VisitSimpleCaseClause(SimpleCaseClause simpleCaseClause, object data)
|
|
{
|
|
StartNode(simpleCaseClause);
|
|
simpleCaseClause.Expression.AcceptVisitor(this, data);
|
|
return EndNode(simpleCaseClause);
|
|
}
|
|
|
|
public object VisitRangeCaseClause(RangeCaseClause rangeCaseClause, object data)
|
|
{
|
|
StartNode(rangeCaseClause);
|
|
rangeCaseClause.Expression.AcceptVisitor(this, data);
|
|
WriteKeyword("To");
|
|
rangeCaseClause.ToExpression.AcceptVisitor(this, data);
|
|
return EndNode(rangeCaseClause);
|
|
}
|
|
|
|
public object VisitComparisonCaseClause(ComparisonCaseClause comparisonCaseClause, object data)
|
|
{
|
|
StartNode(comparisonCaseClause);
|
|
switch (comparisonCaseClause.Operator) {
|
|
case ComparisonOperator.Equality:
|
|
WriteToken("=", ComparisonCaseClause.OperatorRole);
|
|
break;
|
|
case ComparisonOperator.InEquality:
|
|
WriteToken("<>", ComparisonCaseClause.OperatorRole);
|
|
break;
|
|
case ComparisonOperator.LessThan:
|
|
WriteToken("<", ComparisonCaseClause.OperatorRole);
|
|
break;
|
|
case ComparisonOperator.GreaterThan:
|
|
WriteToken(">", ComparisonCaseClause.OperatorRole);
|
|
break;
|
|
case ComparisonOperator.LessThanOrEqual:
|
|
WriteToken("<=", ComparisonCaseClause.OperatorRole);
|
|
break;
|
|
case ComparisonOperator.GreaterThanOrEqual:
|
|
WriteToken(">=", ComparisonCaseClause.OperatorRole);
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for ComparisonOperator");
|
|
}
|
|
Space();
|
|
comparisonCaseClause.Expression.AcceptVisitor(this, data);
|
|
return EndNode(comparisonCaseClause);
|
|
}
|
|
|
|
|
|
public object VisitYieldStatement(YieldStatement yieldStatement, object data)
|
|
{
|
|
StartNode(yieldStatement);
|
|
WriteKeyword("Yield");
|
|
yieldStatement.Expression.AcceptVisitor(this, data);
|
|
return EndNode(yieldStatement);
|
|
}
|
|
|
|
public object VisitVariableInitializer(VariableInitializer variableInitializer, object data)
|
|
{
|
|
StartNode(variableInitializer);
|
|
|
|
variableInitializer.Identifier.AcceptVisitor(this, data);
|
|
if (!variableInitializer.Type.IsNull) {
|
|
if (lastWritten != LastWritten.Whitespace)
|
|
Space();
|
|
WriteKeyword("As");
|
|
variableInitializer.Type.AcceptVisitor(this, data);
|
|
}
|
|
if (!variableInitializer.Expression.IsNull) {
|
|
Space();
|
|
WriteToken("=", VariableInitializer.Roles.Assign);
|
|
Space();
|
|
variableInitializer.Expression.AcceptVisitor(this, data);
|
|
}
|
|
|
|
return EndNode(variableInitializer);
|
|
}
|
|
|
|
public object VisitVariableDeclaratorWithTypeAndInitializer(VariableDeclaratorWithTypeAndInitializer variableDeclaratorWithTypeAndInitializer, object data)
|
|
{
|
|
StartNode(variableDeclaratorWithTypeAndInitializer);
|
|
|
|
WriteCommaSeparatedList(variableDeclaratorWithTypeAndInitializer.Identifiers);
|
|
if (lastWritten != LastWritten.Whitespace)
|
|
Space();
|
|
WriteKeyword("As");
|
|
variableDeclaratorWithTypeAndInitializer.Type.AcceptVisitor(this, data);
|
|
if (!variableDeclaratorWithTypeAndInitializer.Initializer.IsNull) {
|
|
Space();
|
|
WriteToken("=", VariableDeclarator.Roles.Assign);
|
|
Space();
|
|
variableDeclaratorWithTypeAndInitializer.Initializer.AcceptVisitor(this, data);
|
|
}
|
|
|
|
return EndNode(variableDeclaratorWithTypeAndInitializer);
|
|
}
|
|
|
|
public object VisitVariableDeclaratorWithObjectCreation(VariableDeclaratorWithObjectCreation variableDeclaratorWithObjectCreation, object data)
|
|
{
|
|
StartNode(variableDeclaratorWithObjectCreation);
|
|
|
|
WriteCommaSeparatedList(variableDeclaratorWithObjectCreation.Identifiers);
|
|
if (lastWritten != LastWritten.Whitespace)
|
|
Space();
|
|
WriteKeyword("As");
|
|
variableDeclaratorWithObjectCreation.Initializer.AcceptVisitor(this, data);
|
|
|
|
return EndNode(variableDeclaratorWithObjectCreation);
|
|
}
|
|
|
|
public object VisitDoLoopStatement(DoLoopStatement doLoopStatement, object data)
|
|
{
|
|
StartNode(doLoopStatement);
|
|
|
|
WriteKeyword("Do");
|
|
if (doLoopStatement.ConditionType == ConditionType.DoUntil) {
|
|
WriteKeyword("Until");
|
|
doLoopStatement.Expression.AcceptVisitor(this, data);
|
|
}
|
|
if (doLoopStatement.ConditionType == ConditionType.DoWhile) {
|
|
WriteKeyword("While");
|
|
doLoopStatement.Expression.AcceptVisitor(this, data);
|
|
}
|
|
doLoopStatement.Body.AcceptVisitor(this, data);
|
|
WriteKeyword("Loop");
|
|
if (doLoopStatement.ConditionType == ConditionType.LoopUntil) {
|
|
WriteKeyword("Until");
|
|
doLoopStatement.Expression.AcceptVisitor(this, data);
|
|
}
|
|
if (doLoopStatement.ConditionType == ConditionType.LoopWhile) {
|
|
WriteKeyword("While");
|
|
doLoopStatement.Expression.AcceptVisitor(this, data);
|
|
}
|
|
|
|
return EndNode(doLoopStatement);
|
|
}
|
|
|
|
public object VisitUsingStatement(UsingStatement usingStatement, object data)
|
|
{
|
|
StartNode(usingStatement);
|
|
|
|
WriteKeyword("Using");
|
|
WriteCommaSeparatedList(usingStatement.Resources);
|
|
usingStatement.Body.AcceptVisitor(this, data);
|
|
WriteKeyword("End");
|
|
WriteKeyword("Using");
|
|
|
|
return EndNode(usingStatement);
|
|
}
|
|
|
|
public object VisitGoToStatement(GoToStatement goToStatement, object data)
|
|
{
|
|
StartNode(goToStatement);
|
|
|
|
WriteKeyword("GoTo");
|
|
goToStatement.Label.AcceptVisitor(this, data);
|
|
|
|
return EndNode(goToStatement);
|
|
}
|
|
|
|
public object VisitSingleLineSubLambdaExpression(SingleLineSubLambdaExpression singleLineSubLambdaExpression, object data)
|
|
{
|
|
StartNode(singleLineSubLambdaExpression);
|
|
|
|
WriteModifiers(singleLineSubLambdaExpression.ModifierTokens);
|
|
WriteKeyword("Sub");
|
|
WriteCommaSeparatedListInParenthesis(singleLineSubLambdaExpression.Parameters, false);
|
|
Space();
|
|
singleLineSubLambdaExpression.EmbeddedStatement.AcceptVisitor(this, data);
|
|
|
|
return EndNode(singleLineSubLambdaExpression);
|
|
}
|
|
|
|
public object VisitSingleLineFunctionLambdaExpression(SingleLineFunctionLambdaExpression singleLineFunctionLambdaExpression, object data)
|
|
{
|
|
StartNode(singleLineFunctionLambdaExpression);
|
|
|
|
WriteModifiers(singleLineFunctionLambdaExpression.ModifierTokens);
|
|
WriteKeyword("Function");
|
|
WriteCommaSeparatedListInParenthesis(singleLineFunctionLambdaExpression.Parameters, false);
|
|
Space();
|
|
singleLineFunctionLambdaExpression.EmbeddedExpression.AcceptVisitor(this, data);
|
|
|
|
return EndNode(singleLineFunctionLambdaExpression);
|
|
}
|
|
|
|
public object VisitMultiLineLambdaExpression(MultiLineLambdaExpression multiLineLambdaExpression, object data)
|
|
{
|
|
StartNode(multiLineLambdaExpression);
|
|
|
|
WriteModifiers(multiLineLambdaExpression.ModifierTokens);
|
|
if (multiLineLambdaExpression.IsSub)
|
|
WriteKeyword("Sub");
|
|
else
|
|
WriteKeyword("Function");
|
|
WriteCommaSeparatedListInParenthesis(multiLineLambdaExpression.Parameters, false);
|
|
multiLineLambdaExpression.Body.AcceptVisitor(this, data);
|
|
WriteKeyword("End");
|
|
if (multiLineLambdaExpression.IsSub)
|
|
WriteKeyword("Sub");
|
|
else
|
|
WriteKeyword("Function");
|
|
|
|
return EndNode(multiLineLambdaExpression);
|
|
}
|
|
|
|
public object VisitQueryExpression(QueryExpression queryExpression, object data)
|
|
{
|
|
StartNode(queryExpression);
|
|
|
|
foreach (var op in queryExpression.QueryOperators) {
|
|
op.AcceptVisitor(this, data);
|
|
}
|
|
|
|
return EndNode(queryExpression);
|
|
}
|
|
|
|
public object VisitContinueStatement(ContinueStatement continueStatement, object data)
|
|
{
|
|
StartNode(continueStatement);
|
|
|
|
WriteKeyword("Continue");
|
|
|
|
switch (continueStatement.ContinueKind) {
|
|
case ContinueKind.Do:
|
|
WriteKeyword("Do");
|
|
break;
|
|
case ContinueKind.For:
|
|
WriteKeyword("For");
|
|
break;
|
|
case ContinueKind.While:
|
|
WriteKeyword("While");
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for ContinueKind");
|
|
}
|
|
|
|
return EndNode(continueStatement);
|
|
}
|
|
|
|
public object VisitExternalMethodDeclaration(ExternalMethodDeclaration externalMethodDeclaration, object data)
|
|
{
|
|
StartNode(externalMethodDeclaration);
|
|
|
|
WriteAttributes(externalMethodDeclaration.Attributes);
|
|
WriteModifiers(externalMethodDeclaration.ModifierTokens);
|
|
WriteKeyword("Declare");
|
|
switch (externalMethodDeclaration.CharsetModifier) {
|
|
case CharsetModifier.None:
|
|
break;
|
|
case CharsetModifier.Auto:
|
|
WriteKeyword("Auto");
|
|
break;
|
|
case CharsetModifier.Unicode:
|
|
WriteKeyword("Unicode");
|
|
break;
|
|
case CharsetModifier.Ansi:
|
|
WriteKeyword("Ansi");
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for CharsetModifier");
|
|
}
|
|
if (externalMethodDeclaration.IsSub)
|
|
WriteKeyword("Sub");
|
|
else
|
|
WriteKeyword("Function");
|
|
externalMethodDeclaration.Name.AcceptVisitor(this, data);
|
|
WriteKeyword("Lib");
|
|
Space();
|
|
WritePrimitiveValue(externalMethodDeclaration.Library);
|
|
Space();
|
|
if (externalMethodDeclaration.Alias != null) {
|
|
WriteKeyword("Alias");
|
|
Space();
|
|
WritePrimitiveValue(externalMethodDeclaration.Alias);
|
|
Space();
|
|
}
|
|
WriteCommaSeparatedListInParenthesis(externalMethodDeclaration.Parameters, false);
|
|
if (!externalMethodDeclaration.IsSub && !externalMethodDeclaration.ReturnType.IsNull) {
|
|
Space();
|
|
WriteKeyword("As");
|
|
WriteAttributes(externalMethodDeclaration.ReturnTypeAttributes);
|
|
externalMethodDeclaration.ReturnType.AcceptVisitor(this, data);
|
|
}
|
|
NewLine();
|
|
|
|
return EndNode(externalMethodDeclaration);
|
|
}
|
|
|
|
public static string ToVBNetString(PrimitiveExpression primitiveExpression)
|
|
{
|
|
var writer = new StringWriter();
|
|
new OutputVisitor(writer, new VBFormattingOptions()).WritePrimitiveValue(primitiveExpression.Value);
|
|
return writer.ToString();
|
|
}
|
|
|
|
public object VisitEmptyExpression(EmptyExpression emptyExpression, object data)
|
|
{
|
|
StartNode(emptyExpression);
|
|
|
|
return EndNode(emptyExpression);
|
|
}
|
|
|
|
public object VisitAnonymousObjectCreationExpression(AnonymousObjectCreationExpression anonymousObjectCreationExpression, object data)
|
|
{
|
|
StartNode(anonymousObjectCreationExpression);
|
|
|
|
WriteKeyword("New");
|
|
WriteKeyword("With");
|
|
|
|
WriteToken("{", AnonymousObjectCreationExpression.Roles.LBrace);
|
|
Space();
|
|
WriteCommaSeparatedList(anonymousObjectCreationExpression.Initializer);
|
|
Space();
|
|
WriteToken("}", AnonymousObjectCreationExpression.Roles.RBrace);
|
|
|
|
return EndNode(anonymousObjectCreationExpression);
|
|
}
|
|
|
|
public object VisitCollectionRangeVariableDeclaration(CollectionRangeVariableDeclaration collectionRangeVariableDeclaration, object data)
|
|
{
|
|
StartNode(collectionRangeVariableDeclaration);
|
|
|
|
collectionRangeVariableDeclaration.Identifier.AcceptVisitor(this, data);
|
|
if (!collectionRangeVariableDeclaration.Type.IsNull) {
|
|
WriteKeyword("As");
|
|
collectionRangeVariableDeclaration.Type.AcceptVisitor(this, data);
|
|
}
|
|
WriteKeyword("In");
|
|
collectionRangeVariableDeclaration.Expression.AcceptVisitor(this, data);
|
|
|
|
return EndNode(collectionRangeVariableDeclaration);
|
|
}
|
|
|
|
public object VisitFromQueryOperator(FromQueryOperator fromQueryOperator, object data)
|
|
{
|
|
StartNode(fromQueryOperator);
|
|
|
|
WriteKeyword("From");
|
|
WriteCommaSeparatedList(fromQueryOperator.Variables);
|
|
|
|
return EndNode(fromQueryOperator);
|
|
}
|
|
|
|
public object VisitAggregateQueryOperator(AggregateQueryOperator aggregateQueryOperator, object data)
|
|
{
|
|
StartNode(aggregateQueryOperator);
|
|
|
|
WriteKeyword("Aggregate");
|
|
aggregateQueryOperator.Variable.AcceptVisitor(this, data);
|
|
|
|
foreach (var operators in aggregateQueryOperator.SubQueryOperators) {
|
|
operators.AcceptVisitor(this, data);
|
|
}
|
|
|
|
WriteKeyword("Into");
|
|
WriteCommaSeparatedList(aggregateQueryOperator.IntoExpressions);
|
|
|
|
return EndNode(aggregateQueryOperator);
|
|
}
|
|
|
|
public object VisitSelectQueryOperator(SelectQueryOperator selectQueryOperator, object data)
|
|
{
|
|
StartNode(selectQueryOperator);
|
|
|
|
WriteKeyword("Select");
|
|
WriteCommaSeparatedList(selectQueryOperator.Variables);
|
|
|
|
return EndNode(selectQueryOperator);
|
|
}
|
|
|
|
public object VisitDistinctQueryOperator(DistinctQueryOperator distinctQueryOperator, object data)
|
|
{
|
|
StartNode(distinctQueryOperator);
|
|
|
|
WriteKeyword("Distinct");
|
|
|
|
return EndNode(distinctQueryOperator);
|
|
}
|
|
|
|
public object VisitWhereQueryOperator(WhereQueryOperator whereQueryOperator, object data)
|
|
{
|
|
StartNode(whereQueryOperator);
|
|
|
|
WriteKeyword("Where");
|
|
whereQueryOperator.Condition.AcceptVisitor(this, data);
|
|
|
|
return EndNode(whereQueryOperator);
|
|
}
|
|
|
|
public object VisitPartitionQueryOperator(PartitionQueryOperator partitionQueryOperator, object data)
|
|
{
|
|
StartNode(partitionQueryOperator);
|
|
|
|
switch (partitionQueryOperator.Kind) {
|
|
case PartitionKind.Take:
|
|
WriteKeyword("Take");
|
|
break;
|
|
case PartitionKind.TakeWhile:
|
|
WriteKeyword("Take");
|
|
WriteKeyword("While");
|
|
break;
|
|
case PartitionKind.Skip:
|
|
WriteKeyword("Skip");
|
|
break;
|
|
case PartitionKind.SkipWhile:
|
|
WriteKeyword("Skip");
|
|
WriteKeyword("While");
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for PartitionKind");
|
|
}
|
|
|
|
partitionQueryOperator.Expression.AcceptVisitor(this, data);
|
|
|
|
return EndNode(partitionQueryOperator);
|
|
}
|
|
|
|
public object VisitOrderExpression(OrderExpression orderExpression, object data)
|
|
{
|
|
StartNode(orderExpression);
|
|
|
|
orderExpression.Expression.AcceptVisitor(this, data);
|
|
|
|
switch (orderExpression.Direction) {
|
|
case QueryOrderingDirection.None:
|
|
break;
|
|
case QueryOrderingDirection.Ascending:
|
|
WriteKeyword("Ascending");
|
|
break;
|
|
case QueryOrderingDirection.Descending:
|
|
WriteKeyword("Descending");
|
|
break;
|
|
default:
|
|
throw new Exception("Invalid value for QueryExpressionOrderingDirection");
|
|
}
|
|
|
|
return EndNode(orderExpression);
|
|
}
|
|
|
|
public object VisitOrderByQueryOperator(OrderByQueryOperator orderByQueryOperator, object data)
|
|
{
|
|
StartNode(orderByQueryOperator);
|
|
|
|
WriteKeyword("Order");
|
|
WriteKeyword("By");
|
|
WriteCommaSeparatedList(orderByQueryOperator.Expressions);
|
|
|
|
return EndNode(orderByQueryOperator);
|
|
}
|
|
|
|
public object VisitLetQueryOperator(LetQueryOperator letQueryOperator, object data)
|
|
{
|
|
StartNode(letQueryOperator);
|
|
|
|
WriteKeyword("Let");
|
|
WriteCommaSeparatedList(letQueryOperator.Variables);
|
|
|
|
return EndNode(letQueryOperator);
|
|
}
|
|
|
|
public object VisitGroupByQueryOperator(GroupByQueryOperator groupByQueryOperator, object data)
|
|
{
|
|
StartNode(groupByQueryOperator);
|
|
|
|
WriteKeyword("Group");
|
|
WriteCommaSeparatedList(groupByQueryOperator.GroupExpressions);
|
|
WriteKeyword("By");
|
|
WriteCommaSeparatedList(groupByQueryOperator.ByExpressions);
|
|
WriteKeyword("Into");
|
|
WriteCommaSeparatedList(groupByQueryOperator.IntoExpressions);
|
|
|
|
return EndNode(groupByQueryOperator);
|
|
}
|
|
|
|
public object VisitJoinQueryOperator(JoinQueryOperator joinQueryOperator, object data)
|
|
{
|
|
StartNode(joinQueryOperator);
|
|
|
|
WriteKeyword("Join");
|
|
joinQueryOperator.JoinVariable.AcceptVisitor(this, data);
|
|
if (!joinQueryOperator.SubJoinQuery.IsNull) {
|
|
joinQueryOperator.SubJoinQuery.AcceptVisitor(this, data);
|
|
}
|
|
WriteKeyword("On");
|
|
bool first = true;
|
|
foreach (var cond in joinQueryOperator.JoinConditions) {
|
|
if (first)
|
|
first = false;
|
|
else
|
|
WriteKeyword("And");
|
|
cond.AcceptVisitor(this, data);
|
|
}
|
|
|
|
return EndNode(joinQueryOperator);
|
|
}
|
|
|
|
public object VisitJoinCondition(JoinCondition joinCondition, object data)
|
|
{
|
|
StartNode(joinCondition);
|
|
|
|
joinCondition.Left.AcceptVisitor(this, data);
|
|
WriteKeyword("Equals");
|
|
joinCondition.Right.AcceptVisitor(this, data);
|
|
|
|
return EndNode(joinCondition);
|
|
}
|
|
|
|
public object VisitGroupJoinQueryOperator(GroupJoinQueryOperator groupJoinQueryOperator, object data)
|
|
{
|
|
StartNode(groupJoinQueryOperator);
|
|
|
|
WriteKeyword("Group");
|
|
WriteKeyword("Join");
|
|
groupJoinQueryOperator.JoinVariable.AcceptVisitor(this, data);
|
|
if (!groupJoinQueryOperator.SubJoinQuery.IsNull) {
|
|
groupJoinQueryOperator.SubJoinQuery.AcceptVisitor(this, data);
|
|
}
|
|
WriteKeyword("On");
|
|
bool first = true;
|
|
foreach (var cond in groupJoinQueryOperator.JoinConditions) {
|
|
if (first)
|
|
first = false;
|
|
else
|
|
WriteKeyword("And");
|
|
cond.AcceptVisitor(this, data);
|
|
}
|
|
WriteKeyword("Into");
|
|
WriteCommaSeparatedList(groupJoinQueryOperator.IntoExpressions);
|
|
|
|
return EndNode(groupJoinQueryOperator);
|
|
}
|
|
|
|
public object VisitAddRemoveHandlerStatement(AddRemoveHandlerStatement addRemoveHandlerStatement, object data)
|
|
{
|
|
StartNode(addRemoveHandlerStatement);
|
|
|
|
if (addRemoveHandlerStatement.IsAddHandler)
|
|
WriteKeyword("AddHandler");
|
|
else
|
|
WriteKeyword("RemoveHandler");
|
|
|
|
addRemoveHandlerStatement.EventExpression.AcceptVisitor(this, data);
|
|
Comma(addRemoveHandlerStatement.DelegateExpression);
|
|
addRemoveHandlerStatement.DelegateExpression.AcceptVisitor(this, data);
|
|
|
|
return EndNode(addRemoveHandlerStatement);
|
|
}
|
|
}
|
|
}
|