From 1bb5b83fd57b5c482152914524ea516b4ade192e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 29 Jun 2011 21:46:57 +0200 Subject: [PATCH] implement conversion of AsExpression to TryCast, improve conversion of string literals, add UnaryOperatorExpression --- ICSharpCode.NRefactory.VB/Ast/Enums.cs | 21 --- .../Ast/Expressions/Expression.cs | 67 +++++++ ICSharpCode.NRefactory.VB/Ast/Identifier.cs | 5 + ICSharpCode.NRefactory.VB/IAstVisitor.cs | 1 + .../OutputVisitor/OutputVisitor.cs | 23 +++ .../Visitors/CSharpToVBConverterVisitor.cs | 166 ++++++++++++++---- 6 files changed, 229 insertions(+), 54 deletions(-) diff --git a/ICSharpCode.NRefactory.VB/Ast/Enums.cs b/ICSharpCode.NRefactory.VB/Ast/Enums.cs index de56e432aa..b54c49b65a 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Enums.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Enums.cs @@ -85,27 +85,6 @@ namespace ICSharpCode.NRefactory.VB.Ast ShiftRight, } - public enum UnaryOperatorType - { - None, - Not, - BitNot, - - Minus, - Plus, - - Increment, - Decrement, - - PostIncrement, - PostDecrement, - - /// Dereferencing pointer - Dereference, - /// Get address of - AddressOf - } - public enum ContinueType { None, diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/Expression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/Expression.cs index c656b485cf..212db02c34 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Expressions/Expression.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/Expression.cs @@ -213,4 +213,71 @@ namespace ICSharpCode.NRefactory.VB.Ast return o != null && this.Target.DoMatch(o.Target, match) && this.Arguments.DoMatch(o.Arguments, match); } } + + /// + /// Operator Expression + /// + public class UnaryOperatorExpression : Expression + { + public readonly static Role OperatorRole = BinaryOperatorExpression.OperatorRole; + + public UnaryOperatorExpression() + { + } + + public UnaryOperatorExpression(UnaryOperatorType op, Expression expression) + { + this.Operator = op; + this.Expression = expression; + } + + public UnaryOperatorType Operator { + get; + set; + } + + public VBTokenNode OperatorToken { + get { return GetChildByRole (OperatorRole); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitUnaryOperatorExpression(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + UnaryOperatorExpression o = other as UnaryOperatorExpression; + return o != null && this.Operator == o.Operator && this.Expression.DoMatch(o.Expression, match); + } + + public static string GetOperatorSymbol(UnaryOperatorType op) + { + switch (op) { + case UnaryOperatorType.Not: + return "Not"; + case UnaryOperatorType.Minus: + return "-"; + case UnaryOperatorType.Plus: + return "+"; + default: + throw new NotSupportedException("Invalid value for UnaryOperatorType"); + } + } + } + + public enum UnaryOperatorType + { + /// Logical/Bitwise not (Not a) + Not, + /// Unary minus (-a) + Minus, + /// Unary plus (+a) + Plus + } } diff --git a/ICSharpCode.NRefactory.VB/Ast/Identifier.cs b/ICSharpCode.NRefactory.VB/Ast/Identifier.cs index ea308b7f9f..72f3cbdd20 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Identifier.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Identifier.cs @@ -69,6 +69,11 @@ namespace ICSharpCode.NRefactory.VB.Ast this.startLocation = location; } + public static implicit operator Identifier(string name) + { + return new Identifier(name, AstLocation.Empty); + } + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) { var node = other as Identifier; diff --git a/ICSharpCode.NRefactory.VB/IAstVisitor.cs b/ICSharpCode.NRefactory.VB/IAstVisitor.cs index 4215de42b3..bbe2331b67 100644 --- a/ICSharpCode.NRefactory.VB/IAstVisitor.cs +++ b/ICSharpCode.NRefactory.VB/IAstVisitor.cs @@ -56,6 +56,7 @@ namespace ICSharpCode.NRefactory.VB { S VisitGetXmlNamespaceExpression(GetXmlNamespaceExpression getXmlNamespaceExpression, T data); S VisitMemberAccessExpression(MemberAccessExpression memberAccessExpression, T data); S VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, T data); + S VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, T data); S VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, T data); S VisitAssignmentExpression(AssignmentExpression assignmentExpression, T data); S VisitIdentifierExpression(IdentifierExpression identifierExpression, T data); diff --git a/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs index 48d00c13aa..2632900946 100644 --- a/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs @@ -1750,5 +1750,28 @@ namespace ICSharpCode.NRefactory.VB 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; + default: + throw new Exception("Invalid value for UnaryOperatorType"); + } + + unaryOperatorExpression.Expression.AcceptVisitor(this, data); + + return EndNode(unaryOperatorExpression); + } } } diff --git a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs index 7931ee5342..b8fce019ef 100644 --- a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs +++ b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs @@ -37,6 +37,9 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitUndocumentedExpression(CSharp.UndocumentedExpression undocumentedExpression, object data) { + // 29.06.2011 20:28:36 Siegfried Pammer: wie soll ich die behandeln? + // 29.06.2011 20:28:58 Siegfried Pammer: throw new NotSupportedException(); ? + // 29.06.2011 20:35:50 Daniel Grunwald: da würde ich wieder Pseudo-Funktionen einführen throw new NotImplementedException(); } @@ -62,7 +65,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitAsExpression(CSharp.AsExpression asExpression, object data) { - throw new NotImplementedException(); + return EndNode(asExpression, new CastExpression(CastType.TryCast, (AstType)asExpression.Type.AcceptVisitor(this, data), (Expression)asExpression.Expression.AcceptVisitor(this, data))); } public AstNode VisitAssignmentExpression(CSharp.AssignmentExpression assignmentExpression, object data) @@ -80,33 +83,30 @@ 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.Any: - - 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; default: throw new Exception("Invalid value for AssignmentOperatorType: " + assignmentExpression.Operator); } @@ -242,7 +242,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitDirectionExpression(CSharp.DirectionExpression directionExpression, object data) { - throw new NotImplementedException(); + return EndNode(directionExpression, (Expression)directionExpression.Expression.AcceptVisitor(this, data)); } public AstNode VisitIdentifierExpression(CSharp.IdentifierExpression identifierExpression, object data) @@ -256,7 +256,9 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitIndexerExpression(CSharp.IndexerExpression indexerExpression, object data) { - throw new NotImplementedException(); + var expr = new InvocationExpression((Expression)indexerExpression.Target.AcceptVisitor(this, data)); + ConvertNodes(indexerExpression.Arguments, expr.Arguments); + return EndNode(indexerExpression, expr); } public AstNode VisitInvocationExpression(CSharp.InvocationExpression invocationExpression, object data) @@ -330,11 +332,52 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitPrimitiveExpression(CSharp.PrimitiveExpression primitiveExpression, object data) { - var expr = new PrimitiveExpression(primitiveExpression.Value); + Expression expr; + + if (primitiveExpression.Value is string && ((string)primitiveExpression.Value).IndexOfAny(new[] {'\r', '\n'}) > -1) + expr = ConvertToConcat((string)primitiveExpression.Value); + else + expr = new PrimitiveExpression(primitiveExpression.Value); return EndNode(primitiveExpression, expr); } + Expression ConvertToConcat(string literal) + { + Stack parts = new Stack(); + int start = 0; + + 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 (i + 1 < literal.Length && literal[i + 1] == '\n') { + i++; + parts.Push(new IdentifierExpression() { Identifier = "vbCrLf" }); + } else + parts.Push(new IdentifierExpression() { Identifier = "vbCr" }); + start = i + 1; + } else if (literal[i] == '\n') { + string part = literal.Substring(start, i - start); + parts.Push(new PrimitiveExpression(part)); + parts.Push(new IdentifierExpression() { Identifier = "vbLf" }); + start = i + 1; + } + } + + if (start < literal.Length) { + string part = literal.Substring(start); + parts.Push(new PrimitiveExpression(part)); + } + + Expression current = parts.Pop(); + + while (parts.Any()) + current = new BinaryOperatorExpression(parts.Pop(), BinaryOperatorType.Concat, current); + + return current; + } + public AstNode VisitSizeOfExpression(CSharp.SizeOfExpression sizeOfExpression, object data) { throw new NotImplementedException(); @@ -367,7 +410,59 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitUnaryOperatorExpression(CSharp.UnaryOperatorExpression unaryOperatorExpression, object data) { - throw new NotImplementedException(); + Expression expr; + + switch (unaryOperatorExpression.Operator) { + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Not: + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.BitNot: + expr = new UnaryOperatorExpression() { + Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data), + Operator = UnaryOperatorType.Not + }; + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Minus: + expr = new UnaryOperatorExpression() { + Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data), + Operator = UnaryOperatorType.Minus + }; + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Plus: + expr = new UnaryOperatorExpression() { + Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data), + Operator = UnaryOperatorType.Plus + }; + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Increment: + expr = new InvocationExpression(); + ((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "Increment" }; + ((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data)); + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.PostIncrement: + expr = new InvocationExpression(); + ((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "PostIncrement" }; + ((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data)); + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Decrement: + expr = new InvocationExpression(); + ((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "Decrement" }; + ((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data)); + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.PostDecrement: + expr = new InvocationExpression(); + ((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "PostDecrement" }; + ((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data)); + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.AddressOf: + expr = new AddressOfExpression() { + Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data) + }; + break; +// case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Dereference: + default: + throw new Exception("Invalid value for UnaryOperatorType"); + } + + return EndNode(unaryOperatorExpression, expr); } public AstNode VisitUncheckedExpression(CSharp.UncheckedExpression uncheckedExpression, object data) @@ -894,6 +989,11 @@ namespace ICSharpCode.NRefactory.VB.Visitors param.Modifiers = ConvertParamModifiers(parameterDeclaration.ParameterModifier); if ((param.Modifiers & Modifiers.None) == Modifiers.None) param.Modifiers = Modifiers.ByVal; + if ((parameterDeclaration.ParameterModifier & ICSharpCode.NRefactory.CSharp.ParameterModifier.Out) == ICSharpCode.NRefactory.CSharp.ParameterModifier.Out) { + AttributeBlock block = new AttributeBlock(); + block.Attributes.Add(new Ast.Attribute() { Type = new SimpleType("System.Runtime.InteropServices.OutAttribute") }); + param.Attributes.Add(block); + } param.Name = new Identifier(parameterDeclaration.Name, AstLocation.Empty); param.Type = (AstType)parameterDeclaration.Type.AcceptVisitor(this, data); param.OptionalValue = (Expression)parameterDeclaration.DefaultExpression.AcceptVisitor(this, data); @@ -912,7 +1012,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors case ICSharpCode.NRefactory.CSharp.ParameterModifier.Ref: return Modifiers.ByRef; case ICSharpCode.NRefactory.CSharp.ParameterModifier.Out: - return Modifiers.ByRef; // TODO verify this! + return Modifiers.ByRef; case ICSharpCode.NRefactory.CSharp.ParameterModifier.Params: return Modifiers.ParamArray; default: