diff --git a/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/SelectStatement.cs b/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/SelectStatement.cs index 21de4c435..70f2dd720 100644 --- a/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/SelectStatement.cs +++ b/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/SelectStatement.cs @@ -32,14 +32,116 @@ namespace ICSharpCode.NRefactory.VB.Ast { public static readonly Role CaseStatementRole = new Role("CaseStatement"); + public AstNodeCollection Clauses { + get { return GetChildrenByRole(CaseClause.CaseClauseRole); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitCaseStatement(this, data); + } + } + + public abstract class CaseClause : AstNode + { + #region Null + public new static readonly CaseClause Null = new NullCaseClause(); + + sealed class NullCaseClause : CaseClause + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + public static readonly Role CaseClauseRole = new Role("CaseClause", CaseClause.Null); + + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + } + + public class SimpleCaseClause : CaseClause + { + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitSimpleCaseClause(this, data); + } + } + + public class RangeCaseClause : CaseClause + { + public static readonly Role ToExpressionRole = ForStatement.ToExpressionRole; + + public Expression ToExpression { + get { return GetChildByRole(ToExpressionRole); } + set { SetChildByRole(ToExpressionRole, value); } + } + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) { throw new NotImplementedException(); } public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitRangeCaseClause(this, data); + } + } + + public class ComparisonCaseClause : CaseClause + { + public static readonly Role OperatorRole = BinaryOperatorExpression.OperatorRole; + + public ComparisonOperator Operator { get; set; } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) { throw new NotImplementedException(); } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitComparisonCaseClause(this, data); + } + } + + public enum ComparisonOperator + { + Equality = BinaryOperatorType.Equality, + InEquality = BinaryOperatorType.InEquality, + LessThan = BinaryOperatorType.LessThan, + GreaterThan = BinaryOperatorType.GreaterThan, + LessThanOrEqual = BinaryOperatorType.LessThanOrEqual, + GreaterThanOrEqual = BinaryOperatorType.GreaterThanOrEqual } } diff --git a/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/Statement.cs b/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/Statement.cs index c20407051..5b2a55bbb 100644 --- a/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/Statement.cs +++ b/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/Statement.cs @@ -115,18 +115,18 @@ namespace ICSharpCode.NRefactory.VB.Ast } // Make debugging easier by giving Statements a ToString() implementation - public override string ToString() - { -// if (IsNull) -// return "Null"; -// StringWriter w = new StringWriter(); -// AcceptVisitor(new OutputVisitor(w, new CSharpFormattingOptions()), null); -// string text = w.ToString().TrimEnd().Replace("\t", "").Replace(w.NewLine, " "); -// if (text.Length > 100) -// return text.Substring(0, 97) + "..."; -// else -// return text; - throw new NotImplementedException(); - } +// public override string ToString() +// { +//// if (IsNull) +//// return "Null"; +//// StringWriter w = new StringWriter(); +//// AcceptVisitor(new OutputVisitor(w, new CSharpFormattingOptions()), null); +//// string text = w.ToString().TrimEnd().Replace("\t", "").Replace(w.NewLine, " "); +//// if (text.Length > 100) +//// return text.Substring(0, 97) + "..."; +//// else +//// return text; +// throw new NotImplementedException(); +// } } } diff --git a/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeMembers/FieldDeclaration.cs b/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeMembers/FieldDeclaration.cs index e9679da63..06cf639d9 100644 --- a/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeMembers/FieldDeclaration.cs +++ b/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeMembers/FieldDeclaration.cs @@ -32,7 +32,30 @@ namespace ICSharpCode.NRefactory.VB.Ast /// public class VariableIdentifier : AstNode { - public static readonly Role VariableIdentifierRole = new Role("VariableIdentifier"); + #region Null + public new static readonly VariableIdentifier Null = new NullVariableIdentifier(); + + sealed class NullVariableIdentifier : VariableIdentifier + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + public static readonly Role VariableIdentifierRole = new Role("VariableIdentifier", VariableIdentifier.Null); public Identifier Name { get { return GetChildByRole(Roles.Identifier); } diff --git a/NRefactory/ICSharpCode.NRefactory.VB/IAstVisitor.cs b/NRefactory/ICSharpCode.NRefactory.VB/IAstVisitor.cs index 3a4ed8673..ed4ddb06f 100644 --- a/NRefactory/ICSharpCode.NRefactory.VB/IAstVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory.VB/IAstVisitor.cs @@ -97,5 +97,9 @@ namespace ICSharpCode.NRefactory.VB { S VisitSimpleType(SimpleType simpleType, T data); S VisitVariableInitializer(VariableInitializer variableInitializer, T data); + S VisitRangeCaseClause(RangeCaseClause rangeCaseClause, T data); + S VisitComparisonCaseClause(ComparisonCaseClause comparisonCaseClause, T data); + S VisitSimpleCaseClause(SimpleCaseClause simpleCaseClause, T data); + S VisitCaseStatement(CaseStatement caseStatement, T data); } } diff --git a/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs index f85a48cb7..cf0d7310e 100644 --- a/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs @@ -2064,9 +2064,89 @@ namespace ICSharpCode.NRefactory.VB public object VisitSelectStatement(SelectStatement selectStatement, object data) { - throw new NotImplementedException(); + 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 + WriteCommaSeparatedList(caseStatement.Clauses); + NewLine(); + Indent(); + caseStatement.Body.AcceptVisitor(this, data); + Unindent(); + + 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); diff --git a/NRefactory/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs b/NRefactory/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs index 35569db9c..2de473059 100644 --- a/NRefactory/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs @@ -77,6 +77,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors { var left = (Expression)assignmentExpression.Left.AcceptVisitor(this, data); var op = AssignmentOperatorType.None; + var right = (Expression)assignmentExpression.Right.AcceptVisitor(this, data); switch (assignmentExpression.Operator) { case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Assign: @@ -88,36 +89,38 @@ namespace ICSharpCode.NRefactory.VB.Visitors case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Subtract: op = AssignmentOperatorType.Subtract; break; -// case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Multiply: -// -// break; -// case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Divide: -// -// break; -// case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Modulus: -// -// break; -// case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ShiftLeft: -// -// break; -// case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ShiftRight: -// -// break; -// case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.BitwiseAnd: -// -// break; -// case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.BitwiseOr: -// -// break; -// case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ExclusiveOr: -// -// break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Multiply: + op = AssignmentOperatorType.Multiply; + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Divide: + op = AssignmentOperatorType.Divide; + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Modulus: + op = AssignmentOperatorType.Assign; + right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.Modulus, right); + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ShiftLeft: + op = AssignmentOperatorType.ShiftLeft; + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ShiftRight: + op = AssignmentOperatorType.ShiftRight; + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.BitwiseAnd: + op = AssignmentOperatorType.Assign; + right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.BitwiseAnd, right); + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.BitwiseOr: + op = AssignmentOperatorType.Assign; + right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.BitwiseOr, right); + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ExclusiveOr: + op = AssignmentOperatorType.Assign; + right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.ExclusiveOr, right); + break; default: throw new Exception("Invalid value for AssignmentOperatorType: " + assignmentExpression.Operator); } - var right = (Expression)assignmentExpression.Right.AcceptVisitor(this, data); - var expr = new AssignmentExpression(left, op, right); return EndNode(assignmentExpression, expr); } @@ -222,10 +225,38 @@ namespace ICSharpCode.NRefactory.VB.Visitors return CastType.CType; switch (primType.Keyword) { + case "Boolean": + return CastType.CBool; + case "Byte": + return CastType.CByte; + case "Char": + return CastType.CChar; + case "Date": + return CastType.CDate; + case "Double": + return CastType.CDbl; + case "Decimal": + return CastType.CDec; case "Integer": return CastType.CInt; + case "Long": + return CastType.CLng; + case "Object": + return CastType.CObj; + case "SByte": + return CastType.CSByte; + case "Short": + return CastType.CShort; + case "Single": + return CastType.CSng; case "String": return CastType.CStr; + case "UInteger": + return CastType.CUInt; + case "ULong": + return CastType.CULng; + case "UShort": + return CastType.CUShort; } return CastType.CType; @@ -367,8 +398,8 @@ namespace ICSharpCode.NRefactory.VB.Visitors { Expression expr; - if (primitiveExpression.Value is string && ((string)primitiveExpression.Value).IndexOfAny(new[] {'\r', '\n'}) > -1) - expr = ConvertToConcat((string)primitiveExpression.Value); + if ((primitiveExpression.Value is string || primitiveExpression.Value is char) && primitiveExpression.Value.ToString().IndexOfAny(new[] {'\r', '\n'}) > -1) + expr = ConvertToConcat(primitiveExpression.Value.ToString()); else expr = new PrimitiveExpression(primitiveExpression.Value); @@ -383,7 +414,8 @@ namespace ICSharpCode.NRefactory.VB.Visitors for (int i = 0; i < literal.Length; i++) { if (literal[i] == '\r') { string part = literal.Substring(start, i - start); - parts.Push(new PrimitiveExpression(part)); + if (!string.IsNullOrEmpty(part)) + parts.Push(new PrimitiveExpression(part)); if (i + 1 < literal.Length && literal[i + 1] == '\n') { i++; parts.Push(new IdentifierExpression() { Identifier = "vbCrLf" }); @@ -392,9 +424,16 @@ namespace ICSharpCode.NRefactory.VB.Visitors start = i + 1; } else if (literal[i] == '\n') { string part = literal.Substring(start, i - start); - parts.Push(new PrimitiveExpression(part)); + if (!string.IsNullOrEmpty(part)) + parts.Push(new PrimitiveExpression(part)); parts.Push(new IdentifierExpression() { Identifier = "vbLf" }); start = i + 1; + } else if (literal[i] == '\t') { + string part = literal.Substring(start, i - start); + if (!string.IsNullOrEmpty(part)) + parts.Push(new PrimitiveExpression(part)); + parts.Push(new IdentifierExpression() { Identifier = "vbTab" }); + start = i + 1; } } @@ -850,17 +889,30 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitSwitchStatement(CSharp.SwitchStatement switchStatement, object data) { - throw new NotImplementedException(); + var stmt = new SelectStatement() { Expression = (Expression)switchStatement.Expression.AcceptVisitor(this, data) }; + ConvertNodes(switchStatement.SwitchSections, stmt.Cases); + + return EndNode(switchStatement, stmt); } public AstNode VisitSwitchSection(CSharp.SwitchSection switchSection, object data) { - throw new NotImplementedException(); + var caseStmt = new CaseStatement(); + ConvertNodes(switchSection.CaseLabels, caseStmt.Clauses); + if (switchSection.Statements.Count == 1 && switchSection.Statements.FirstOrDefault() is CSharp.BlockStatement) + caseStmt.Body = (BlockStatement)switchSection.Statements.FirstOrDefault().AcceptVisitor(this, data); + else { + caseStmt.Body = new BlockStatement(); + ConvertNodes(switchSection.Statements, caseStmt.Body.Statements); + } + if (caseStmt.Body.LastOrDefault() is ExitStatement && ((ExitStatement)caseStmt.Body.LastOrDefault()).ExitKind == ExitKind.Select) + caseStmt.Body.LastOrDefault().Remove(); + return EndNode(switchSection, caseStmt); } public AstNode VisitCaseLabel(CSharp.CaseLabel caseLabel, object data) { - throw new NotImplementedException(); + return EndNode(caseLabel, new SimpleCaseClause() { Expression = (Expression)caseLabel.Expression.AcceptVisitor(this, data) }); } public AstNode VisitThrowStatement(CSharp.ThrowStatement throwStatement, object data)