diff --git a/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs b/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs index d3ce63aff1..f862c80ef6 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs @@ -455,47 +455,55 @@ namespace ICSharpCode.NRefactory.CSharp return VisitChildren (uncheckedExpression, data); } - /* - public virtual S VisitQueryExpressionFromClause (QueryExpressionFromClause queryExpressionFromClause, T data) + public virtual S VisitQueryExpression(QueryExpression queryExpression, T data) { - return VisitChildren (queryExpressionFromClause, data); + return VisitChildren (queryExpression, data); } - public virtual S VisitQueryExpressionWhereClause (QueryExpressionWhereClause queryExpressionWhereClause, T data) + public virtual S VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause, T data) { - return VisitChildren (queryExpressionWhereClause, data); + return VisitChildren (queryContinuationClause, data); } - public virtual S VisitQueryExpressionJoinClause (QueryExpressionJoinClause queryExpressionJoinClause, T data) + public virtual S VisitQueryFromClause(QueryFromClause queryFromClause, T data) { - return VisitChildren (queryExpressionJoinClause, data); + return VisitChildren (queryFromClause, data); } - public virtual S VisitQueryExpressionGroupClause (QueryExpressionGroupClause queryExpressionGroupClause, T data) + public virtual S VisitQueryLetClause(QueryLetClause queryLetClause, T data) { - return VisitChildren (queryExpressionGroupClause, data); + return VisitChildren (queryLetClause, data); } - public virtual S VisitQueryExpressionLetClause (QueryExpressionLetClause queryExpressionLetClause, T data) + public virtual S VisitQueryWhereClause(QueryWhereClause queryWhereClause, T data) { - return VisitChildren (queryExpressionLetClause, data); + return VisitChildren (queryWhereClause, data); } - public virtual S VisitQueryExpressionOrderClause (QueryExpressionOrderClause queryExpressionOrderClause, T data) + public virtual S VisitQueryJoinClause(QueryJoinClause queryJoinClause, T data) { - return VisitChildren (queryExpressionOrderClause, data); + return VisitChildren (queryJoinClause, data); } - public virtual S VisitQueryExpressionOrdering (QueryExpressionOrdering queryExpressionOrdering, T data) + public virtual S VisitQueryOrderClause(QueryOrderClause queryOrderClause, T data) { - return VisitChildren (queryExpressionOrdering, data); + return VisitChildren (queryOrderClause, data); } - public virtual S VisitQueryExpressionSelectClause (QueryExpressionSelectClause queryExpressionSelectClause, T data) + public virtual S VisitQueryOrdering(QueryOrdering queryOrdering, T data) { - return VisitChildren (queryExpressionSelectClause, data); + return VisitChildren (queryOrdering, data); + } + + public virtual S VisitQuerySelectClause(QuerySelectClause querySelectClause, T data) + { + return VisitChildren (querySelectClause, data); + } + + public virtual S VisitQueryGroupClause(QueryGroupClause queryGroupClause, T data) + { + return VisitChildren (queryGroupClause, data); } - */ public virtual S VisitAsExpression (AsExpression asExpression, T data) { diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs index e369ad7f91..d54e1417c4 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs @@ -1,322 +1,354 @@ -// -// QueryExpression.cs -// -// Author: -// Mike Krüger -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// -// 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. +// 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.Linq; namespace ICSharpCode.NRefactory.CSharp { - /* TODO: how do we represent clauses? is QueryExpressionFromClause an expression, - * or do we introduce a parent QueryExpression? - public class QueryExpressionFromClause : AstNode + public class QueryExpression : Expression { - public const int FromKeywordRole = 100; - public const int InKeywordRole = 101; + public static readonly Role ClauseRole = new Role("Clause"); - public AstType Type { - get { return GetChildByRole (Roles.Type); } - set { SetChildByRole (Roles.Type, value); } - } + #region Null + public new static readonly QueryExpression Null = new NullQueryExpression (); - public string Identifier { - get { - return QueryIdentifier.Name; + sealed class NullQueryExpression : QueryExpression + { + public override bool IsNull { + get { + return true; + } } - } - - public Identifier QueryIdentifier { - get { - return (Identifier)GetChildByRole (Roles.Identifier) ?? ICSharpCode.NRefactory.CSharp.Identifier.Null; + + public override S AcceptVisitor (AstVisitor visitor, T data) + { + return default (S); } } + #endregion - public AstNode Expression { - get { return GetChildByRole (Roles.Expression) ?? AstNode.Null; } + public IEnumerable Clauses { + get { return GetChildrenByRole(ClauseRole); } + set { SetChildrenByRole(ClauseRole, value); } } - public override S AcceptVisitor (AstVisitor visitor, T data) + public override S AcceptVisitor(AstVisitor visitor, T data) { - return visitor.VisitQueryExpressionFromClause (this, data); + throw new NotImplementedException(); } } - public class QueryExpressionJoinClause : QueryExpressionFromClause + public abstract class QueryClause : AstNode { - public const int OnExpressionRole = 100; - public const int EqualsExpressionRole = 101; - public const int IntoIdentifierRole = 102; - - public const int JoinKeywordRole = 110; - public new const int InKeywordRole = 111; - public const int OnKeywordRole = 112; - public const int EqualsKeywordRole = 113; - public const int IntoKeywordRole = 114; - - public CSharpTokenNode JoinKeyword { - get { return (CSharpTokenNode)GetChildByRole (JoinKeywordRole); } - } - public CSharpTokenNode InKeyword { - get { return (CSharpTokenNode)GetChildByRole (InKeywordRole); } - } - public CSharpTokenNode OnKeyword { - get { return (CSharpTokenNode)GetChildByRole (OnKeywordRole); } - } - public CSharpTokenNode EqualsKeyword { - get { return (CSharpTokenNode)GetChildByRole (EqualsKeywordRole); } - } - public CSharpTokenNode IntoKeyword { - get { return (CSharpTokenNode)GetChildByRole (IntoKeywordRole); } + public override NodeType NodeType { + get { return NodeType.QueryClause; } } + } + + /// + /// Represents a query continuation. + /// "(from .. select ..) into Identifier" or "(from .. group .. by ..) into Identifier" + /// Note that "join .. into .." is not a query continuation! + /// + /// This is always the first(!!) clause in a query expression. + /// The tree for "from a in b select c into d select e" looks like this: + /// new QueryExpression { + /// new QueryContinuationClause { + /// PrecedingQuery = new QueryExpression { + /// new QueryFromClause(a in b), + /// new QuerySelectClause(c) + /// }, + /// Identifier = d + /// }, + /// new QuerySelectClause(e) + /// } + /// + public class QueryContinuationClause : QueryClause + { + public static readonly Role PrecedingQueryRole = new Role("PrecedingQuery", QueryExpression.Null); + public static readonly Role IntoKeywordRole = Roles.Keyword; + public QueryExpression PrecedingQuery { + get { return GetChildByRole(PrecedingQueryRole); } + set { SetChildByRole(PrecedingQueryRole, value); } + } - public AstNode OnExpression { + public string Identifier { get { - return GetChildByRole (OnExpressionRole); + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); } } - public AstNode EqualsExpression { - get { - return GetChildByRole (EqualsExpressionRole); - } + public override S AcceptVisitor (AstVisitor visitor, T data) + { + return visitor.VisitQueryContinuationClause (this, data); } + } + + public class QueryFromClause : QueryClause + { + public static readonly Role FromKeywordRole = Roles.Keyword; + public static readonly Role InKeywordRole = Roles.InKeyword; - public string IntoIdentifier { - get { - return IntoIdentifierIdentifier.Name; - } + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } } - public Identifier IntoIdentifierIdentifier { + public string Identifier { get { - return (Identifier)GetChildByRole (IntoIdentifierRole); + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); } } - public AstNode InExpression { - get { - return GetChildByRole (Roles.Expression); - } + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } } public override S AcceptVisitor (AstVisitor visitor, T data) { - return visitor.VisitQueryExpressionJoinClause (this, data); + return visitor.VisitQueryFromClause (this, data); } } - public class QueryExpressionGroupClause : AstNode + public class QueryLetClause : QueryClause { - public override NodeType NodeType { + public CSharpTokenNode LetKeyword { + get { return GetChildByRole(Roles.Keyword); } + } + + public string Identifier { get { - return NodeType.Unknown; + return GetChildByRole(Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, new Identifier(value, AstLocation.Empty)); } } - public const int ProjectionExpressionRole = 100; - public const int GroupByExpressionRole = 101; - - public const int GroupKeywordRole = 102; - public const int ByKeywordRole = 103; - - public CSharpTokenNode GroupKeyword { - get { return (CSharpTokenNode)GetChildByRole (GroupKeywordRole); } + public CSharpTokenNode AssignToken { + get { return GetChildByRole(Roles.Assign); } } - public CSharpTokenNode ByKeyword { - get { return (CSharpTokenNode)GetChildByRole (ByKeywordRole); } + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - public AstNode Projection { - get { - return GetChildByRole (ProjectionExpressionRole); - } + public override S AcceptVisitor (AstVisitor visitor, T data) + { + return visitor.VisitQueryLetClause (this, data); + } + } + + + public class QueryWhereClause : QueryClause + { + public CSharpTokenNode WhereKeyword { + get { return GetChildByRole (Roles.Keyword); } } - public AstNode GroupBy { - get { - return GetChildByRole (GroupByExpressionRole); - } + public Expression Condition { + get { return GetChildByRole (Roles.Condition); } + set { SetChildByRole (Roles.Condition, value); } } public override S AcceptVisitor (AstVisitor visitor, T data) { - return visitor.VisitQueryExpressionGroupClause (this, data); + return visitor.VisitQueryWhereClause (this, data); } } - public class QueryExpressionLetClause : AstNode + /// + /// Represents a join or group join clause. + /// + public class QueryJoinClause : QueryClause { - public override NodeType NodeType { - get { - return NodeType.Unknown; - } + public static readonly Role JoinKeywordRole = Roles.Keyword; + public static readonly Role TypeRole = Roles.Type; + public static readonly Role JoinIdentifierRole = Roles.Identifier; + public static readonly Role InKeywordRole = Roles.InKeyword; + public static readonly Role InExpressionRole = Roles.Expression; + public static readonly Role OnKeywordRole = new Role("OnKeyword", CSharpTokenNode.Null); + public static readonly Role OnExpressionRole = new Role("OnExpression", Expression.Null); + public static readonly Role EqualsKeywordRole = new Role("EqualsKeyword", CSharpTokenNode.Null); + public static readonly Role EqualsExpressionRole = new Role("EqualsExpression", Expression.Null); + public static readonly Role IntoKeywordRole = new Role("IntoKeyword", CSharpTokenNode.Null); + public static readonly Role IntoIdentifierRole = new Role("IntoIdentifier", Identifier.Null); + + public bool IsGroupJoin { + get { return !string.IsNullOrEmpty(this.IntoIdentifier); } } - public string Identifier { - get { - return QueryIdentifier.Name; - } + public CSharpTokenNode JoinKeyword { + get { return GetChildByRole (JoinKeywordRole); } } - public Identifier QueryIdentifier { - get { - return (Identifier)GetChildByRole (Roles.Identifier); - } + public AstType Type { + get { return GetChildByRole (TypeRole); } + set { SetChildByRole (TypeRole, value); } } - public AstNode Expression { + public string JoinIdentifier { get { - return GetChildByRole (Roles.Expression); + return GetChildByRole(JoinIdentifierRole).Name; + } + set { + SetChildByRole(JoinIdentifierRole, new Identifier(value, AstLocation.Empty)); } } - public CSharpTokenNode LetKeyword { - get { return (CSharpTokenNode)GetChildByRole (Roles.Keyword); } + public CSharpTokenNode InKeyword { + get { return GetChildByRole (InKeywordRole); } } - public AstNode Assign { - get { - return GetChildByRole (Roles.Assign); - } + public Expression InExpression { + get { return GetChildByRole (InExpressionRole); } + set { SetChildByRole (InExpressionRole, value); } } - public override S AcceptVisitor (AstVisitor visitor, T data) - { - return visitor.VisitQueryExpressionLetClause (this, data); + public CSharpTokenNode OnKeyword { + get { return GetChildByRole (OnKeywordRole); } } - } - - public class QueryExpressionOrderClause : AstNode - { - public const int OrderingRole = 100; - public override NodeType NodeType { - get { - return NodeType.Unknown; - } + public Expression OnExpression { + get { return GetChildByRole (OnExpressionRole); } + set { SetChildByRole (OnExpressionRole, value); } } - public bool OrderAscending { - get; - set; + public CSharpTokenNode EqualsKeyword { + get { return GetChildByRole (EqualsKeywordRole); } + } + + public Expression EqualsExpression { + get { return GetChildByRole (EqualsExpressionRole); } + set { SetChildByRole (EqualsExpressionRole, value); } + } + + public CSharpTokenNode IntoKeyword { + get { return GetChildByRole (IntoKeywordRole); } } - public AstNode Expression { + public string IntoIdentifier { get { - return GetChildByRole (Roles.Expression); + return GetChildByRole (IntoIdentifierRole).Name; + } + set { + SetChildByRole(IntoIdentifierRole, new Identifier(value, AstLocation.Empty)); } } + public override S AcceptVisitor (AstVisitor visitor, T data) + { + return visitor.VisitQueryJoinClause (this, data); + } + } + + public class QueryOrderClause : QueryClause + { + public static readonly Role OrderingRole = new Role("Ordering"); + public CSharpTokenNode Keyword { - get { return (CSharpTokenNode)GetChildByRole (Roles.Keyword); } + get { return GetChildByRole (Roles.Keyword); } + } + + public IEnumerable Orderings { + get { return GetChildrenByRole (OrderingRole); } + set { SetChildrenByRole (OrderingRole, value); } } public override S AcceptVisitor (AstVisitor visitor, T data) { - return visitor.VisitQueryExpressionOrderClause (this, data); + return visitor.VisitQueryOrderClause (this, data); } } - public class QueryExpressionOrdering : AstNode + public class QueryOrdering : AstNode { public override NodeType NodeType { - get { - return NodeType.Unknown; - } + get { return NodeType.Unknown; } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } } - public QueryExpressionOrderingDirection Direction { + public QueryOrderingDirection Direction { get; set; } - public AstNode Criteria { - get { - return GetChildByRole (Roles.Expression); - } + public CSharpTokenNode DirectionToken { + get { return GetChildByRole (Roles.Keyword); } } public override S AcceptVisitor (AstVisitor visitor, T data) { - return visitor.VisitQueryExpressionOrdering (this, data); + return visitor.VisitQueryOrdering (this, data); } } - public enum QueryExpressionOrderingDirection + public enum QueryOrderingDirection { - Unknown, + None, Ascending, Descending } - public class QueryExpressionSelectClause : AstNode + public class QuerySelectClause : QueryClause { - public override NodeType NodeType { - get { - return NodeType.Unknown; - } - } - public CSharpTokenNode SelectKeyword { - get { return (CSharpTokenNode)GetChildByRole (Roles.Keyword); } + get { return GetChildByRole (Roles.Keyword); } } - public AstNode Projection { - get { - return GetChildByRole (Roles.Expression); - } + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } } public override S AcceptVisitor (AstVisitor visitor, T data) { - return visitor.VisitQueryExpressionSelectClause (this, data); + return visitor.VisitQuerySelectClause (this, data); } } - public class QueryExpressionWhereClause : AstNode + public class QueryGroupClause : QueryClause { - public override NodeType NodeType { - get { - return NodeType.Unknown; - } + public static readonly Role GroupKeywordRole = Roles.Keyword; + public static readonly Role ProjectionRole = new Role("Projection", Expression.Null); + public static readonly Role ByKeywordRole = new Role("ByKeyword", CSharpTokenNode.Null); + public static readonly Role KeyRole = new Role("Key", Expression.Null); + + public CSharpTokenNode GroupKeyword { + get { return GetChildByRole (GroupKeywordRole); } } - public CSharpTokenNode WhereKeyword { - get { return (CSharpTokenNode)GetChildByRole (Roles.Keyword); } + public Expression Projection { + get { return GetChildByRole (ProjectionRole); } + set { SetChildByRole (ProjectionRole, value); } } - public AstNode Condition { - get { - return GetChildByRole (Roles.Condition); - } + public CSharpTokenNode ByKeyword { + get { return GetChildByRole (ByKeywordRole); } + } + + public Expression Key { + get { return GetChildByRole (KeyRole); } + set { SetChildByRole (KeyRole, value); } } public override S AcceptVisitor (AstVisitor visitor, T data) { - return visitor.VisitQueryExpressionWhereClause (this, data); + return visitor.VisitQueryGroupClause (this, data); } - } - */ } \ No newline at end of file diff --git a/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs b/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs index af5ec4477d..e61922a881 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs @@ -42,6 +42,17 @@ namespace ICSharpCode.NRefactory.CSharp S VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, T data); S VisitUncheckedExpression(UncheckedExpression uncheckedExpression, T data); + S VisitQueryExpression(QueryExpression queryExpression, T data); + S VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause, T data); + S VisitQueryFromClause(QueryFromClause queryFromClause, T data); + S VisitQueryLetClause(QueryLetClause queryLetClause, T data); + S VisitQueryWhereClause(QueryWhereClause queryWhereClause, T data); + S VisitQueryJoinClause(QueryJoinClause queryJoinClause, T data); + S VisitQueryOrderClause(QueryOrderClause queryOrderClause, T data); + S VisitQueryOrdering(QueryOrdering queryOrdering, T data); + S VisitQuerySelectClause(QuerySelectClause querySelectClause, T data); + S VisitQueryGroupClause(QueryGroupClause queryGroupClause, T data); + S VisitAttribute(Attribute attribute, T data); S VisitAttributeSection(AttributeSection attributeSection, T data); S VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, T data); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/NodeType.cs b/ICSharpCode.NRefactory/CSharp/Ast/NodeType.cs index f17e41f424..d5d56fb4ca 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/NodeType.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/NodeType.cs @@ -42,7 +42,8 @@ namespace ICSharpCode.NRefactory.CSharp Member, Statement, Expression, - Token + Token, + QueryClause } } diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index ed189899a7..51f75d75f1 100644 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -914,6 +914,143 @@ namespace ICSharpCode.NRefactory.CSharp } #endregion + #region Query Expressions + public object VisitQueryExpression(QueryExpression queryExpression, object data) + { + StartNode(queryExpression); + bool first = true; + foreach (var clause in queryExpression.Clauses) { + if (first) { + first = false; + } else { + NewLine(); + } + clause.AcceptVisitor(this, data); + } + return EndNode(queryExpression); + } + + public object VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause, object data) + { + StartNode(queryContinuationClause); + queryContinuationClause.PrecedingQuery.AcceptVisitor(this, data); + Space(); + WriteKeyword("into", QueryContinuationClause.IntoKeywordRole); + Space(); + WriteIdentifier(queryContinuationClause.Identifier); + return EndNode(queryContinuationClause); + } + + public object VisitQueryFromClause(QueryFromClause queryFromClause, object data) + { + StartNode(queryFromClause); + WriteKeyword("from", QueryFromClause.FromKeywordRole); + queryFromClause.Type.AcceptVisitor(this, data); + Space(); + WriteIdentifier(queryFromClause.Identifier); + WriteKeyword("in", QueryFromClause.InKeywordRole); + queryFromClause.Expression.AcceptVisitor(this, data); + return EndNode(queryFromClause); + } + + public object VisitQueryLetClause(QueryLetClause queryLetClause, object data) + { + StartNode(queryLetClause); + WriteKeyword("let"); + Space(); + WriteIdentifier(queryLetClause.Identifier); + Space(policy.AroundAssignmentParentheses); + WriteToken("=", QueryLetClause.Roles.Assign); + Space(policy.AroundAssignmentParentheses); + queryLetClause.Expression.AcceptVisitor(this, data); + return EndNode(queryLetClause); + } + + public object VisitQueryWhereClause(QueryWhereClause queryWhereClause, object data) + { + StartNode(queryWhereClause); + WriteKeyword("where"); + Space(); + queryWhereClause.Condition.AcceptVisitor(this, data); + return EndNode(queryWhereClause); + } + + public object VisitQueryJoinClause(QueryJoinClause queryJoinClause, object data) + { + StartNode(queryJoinClause); + WriteKeyword("join", QueryJoinClause.JoinKeywordRole); + queryJoinClause.Type.AcceptVisitor(this, data); + Space(); + WriteIdentifier(queryJoinClause.JoinIdentifier, QueryJoinClause.JoinIdentifierRole); + Space(); + WriteKeyword("in", QueryJoinClause.InKeywordRole); + Space(); + queryJoinClause.InExpression.AcceptVisitor(this, data); + Space(); + WriteKeyword("on", QueryJoinClause.OnKeywordRole); + Space(); + queryJoinClause.OnExpression.AcceptVisitor(this, data); + Space(); + WriteKeyword("equals", QueryJoinClause.EqualsKeywordRole); + Space(); + queryJoinClause.EqualsExpression.AcceptVisitor(this, data); + if (queryJoinClause.IsGroupJoin) { + Space(); + WriteKeyword("into", QueryJoinClause.IntoKeywordRole); + WriteIdentifier(queryJoinClause.IntoIdentifier, QueryJoinClause.IntoIdentifierRole); + } + return EndNode(queryJoinClause); + } + + public object VisitQueryOrderClause(QueryOrderClause queryOrderClause, object data) + { + StartNode(queryOrderClause); + WriteKeyword("orderby"); + Space(); + WriteCommaSeparatedList(queryOrderClause.Orderings); + return EndNode(queryOrderClause); + } + + public object VisitQueryOrdering(QueryOrdering queryOrdering, object data) + { + StartNode(queryOrdering); + queryOrdering.Expression.AcceptVisitor(this, data); + switch (queryOrdering.Direction) { + case QueryOrderingDirection.Ascending: + Space(); + WriteKeyword("ascending"); + break; + case QueryOrderingDirection.Descending: + Space(); + WriteKeyword("descending"); + break; + } + return EndNode(queryOrdering); + } + + public object VisitQuerySelectClause(QuerySelectClause querySelectClause, object data) + { + StartNode(querySelectClause); + WriteKeyword("select"); + Space(); + querySelectClause.Expression.AcceptVisitor(this, data); + return EndNode(querySelectClause); + } + + public object VisitQueryGroupClause(QueryGroupClause queryGroupClause, object data) + { + StartNode(queryGroupClause); + WriteKeyword("group", QueryGroupClause.GroupKeywordRole); + Space(); + queryGroupClause.Projection.AcceptVisitor(this, data); + Space(); + WriteKeyword("by", QueryGroupClause.ByKeywordRole); + Space(); + queryGroupClause.Key.AcceptVisitor(this, data); + return EndNode(queryGroupClause); + } + #endregion + #region GeneralScope public object VisitAttribute(Attribute attribute, object data) {