From 3a26819995c78ee3fccf7f3b029c8362d0a5d8b1 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 11 May 2011 20:23:09 +0200 Subject: [PATCH] add GetTypeExpression, GetXmlNamespaceExpression, MemberAccessExpression, TypeOfIsExpression and TypeReferenceExpression --- .../Ast/Expressions/GetTypeExpression.cs | 31 ++++ .../Expressions/GetXmlNamespaceExpression.cs | 32 ++++ .../Ast/Expressions/MemberAccessExpression.cs | 42 +++++ .../Ast/Expressions/SimpleNameExpression.cs | 2 +- .../Ast/Expressions/TypeOfIsExpression.cs | 37 +++++ .../Expressions/TypeReferenceExpression.cs | 39 +++++ ICSharpCode.NRefactory.VB/IAstVisitor.cs | 5 + .../ICSharpCode.NRefactory.VB.csproj | 5 + .../OutputVisitor/OutputVisitor.cs | 149 +++++++++++++++++- .../Visitors/CSharpToVBConverterVisitor.cs | 17 +- 10 files changed, 353 insertions(+), 6 deletions(-) create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/GetTypeExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/GetXmlNamespaceExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/MemberAccessExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/TypeOfIsExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/TypeReferenceExpression.cs diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/GetTypeExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/GetTypeExpression.cs new file mode 100644 index 0000000000..ce118eb638 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/GetTypeExpression.cs @@ -0,0 +1,31 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class GetTypeExpression : Expression + { + public GetTypeExpression() + { + } + + public AstType Type { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as GetTypeExpression; + return expr != null && + Type.DoMatch(expr.Type, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitGetTypeExpression(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/GetXmlNamespaceExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/GetXmlNamespaceExpression.cs new file mode 100644 index 0000000000..07a5237384 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/GetXmlNamespaceExpression.cs @@ -0,0 +1,32 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class GetXmlNamespaceExpression : Expression + { + public GetXmlNamespaceExpression(XmlIdentifier namespaceName) + { + SetChildByRole(Roles.XmlIdentifier, namespaceName); + } + + public XmlIdentifier NamespaceName { + get { return GetChildByRole(Roles.XmlIdentifier); } + set { SetChildByRole(Roles.XmlIdentifier, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as GetXmlNamespaceExpression; + return expr != null && + NamespaceName.DoMatch(expr.NamespaceName, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitGetXmlNamespaceExpression(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/MemberAccessExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/MemberAccessExpression.cs new file mode 100644 index 0000000000..f9da04bcf8 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/MemberAccessExpression.cs @@ -0,0 +1,42 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class MemberAccessExpression : Expression + { + public MemberAccessExpression() + { + } + + public Expression Target { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public Identifier Member { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public AstNodeCollection TypeArguments { + get { return GetChildrenByRole(Roles.TypeArgument); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as MemberAccessExpression; + return expr != null && + Target.DoMatch(expr.Target, match) && + Member.DoMatch(expr.Member, match) && + TypeArguments.DoMatch(expr.TypeArguments, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitMemberAccessExpression(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/SimpleNameExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/SimpleNameExpression.cs index e3493784a2..82250a8fa3 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Expressions/SimpleNameExpression.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/SimpleNameExpression.cs @@ -13,7 +13,7 @@ namespace ICSharpCode.NRefactory.VB.Ast public Identifier Identifier { get; set; } public AstNodeCollection TypeArguments { - get { return GetChildrenByRole (Roles.TypeArgument); } + get { return GetChildrenByRole(Roles.TypeArgument); } } protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/TypeOfIsExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/TypeOfIsExpression.cs new file mode 100644 index 0000000000..a1dfa6ea5f --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/TypeOfIsExpression.cs @@ -0,0 +1,37 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class TypeOfIsExpression : Expression + { + public TypeOfIsExpression() + { + } + + public Expression TypeOfExpression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public AstType Type { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as TypeOfIsExpression; + return expr != null && + TypeOfExpression.DoMatch(expr.TypeOfExpression, match) && + Type.DoMatch(expr.Type, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitTypeOfIsExpression(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/TypeReferenceExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/TypeReferenceExpression.cs new file mode 100644 index 0000000000..cfe920d1eb --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/TypeReferenceExpression.cs @@ -0,0 +1,39 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Represents an AstType as an expression. + /// This is used when calling a method on a primitive type: "Integer.Parse()" + /// + public class TypeReferenceExpression : Expression + { + public AstType Type { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitTypeReferenceExpression(this, data); + } + + public TypeReferenceExpression () + { + } + + public TypeReferenceExpression (AstType type) + { + SetChildByRole(Roles.Type, type); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + TypeReferenceExpression o = other as TypeReferenceExpression; + return o != null && this.Type.DoMatch(o.Type, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/IAstVisitor.cs b/ICSharpCode.NRefactory.VB/IAstVisitor.cs index 5c482efa53..eba3749035 100644 --- a/ICSharpCode.NRefactory.VB/IAstVisitor.cs +++ b/ICSharpCode.NRefactory.VB/IAstVisitor.cs @@ -38,6 +38,11 @@ namespace ICSharpCode.NRefactory.VB { S VisitInstanceExpression(InstanceExpression instanceExpression, T data); S VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, T data); S VisitAddressOfExpression(AddressOfExpression addressOfExpression, T data); + S VisitGetTypeExpression(GetTypeExpression getTypeExpression, T data); + S VisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, T data); + S VisitGetXmlNamespaceExpression(GetXmlNamespaceExpression getXmlNamespaceExpression, T data); + S VisitMemberAccessExpression(MemberAccessExpression memberAccessExpression, T data); + S VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, T data); // TypeName S VisitPrimitiveType(PrimitiveType primitiveType, T data); diff --git a/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj b/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj index f6deb3479d..c2c6c1dbff 100644 --- a/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj +++ b/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj @@ -49,10 +49,15 @@ + + + + + diff --git a/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs index d498e54292..4bba92a926 100644 --- a/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs @@ -4,8 +4,11 @@ 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; @@ -261,7 +264,11 @@ namespace ICSharpCode.NRefactory.VB public object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) { - throw new NotImplementedException(); + StartNode(primitiveExpression); + + WritePrimitiveValue(primitiveExpression.Value); + + return EndNode(primitiveExpression); } public object VisitInstanceExpression(InstanceExpression instanceExpression, object data) @@ -306,6 +313,43 @@ namespace ICSharpCode.NRefactory.VB return EndNode(addressOfExpression); } + + public object VisitGetTypeExpression(GetTypeExpression getTypeExpression, object data) + { + throw new NotImplementedException(); + } + + public object VisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, object data) + { + throw new NotImplementedException(); + } + + 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.Member.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); + } + #region TypeName public object VisitPrimitiveType(PrimitiveType primitiveType, object data) { @@ -818,6 +862,109 @@ namespace ICSharpCode.NRefactory.VB WriteToken(".", AstNode.Roles.Dot); } } + + 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 } } diff --git a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs index 401bc51634..160f30ab2f 100644 --- a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs +++ b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs @@ -122,7 +122,13 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitMemberReferenceExpression(CSharp.MemberReferenceExpression memberReferenceExpression, object data) { - throw new NotImplementedException(); + var memberAccessExpression = new MemberAccessExpression(); + + memberAccessExpression.Target = (Expression)memberReferenceExpression.Target.AcceptVisitor(this, data); + memberAccessExpression.Member = new Identifier(memberReferenceExpression.MemberName, AstLocation.Empty); + ConvertNodes(memberReferenceExpression.TypeArguments, memberAccessExpression.TypeArguments); + + return EndNode(memberReferenceExpression, memberAccessExpression); } public AstNode VisitNamedArgumentExpression(CSharp.NamedArgumentExpression namedArgumentExpression, object data) @@ -161,7 +167,9 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitPrimitiveExpression(CSharp.PrimitiveExpression primitiveExpression, object data) { - throw new NotImplementedException(); + var expr = new PrimitiveExpression(primitiveExpression.Value); + + return EndNode(primitiveExpression, expr); } public AstNode VisitSizeOfExpression(CSharp.SizeOfExpression sizeOfExpression, object data) @@ -188,7 +196,8 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitTypeReferenceExpression(CSharp.TypeReferenceExpression typeReferenceExpression, object data) { - throw new NotImplementedException(); + var expr = new TypeReferenceExpression((AstType)typeReferenceExpression.Type.AcceptVisitor(this, data)); + return EndNode(typeReferenceExpression, expr); } public AstNode VisitUnaryOperatorExpression(CSharp.UnaryOperatorExpression unaryOperatorExpression, object data) @@ -263,7 +272,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors // TODO : attribute targets attr.Type = (AstType)attribute.Type.AcceptVisitor(this, data); -// ConvertNodes(attribute.Arguments, attr.Arguments); + ConvertNodes(attribute.Arguments, attr.Arguments); return EndNode(attribute, attr); }