From 3381b04961094df6ef7d9cde7f03fd5f10a30284 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 28 Jun 2011 21:51:23 +0200 Subject: [PATCH] implement ArrayCreateExpression and CastExpression --- ICSharpCode.NRefactory.VB/Ast/Enums.cs | 20 ---- .../Ast/Expressions/ArrayCreateExpression.cs | 66 +++++++++++++ .../Ast/Expressions/CastExpression.cs | 95 ++++++++++++++++++ ICSharpCode.NRefactory.VB/IAstVisitor.cs | 2 + .../ICSharpCode.NRefactory.VB.csproj | 2 + .../OutputVisitor/OutputVisitor.cs | 99 +++++++++++++++++++ .../Visitors/CSharpToVBConverterVisitor.cs | 56 ++++++++++- 7 files changed, 316 insertions(+), 24 deletions(-) create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/ArrayCreateExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/CastExpression.cs diff --git a/ICSharpCode.NRefactory.VB/Ast/Enums.cs b/ICSharpCode.NRefactory.VB/Ast/Enums.cs index bfe8af953a..de56e432aa 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Enums.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Enums.cs @@ -85,26 +85,6 @@ namespace ICSharpCode.NRefactory.VB.Ast ShiftRight, } - public enum CastType - { - /// - /// direct cast (C#, VB "DirectCast") - /// - Cast, - /// - /// try cast (C# "as", VB "TryCast") - /// - TryCast, - /// - /// converting cast (VB "CType") - /// - Conversion, - /// - /// primitive converting cast (VB "CString" etc.) - /// - PrimitiveConversion - } - public enum UnaryOperatorType { None, diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/ArrayCreateExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/ArrayCreateExpression.cs new file mode 100644 index 0000000000..544213829b --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/ArrayCreateExpression.cs @@ -0,0 +1,66 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// New Type[Dimensions] + /// + public class ArrayCreateExpression : Expression + { + public readonly static Role AdditionalArraySpecifierRole = new Role("AdditionalArraySpecifier"); + public readonly static Role InitializerRole = new Role("Initializer", ArrayInitializerExpression.Null); + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public AstNodeCollection Arguments { + get { return GetChildrenByRole (Roles.Argument); } + } + + /// + /// Gets additional array ranks (those without size info). + /// Empty for "New Integer(5,1)"; will contain a single element for "New Integer(5)()". + /// + public AstNodeCollection AdditionalArraySpecifiers { + get { return GetChildrenByRole(AdditionalArraySpecifierRole); } + } + + public ArrayInitializerExpression Initializer { + get { return GetChildByRole (InitializerRole); } + set { SetChildByRole (InitializerRole, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitArrayCreateExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ArrayCreateExpression o = other as ArrayCreateExpression; + return o != null && this.Type.DoMatch(o.Type, match) && this.Arguments.DoMatch(o.Arguments, match) && this.AdditionalArraySpecifiers.DoMatch(o.AdditionalArraySpecifiers, match) && this.Initializer.DoMatch(o.Initializer, match); + } + } + + +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/CastExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/CastExpression.cs new file mode 100644 index 0000000000..5cdbd3fa63 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/CastExpression.cs @@ -0,0 +1,95 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// CastType(Expression, AstType) + /// + public class CastExpression : Expression + { + public CastType CastType { get; set; } + + public VBTokenNode CastTypeToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CastExpression () + { + } + + public CastExpression (CastType castType, AstType castToType, Expression expression) + { + CastType = castType; + AddChild (castToType, Roles.Type); + AddChild (expression, Roles.Expression); + } + + public CastExpression (CastType castType, Expression expression) + { + CastType = castType; + AddChild (expression, Roles.Expression); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitCastExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CastExpression o = other as CastExpression; + return o != null && this.CastType == o.CastType && this.Type.DoMatch(o.Type, match) && this.Expression.DoMatch(o.Expression, match); + } + } + + public enum CastType + { + DirectCast, + TryCast, + CType, + CBool, + CByte, + CChar, + CDate, + CDec, + CDbl, + CInt, + CLng, + CObj, + CSByte, + CShort, + CSng, + CStr, + CUInt, + CULng, + CUShort + } +} diff --git a/ICSharpCode.NRefactory.VB/IAstVisitor.cs b/ICSharpCode.NRefactory.VB/IAstVisitor.cs index b403ba709e..4215de42b3 100644 --- a/ICSharpCode.NRefactory.VB/IAstVisitor.cs +++ b/ICSharpCode.NRefactory.VB/IAstVisitor.cs @@ -61,7 +61,9 @@ namespace ICSharpCode.NRefactory.VB { S VisitIdentifierExpression(IdentifierExpression identifierExpression, T data); S VisitInvocationExpression(InvocationExpression invocationExpression, T data); S VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, T data); + S VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, T data); S VisitObjectCreationExpression(ObjectCreationExpression objectCreationExpression, T data); + S VisitCastExpression(CastExpression castExpression, T data); // Statement scope S VisitLabelDeclarationStatement(LabelDeclarationStatement labelDeclarationStatement, T data); diff --git a/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj b/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj index f686043a4e..bf288e0841 100644 --- a/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj +++ b/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj @@ -49,7 +49,9 @@ + + diff --git a/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs index fefd872eb8..48d00c13aa 100644 --- a/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs @@ -1598,6 +1598,23 @@ namespace ICSharpCode.NRefactory.VB 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); + } + Space(); + WriteToken("=", ArrayCreateExpression.Roles.Assign); + Space(); + arrayCreateExpression.Initializer.AcceptVisitor(this, data); + return EndNode(arrayCreateExpression); + } + public object VisitObjectCreationExpression(ObjectCreationExpression objectCreationExpression, object data) { StartNode(objectCreationExpression); @@ -1610,6 +1627,88 @@ namespace ICSharpCode.NRefactory.VB 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); diff --git a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs index 69e5b7dace..7931ee5342 100644 --- a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs +++ b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs @@ -15,6 +15,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors string RootNamespace { get; } string GetTypeNameForAttribute(CSharp.Attribute attribute); ClassType GetClassTypeForAstType(CSharp.AstType type); + IType ResolveExpression(CSharp.Expression expression); } /// @@ -41,12 +42,22 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitArrayCreateExpression(CSharp.ArrayCreateExpression arrayCreateExpression, object data) { - throw new NotImplementedException(); + var expr = new ArrayCreateExpression() { + Type = (AstType)arrayCreateExpression.Type.AcceptVisitor(this, data), + Initializer = (ArrayInitializerExpression)arrayCreateExpression.Initializer.AcceptVisitor(this, data) + }; + ConvertNodes(arrayCreateExpression.Arguments, expr.Arguments); + ConvertNodes(arrayCreateExpression.AdditionalArraySpecifiers, expr.AdditionalArraySpecifiers); + + return EndNode(arrayCreateExpression, expr); } public AstNode VisitArrayInitializerExpression(CSharp.ArrayInitializerExpression arrayInitializerExpression, object data) { - throw new NotImplementedException(); + var expr = new ArrayInitializerExpression(); + ConvertNodes(arrayInitializerExpression.Elements, expr.Elements); + + return EndNode(arrayInitializerExpression, expr); } public AstNode VisitAsExpression(CSharp.AsExpression asExpression, object data) @@ -183,7 +194,34 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitCastExpression(CSharp.CastExpression castExpression, object data) { - throw new NotImplementedException(); + var expr = new CastExpression(); + + expr.Type = (AstType)castExpression.Type.AcceptVisitor(this, data); + // TODO read additional type information from annotation + // (int)x is equivalent to CInt(Math.Truncate(x)) + expr.CastType = GetCastType(expr.Type, null); + expr.Expression = (Expression)castExpression.Expression.AcceptVisitor(this, data); + + if (expr.CastType != CastType.CType) + expr.Type = null; + + return EndNode(castExpression, expr); + } + + CastType GetCastType(AstType type, object typeInformation) + { + var primType = type as PrimitiveType; + if (primType == null) + return CastType.CType; + + switch (primType.Keyword) { + case "Integer": + return CastType.CInt; + case "String": + return CastType.CStr; + } + + return CastType.CType; } public AstNode VisitCheckedExpression(CSharp.CheckedExpression checkedExpression, object data) @@ -712,13 +750,23 @@ namespace ICSharpCode.NRefactory.VB.Visitors ConvertNodes(constructorDeclaration.ModifierTokens, result.ModifierTokens); ConvertNodes(constructorDeclaration.Parameters, result.Parameters); result.Body = (BlockStatement)constructorDeclaration.Body.AcceptVisitor(this, data); + if (!constructorDeclaration.Initializer.IsNull) + result.Body.Statements.InsertBefore(result.Body.FirstOrDefault(), (Statement)constructorDeclaration.Initializer.AcceptVisitor(this, data)); return EndNode(constructorDeclaration, result); } public AstNode VisitConstructorInitializer(CSharp.ConstructorInitializer constructorInitializer, object data) { - throw new NotImplementedException(); + var result = new InvocationExpression( + new MemberAccessExpression() { + Target = new InstanceExpression(constructorInitializer.ConstructorInitializerType == CSharp.ConstructorInitializerType.This ? InstanceExpressionType.Me : InstanceExpressionType.MyBase, AstLocation.Empty), + Member = new Identifier("New", AstLocation.Empty) + } + ); + ConvertNodes(constructorInitializer.Arguments, result.Arguments); + + return EndNode(constructorInitializer, new ExpressionStatement(result)); } public AstNode VisitDestructorDeclaration(CSharp.DestructorDeclaration destructorDeclaration, object data)