// 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; using ICSharpCode.NRefactory.PatternMatching; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.VB.Ast; namespace ICSharpCode.NRefactory.VB.Visitors { public interface IEnvironmentProvider { string RootNamespace { get; } string GetTypeNameForAttribute(CSharp.Attribute attribute); TypeKind GetTypeKindForAstType(CSharp.AstType type); TypeCode ResolveExpression(CSharp.Expression expression); bool? IsReferenceType(CSharp.Expression expression); //ITypeResolveContext ResolveContext { get; } IType ResolveType(AstType type, TypeDeclaration entity = null); bool IsMethodGroup(CSharp.Expression expression); bool HasEvent(Expression expression); CSharp.ParameterDeclaration[] GetParametersForProperty(CSharp.PropertyDeclaration property); } /// /// Description of CSharpToVBConverterVisitor. /// public class CSharpToVBConverterVisitor : CSharp.IAstVisitor { IEnvironmentProvider provider; Stack blocks; Stack types; Stack members; class MemberInfo { public bool inIterator; } public CSharpToVBConverterVisitor(IEnvironmentProvider provider) { this.provider = provider; this.blocks = new Stack(); this.types = new Stack(); this.members = new Stack(); } public AstNode VisitAnonymousMethodExpression(CSharp.AnonymousMethodExpression anonymousMethodExpression, object data) { members.Push(new MemberInfo()); var expr = new MultiLineLambdaExpression() { IsSub = true, Body = (BlockStatement)anonymousMethodExpression.Body.AcceptVisitor(this, data) }; ConvertNodes(anonymousMethodExpression.Parameters, expr.Parameters); if (members.Pop().inIterator) { expr.Modifiers |= LambdaExpressionModifiers.Iterator; } return EndNode(anonymousMethodExpression, expr); } public AstNode VisitUndocumentedExpression(CSharp.UndocumentedExpression undocumentedExpression, object data) { var invocation = new InvocationExpression(); switch (undocumentedExpression.UndocumentedExpressionType) { case CSharp.UndocumentedExpressionType.ArgListAccess: case CSharp.UndocumentedExpressionType.ArgList: invocation.Target = new IdentifierExpression { Identifier = "__ArgList" }; break; case CSharp.UndocumentedExpressionType.RefValue: invocation.Target = new IdentifierExpression { Identifier = "__RefValue" }; break; case CSharp.UndocumentedExpressionType.RefType: invocation.Target = new IdentifierExpression { Identifier = "__RefType" }; break; case CSharp.UndocumentedExpressionType.MakeRef: invocation.Target = new IdentifierExpression { Identifier = "__MakeRef" }; break; default: throw new Exception("Invalid value for UndocumentedExpressionType"); } ConvertNodes(undocumentedExpression.Arguments, invocation.Arguments); return EndNode(undocumentedExpression, invocation); } public AstNode VisitArrayCreateExpression(CSharp.ArrayCreateExpression arrayCreateExpression, object data) { var expr = new ArrayCreateExpression() { Type = (AstType)arrayCreateExpression.Type.AcceptVisitor(this, data), Initializer = (ArrayInitializerExpression)arrayCreateExpression.Initializer.AcceptVisitor(this, data) }; ConvertNodes(arrayCreateExpression.Arguments, expr.Arguments, ReduceArrayUpperBoundExpression); ConvertNodes(arrayCreateExpression.AdditionalArraySpecifiers, expr.AdditionalArraySpecifiers); return EndNode(arrayCreateExpression, expr); } Expression ReduceArrayUpperBoundExpression(Expression expression) { if (expression is PrimitiveExpression) { var numericLiteral = expression as PrimitiveExpression; int? upperBound = numericLiteral.Value as int?; if (upperBound.HasValue) return new PrimitiveExpression(upperBound.Value - 1); } return new BinaryOperatorExpression(expression, BinaryOperatorType.Subtract, new PrimitiveExpression(1)); } public AstNode VisitArrayInitializerExpression(CSharp.ArrayInitializerExpression arrayInitializerExpression, object data) { var expr = new ArrayInitializerExpression(); ConvertNodes(arrayInitializerExpression.Elements, expr.Elements); return EndNode(arrayInitializerExpression, expr); } public AstNode VisitAsExpression(CSharp.AsExpression asExpression, object data) { 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) { var left = (Expression)assignmentExpression.Left.AcceptVisitor(this, data); var op = AssignmentOperatorType.None; var right = (Expression)assignmentExpression.Right.AcceptVisitor(this, data); switch (assignmentExpression.Operator) { case CSharp.AssignmentOperatorType.Assign: op = AssignmentOperatorType.Assign; break; case CSharp.AssignmentOperatorType.Add: if (provider.HasEvent(left)) { var addHandler = new AddRemoveHandlerStatement { IsAddHandler = true }; addHandler.EventExpression = left; addHandler.DelegateExpression = right; return EndNode(assignmentExpression, addHandler); } op = AssignmentOperatorType.Add; break; case CSharp.AssignmentOperatorType.Subtract: if (provider.HasEvent(left)) { var addHandler = new AddRemoveHandlerStatement { IsAddHandler = false }; addHandler.EventExpression = left; addHandler.DelegateExpression = right; return EndNode(assignmentExpression, addHandler); } op = AssignmentOperatorType.Subtract; break; case CSharp.AssignmentOperatorType.Multiply: op = AssignmentOperatorType.Multiply; break; case CSharp.AssignmentOperatorType.Divide: op = AssignmentOperatorType.Divide; break; case CSharp.AssignmentOperatorType.Modulus: op = AssignmentOperatorType.Assign; right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.Modulus, right); break; case CSharp.AssignmentOperatorType.ShiftLeft: op = AssignmentOperatorType.ShiftLeft; break; case CSharp.AssignmentOperatorType.ShiftRight: op = AssignmentOperatorType.ShiftRight; break; case CSharp.AssignmentOperatorType.BitwiseAnd: op = AssignmentOperatorType.Assign; right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.BitwiseAnd, right); break; case CSharp.AssignmentOperatorType.BitwiseOr: op = AssignmentOperatorType.Assign; right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.BitwiseOr, right); break; case 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 expr = new AssignmentExpression(left, op, right); return EndNode(assignmentExpression, expr); } public AstNode VisitBaseReferenceExpression(CSharp.BaseReferenceExpression baseReferenceExpression, object data) { InstanceExpression result = new InstanceExpression(InstanceExpressionType.MyBase, baseReferenceExpression.StartLocation); return EndNode(baseReferenceExpression, result); } public AstNode VisitBinaryOperatorExpression(CSharp.BinaryOperatorExpression binaryOperatorExpression, object data) { var left = (Expression)binaryOperatorExpression.Left.AcceptVisitor(this, data); var op = BinaryOperatorType.None; var right = (Expression)binaryOperatorExpression.Right.AcceptVisitor(this, data); switch (binaryOperatorExpression.Operator) { case CSharp.BinaryOperatorType.BitwiseAnd: op = BinaryOperatorType.BitwiseAnd; break; case CSharp.BinaryOperatorType.BitwiseOr: op = BinaryOperatorType.BitwiseOr; break; case CSharp.BinaryOperatorType.ConditionalAnd: op = BinaryOperatorType.LogicalAnd; break; case CSharp.BinaryOperatorType.ConditionalOr: op = BinaryOperatorType.LogicalOr; break; case CSharp.BinaryOperatorType.ExclusiveOr: op = BinaryOperatorType.ExclusiveOr; break; case CSharp.BinaryOperatorType.GreaterThan: op = BinaryOperatorType.GreaterThan; break; case CSharp.BinaryOperatorType.GreaterThanOrEqual: op = BinaryOperatorType.GreaterThanOrEqual; break; case CSharp.BinaryOperatorType.Equality: if (IsReferentialEquality(binaryOperatorExpression)) op = BinaryOperatorType.ReferenceEquality; else op = BinaryOperatorType.Equality; break; case CSharp.BinaryOperatorType.InEquality: if (IsReferentialEquality(binaryOperatorExpression)) op = BinaryOperatorType.ReferenceInequality; else op = BinaryOperatorType.InEquality; break; case CSharp.BinaryOperatorType.LessThan: op = BinaryOperatorType.LessThan; break; case CSharp.BinaryOperatorType.LessThanOrEqual: op = BinaryOperatorType.LessThanOrEqual; break; case CSharp.BinaryOperatorType.Add: // TODO might be string concatenation op = BinaryOperatorType.Add; break; case CSharp.BinaryOperatorType.Subtract: op = BinaryOperatorType.Subtract; break; case CSharp.BinaryOperatorType.Multiply: op = BinaryOperatorType.Multiply; break; case CSharp.BinaryOperatorType.Divide: op = BinaryOperatorType.Divide; break; case CSharp.BinaryOperatorType.Modulus: op = BinaryOperatorType.Modulus; break; case CSharp.BinaryOperatorType.ShiftLeft: op = BinaryOperatorType.ShiftLeft; break; case CSharp.BinaryOperatorType.ShiftRight: op = BinaryOperatorType.ShiftRight; break; case CSharp.BinaryOperatorType.NullCoalescing: var nullCoalescing = new ConditionalExpression { ConditionExpression = left, FalseExpression = right }; return EndNode(binaryOperatorExpression, nullCoalescing); default: throw new Exception("Invalid value for BinaryOperatorType: " + binaryOperatorExpression.Operator); } return EndNode(binaryOperatorExpression, new BinaryOperatorExpression(left, op, right)); } bool IsReferentialEquality(CSharp.BinaryOperatorExpression binaryOperatorExpression) { var left = provider.IsReferenceType(binaryOperatorExpression.Left); var right = provider.IsReferenceType(binaryOperatorExpression.Right); var leftCode = provider.ResolveExpression(binaryOperatorExpression.Left); var rightCode = provider.ResolveExpression(binaryOperatorExpression.Right); return (left == true || right == true) && (leftCode != TypeCode.String && rightCode != TypeCode.String); } public AstNode VisitCastExpression(CSharp.CastExpression castExpression, object data) { 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 "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; } public AstNode VisitCheckedExpression(CSharp.CheckedExpression checkedExpression, object data) { blocks.Peek().AddChild(new Comment(" The following expression was wrapped in a checked-expression", false), AstNode.Roles.Comment); return EndNode(checkedExpression, checkedExpression.Expression.AcceptVisitor(this, data)); } public AstNode VisitConditionalExpression(CSharp.ConditionalExpression conditionalExpression, object data) { var cond = new ConditionalExpression() { ConditionExpression = (Expression)conditionalExpression.Condition.AcceptVisitor(this, data), TrueExpression = (Expression)conditionalExpression.TrueExpression.AcceptVisitor(this, data), FalseExpression = (Expression)conditionalExpression.FalseExpression.AcceptVisitor(this, data) }; return EndNode(conditionalExpression, cond); } public AstNode VisitDefaultValueExpression(CSharp.DefaultValueExpression defaultValueExpression, object data) { // Nothing is equivalent to default(T) for reference and value types. return EndNode(defaultValueExpression, new PrimitiveExpression(null)); } public AstNode VisitDirectionExpression(CSharp.DirectionExpression directionExpression, object data) { return EndNode(directionExpression, (Expression)directionExpression.Expression.AcceptVisitor(this, data)); } public AstNode VisitIdentifierExpression(CSharp.IdentifierExpression identifierExpression, object data) { var expr = new IdentifierExpression(); expr.Identifier = new Identifier(identifierExpression.Identifier, TextLocation.Empty); ConvertNodes(identifierExpression.TypeArguments, expr.TypeArguments); if (provider.IsMethodGroup(identifierExpression)) { return EndNode(identifierExpression, new UnaryOperatorExpression(UnaryOperatorType.AddressOf, expr)); } return EndNode(identifierExpression, expr); } public AstNode VisitIndexerExpression(CSharp.IndexerExpression indexerExpression, object data) { 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) { var expr = new InvocationExpression((Expression)invocationExpression.Target.AcceptVisitor(this, data)); ConvertNodes(invocationExpression.Arguments, expr.Arguments); return EndNode(invocationExpression, expr); } public AstNode VisitIsExpression(CSharp.IsExpression isExpression, object data) { var expr = new TypeOfIsExpression() { Type = (AstType)isExpression.Type.AcceptVisitor(this, data), TypeOfExpression = (Expression)isExpression.Expression.AcceptVisitor(this, data) }; return EndNode(isExpression, expr); } public AstNode VisitLambdaExpression(CSharp.LambdaExpression lambdaExpression, object data) { LambdaExpression expr = null; if (lambdaExpression.Body is CSharp.Expression) { var singleLine = new SingleLineFunctionLambdaExpression() { EmbeddedExpression = (Expression)lambdaExpression.Body.AcceptVisitor(this, data) }; ConvertNodes(lambdaExpression.Parameters, singleLine.Parameters); expr = singleLine; } else throw new NotImplementedException(); return EndNode(lambdaExpression, expr); } public AstNode VisitMemberReferenceExpression(CSharp.MemberReferenceExpression memberReferenceExpression, object data) { var memberAccessExpression = new MemberAccessExpression(); memberAccessExpression.Target = (Expression)memberReferenceExpression.Target.AcceptVisitor(this, data); memberAccessExpression.MemberName = new Identifier(memberReferenceExpression.MemberName, TextLocation.Empty); ConvertNodes(memberReferenceExpression.TypeArguments, memberAccessExpression.TypeArguments); if (provider.IsMethodGroup(memberReferenceExpression)) { return EndNode(memberReferenceExpression, new UnaryOperatorExpression(UnaryOperatorType.AddressOf, memberAccessExpression)); } return EndNode(memberReferenceExpression, memberAccessExpression); } public AstNode VisitNamedArgumentExpression(CSharp.NamedArgumentExpression namedArgumentExpression, object data) { Expression expr = new NamedArgumentExpression { Identifier = namedArgumentExpression.Name, Expression = (Expression)namedArgumentExpression.Expression.AcceptVisitor(this, data) }; return EndNode(namedArgumentExpression, expr); } public AstNode VisitNamedExpression(CSharp.NamedExpression namedExpression, object data) { Expression expr = new FieldInitializerExpression { IsKey = true, Identifier = namedExpression.Name, Expression = (Expression)namedExpression.Expression.AcceptVisitor(this, data) }; return EndNode(namedExpression, expr); } public AstNode VisitNullReferenceExpression(CSharp.NullReferenceExpression nullReferenceExpression, object data) { return EndNode(nullReferenceExpression, new PrimitiveExpression(null)); } public AstNode VisitObjectCreateExpression(CSharp.ObjectCreateExpression objectCreateExpression, object data) { var expr = new ObjectCreationExpression((AstType)objectCreateExpression.Type.AcceptVisitor(this, data)); ConvertNodes(objectCreateExpression.Arguments, expr.Arguments); var arg1 = expr.Arguments.FirstOrDefault() as UnaryOperatorExpression; if (arg1 != null && arg1.Operator == UnaryOperatorType.AddressOf) { arg1.Remove(); return EndNode(objectCreateExpression, arg1); } if (!objectCreateExpression.Initializer.IsNull) expr.Initializer = (ArrayInitializerExpression)objectCreateExpression.Initializer.AcceptVisitor(this, data); return EndNode(objectCreateExpression, expr); } public AstNode VisitAnonymousTypeCreateExpression(CSharp.AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) { var expr = new AnonymousObjectCreationExpression(); ConvertNodes(anonymousTypeCreateExpression.Initializers, expr.Initializer); return EndNode(anonymousTypeCreateExpression, expr); } public AstNode VisitParenthesizedExpression(CSharp.ParenthesizedExpression parenthesizedExpression, object data) { var result = new ParenthesizedExpression(); result.Expression = (Expression)parenthesizedExpression.Expression.AcceptVisitor(this, data); return EndNode(parenthesizedExpression, result); } public AstNode VisitPointerReferenceExpression(CSharp.PointerReferenceExpression pointerReferenceExpression, object data) { return EndNode(pointerReferenceExpression,((Expression)pointerReferenceExpression.Target.AcceptVisitor(this, data)).Invoke("Dereference").Member(pointerReferenceExpression.MemberName)); } public AstNode VisitPrimitiveExpression(CSharp.PrimitiveExpression primitiveExpression, object data) { Expression expr; if (!string.IsNullOrEmpty(primitiveExpression.Value as string)) expr = ConvertToConcat(primitiveExpression.Value.ToString()); else if (primitiveExpression.Value is char) expr = ConvertToSpecialChar((char)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++) { string part; switch (literal[i]) { case '\0': case '\b': case '\f': case '\n': case '\t': case '\v': part = literal.Substring(start, i - start); if (!string.IsNullOrEmpty(part)) parts.Push(new PrimitiveExpression(part)); parts.Push(ConvertToSpecialChar(literal[i])); start = i + 1; break; case '\r': part = literal.Substring(start, i - start); if (!string.IsNullOrEmpty(part)) parts.Push(new PrimitiveExpression(part)); if (i + 1 < literal.Length && literal[i + 1] == '\n') { i++; parts.Push(new IdentifierExpression("vbCrLf")); } else parts.Push(new IdentifierExpression("vbCr")); start = i + 1; break; default: if ((int)literal[i] > 255) { part = literal.Substring(start, i - start); if (!string.IsNullOrEmpty(part)) parts.Push(new PrimitiveExpression(part)); parts.Push(new InvocationExpression(new IdentifierExpression("ChrW"), new PrimitiveExpression((int)literal[i]))); } else continue; start = i + 1; break; } } 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; } Expression ConvertToSpecialChar(char ch) { switch (ch) { case '\0': return new IdentifierExpression("vbNullChar"); case '\b': return new IdentifierExpression("vbBack"); case '\f': return new IdentifierExpression("vbFormFeed"); case '\r': return new IdentifierExpression("vbCr"); case '\n': return new IdentifierExpression("vbLf"); case '\t': return new IdentifierExpression("vbTab"); case '\v': return new IdentifierExpression("vbVerticalTab"); default: if (ch > 255) return new InvocationExpression(new IdentifierExpression("ChrW"), new PrimitiveExpression((int)ch)); return new PrimitiveExpression(ch); } } public AstNode VisitSizeOfExpression(CSharp.SizeOfExpression sizeOfExpression, object data) { return EndNode( sizeOfExpression, new InvocationExpression( new IdentifierExpression() { Identifier = "__SizeOf" }, new TypeReferenceExpression((AstType)sizeOfExpression.Type.AcceptVisitor(this, data)) ) ); } public AstNode VisitStackAllocExpression(CSharp.StackAllocExpression stackAllocExpression, object data) { return EndNode( stackAllocExpression, new InvocationExpression( new IdentifierExpression() { Identifier = "__StackAlloc" }, new TypeReferenceExpression((AstType)stackAllocExpression.Type.AcceptVisitor(this, data)), (Expression)stackAllocExpression.CountExpression.AcceptVisitor(this, data) ) ); } public AstNode VisitThisReferenceExpression(CSharp.ThisReferenceExpression thisReferenceExpression, object data) { InstanceExpression result = new InstanceExpression(InstanceExpressionType.Me, thisReferenceExpression.StartLocation); return EndNode(thisReferenceExpression, result); } public AstNode VisitTypeOfExpression(CSharp.TypeOfExpression typeOfExpression, object data) { var expr = new GetTypeExpression(); expr.Type = (AstType)typeOfExpression.Type.AcceptVisitor(this, data); return EndNode(typeOfExpression, expr); } public AstNode VisitTypeReferenceExpression(CSharp.TypeReferenceExpression typeReferenceExpression, object data) { var expr = new TypeReferenceExpression((AstType)typeReferenceExpression.Type.AcceptVisitor(this, data)); return EndNode(typeReferenceExpression, expr); } public AstNode VisitUnaryOperatorExpression(CSharp.UnaryOperatorExpression unaryOperatorExpression, object data) { Expression expr; switch (unaryOperatorExpression.Operator) { case CSharp.UnaryOperatorType.Not: case CSharp.UnaryOperatorType.BitNot: expr = new UnaryOperatorExpression() { Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data), Operator = UnaryOperatorType.Not }; break; case CSharp.UnaryOperatorType.Minus: expr = new UnaryOperatorExpression() { Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data), Operator = UnaryOperatorType.Minus }; break; case CSharp.UnaryOperatorType.Plus: expr = new UnaryOperatorExpression() { Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data), Operator = UnaryOperatorType.Plus }; break; case 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 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 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 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 CSharp.UnaryOperatorType.AddressOf: expr = new UnaryOperatorExpression() { Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data), Operator = UnaryOperatorType.AddressOf }; break; case CSharp.UnaryOperatorType.Dereference: expr = new InvocationExpression(); ((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__Dereference" }; ((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data)); break; case CSharp.UnaryOperatorType.Await: expr = new UnaryOperatorExpression() { Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data), Operator = UnaryOperatorType.Await }; break; default: throw new Exception("Invalid value for UnaryOperatorType"); } return EndNode(unaryOperatorExpression, expr); } public AstNode VisitUncheckedExpression(CSharp.UncheckedExpression uncheckedExpression, object data) { blocks.Peek().AddChild(new Comment(" The following expression was wrapped in a unchecked-expression", false), AstNode.Roles.Comment); return EndNode(uncheckedExpression, uncheckedExpression.Expression.AcceptVisitor(this, data)); } public AstNode VisitQueryExpression(CSharp.QueryExpression queryExpression, object data) { var expr = new QueryExpression(); ConvertNodes(queryExpression.Clauses, expr.QueryOperators); return EndNode(queryExpression, expr); } public AstNode VisitQueryContinuationClause(CSharp.QueryContinuationClause queryContinuationClause, object data) { throw new NotImplementedException(); } public AstNode VisitQueryFromClause(CSharp.QueryFromClause queryFromClause, object data) { var op = new FromQueryOperator(); op.Variables.Add( new CollectionRangeVariableDeclaration { Identifier = new VariableIdentifier { Name = queryFromClause.Identifier }, Type = (AstType)queryFromClause.Type.AcceptVisitor(this, data), Expression = (Expression)queryFromClause.Expression.AcceptVisitor(this, data) } ); return EndNode(queryFromClause, op); } public AstNode VisitQueryLetClause(CSharp.QueryLetClause queryLetClause, object data) { throw new NotImplementedException(); } public AstNode VisitQueryWhereClause(CSharp.QueryWhereClause queryWhereClause, object data) { throw new NotImplementedException(); } public AstNode VisitQueryJoinClause(CSharp.QueryJoinClause queryJoinClause, object data) { throw new NotImplementedException(); } public AstNode VisitQueryOrderClause(CSharp.QueryOrderClause queryOrderClause, object data) { var op = new OrderByQueryOperator(); ConvertNodes(queryOrderClause.Orderings, op.Expressions); return EndNode(queryOrderClause, op); } public AstNode VisitQueryOrdering(CSharp.QueryOrdering queryOrdering, object data) { var expr = new OrderExpression(); expr.Direction = (QueryOrderingDirection)queryOrdering.Direction; expr.Expression = (Expression)queryOrdering.Expression.AcceptVisitor(this, data); return EndNode(queryOrdering, expr); } int selectVarCount = 0; public AstNode VisitQuerySelectClause(CSharp.QuerySelectClause querySelectClause, object data) { var op = new SelectQueryOperator(); op.Variables.Add( new VariableInitializer { Identifier = new VariableIdentifier { Name = "SelectVar" + selectVarCount }, Expression = (Expression)querySelectClause.Expression.AcceptVisitor(this, data) }); return EndNode(querySelectClause, op); } public AstNode VisitQueryGroupClause(CSharp.QueryGroupClause queryGroupClause, object data) { var op = new GroupByQueryOperator(); throw new NotImplementedException(); //return EndNode(queryGroupClause, op); } public AstNode VisitAttribute(CSharp.Attribute attribute, object data) { var attr = new VB.Ast.Attribute(); AttributeTarget target; Enum.TryParse(((CSharp.AttributeSection)attribute.Parent).AttributeTarget, true, out target); attr.Target = target; attr.Type = (AstType)attribute.Type.AcceptVisitor(this, data); ConvertNodes(attribute.Arguments, attr.Arguments); return EndNode(attribute, attr); } public AstNode VisitAttributeSection(CSharp.AttributeSection attributeSection, object data) { AttributeBlock block = new AttributeBlock(); ConvertNodes(attributeSection.Attributes, block.Attributes); return EndNode(attributeSection, block); } public AstNode VisitDelegateDeclaration(CSharp.DelegateDeclaration delegateDeclaration, object data) { var result = new DelegateDeclaration(); ConvertNodes(delegateDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), result.Attributes); ConvertNodes(delegateDeclaration.ModifierTokens, result.ModifierTokens); result.Name = new Identifier(delegateDeclaration.Name, TextLocation.Empty); result.IsSub = IsSub(delegateDeclaration.ReturnType); ConvertNodes(delegateDeclaration.Parameters, result.Parameters); ConvertNodes(delegateDeclaration.TypeParameters, result.TypeParameters); ConvertNodes(delegateDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), result.ReturnTypeAttributes); if (!result.IsSub) result.ReturnType = (AstType)delegateDeclaration.ReturnType.AcceptVisitor(this, data); return EndNode(delegateDeclaration, result); } public AstNode VisitNamespaceDeclaration(CSharp.NamespaceDeclaration namespaceDeclaration, object data) { var newNamespace = new NamespaceDeclaration(); foreach (string id in namespaceDeclaration.Identifiers) { newNamespace.Identifiers.Add(new Identifier(id, TextLocation.Empty)); } ConvertMembers(namespaceDeclaration, newNamespace, CSharp.NamespaceDeclaration.MemberRole, NamespaceDeclaration.MemberRole); return EndNode(namespaceDeclaration, newNamespace); } public AstNode VisitTypeDeclaration(CSharp.TypeDeclaration typeDeclaration, object data) { // TODO add missing features! if (typeDeclaration.ClassType == CSharp.ClassType.Enum) { var type = new EnumDeclaration(); CopyAnnotations(typeDeclaration, type); ConvertNodes(typeDeclaration.Attributes, type.Attributes); ConvertNodes(typeDeclaration.ModifierTokens, type.ModifierTokens); if (typeDeclaration.BaseTypes.Any()) { var first = typeDeclaration.BaseTypes.First(); type.UnderlyingType = (AstType)first.AcceptVisitor(this, data); } type.Name = new Identifier(typeDeclaration.Name, TextLocation.Empty); ConvertMembers(typeDeclaration, type, CSharp.Roles.TypeMemberRole, EnumDeclaration.MemberRole); return EndNode(typeDeclaration, type); } else { var type = new TypeDeclaration(); CopyAnnotations(typeDeclaration, type); CSharp.Attribute stdModAttr; if (typeDeclaration.ClassType == CSharp.ClassType.Class && HasAttribute(typeDeclaration.Attributes, "Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute", out stdModAttr)) { type.ClassType = ClassType.Module; // remove AttributeSection if only one attribute is present var attrSec = (CSharp.AttributeSection)stdModAttr.Parent; if (attrSec.Attributes.Count == 1) attrSec.Remove(); else stdModAttr.Remove(); } else { switch (typeDeclaration.ClassType) { case CSharp.ClassType.Class: type.ClassType = ClassType.Class; break; case CSharp.ClassType.Struct: type.ClassType = ClassType.Struct; break; case CSharp.ClassType.Interface: type.ClassType = ClassType.Interface; break; default: throw new InvalidOperationException("Invalid value for ClassType"); } } if ((typeDeclaration.Modifiers & CSharp.Modifiers.Static) == CSharp.Modifiers.Static) { type.ClassType = ClassType.Module; typeDeclaration.Modifiers &= ~CSharp.Modifiers.Static; } ConvertNodes(typeDeclaration.Attributes, type.Attributes); ConvertNodes(typeDeclaration.ModifierTokens, type.ModifierTokens); ConvertNodes(typeDeclaration.TypeParameters, type.TypeParameters); if (typeDeclaration.BaseTypes.Any()) { var first = typeDeclaration.BaseTypes.First(); if (provider.GetTypeKindForAstType(first) != TypeKind.Interface) { ConvertNodes(typeDeclaration.BaseTypes.Skip(1), type.ImplementsTypes); type.InheritsType = (AstType)first.AcceptVisitor(this, data); } else ConvertNodes(typeDeclaration.BaseTypes, type.ImplementsTypes); } type.Name = typeDeclaration.Name; types.Push(type); ConvertMembers(typeDeclaration, type, CSharp.Roles.TypeMemberRole, TypeDeclaration.MemberRole); types.Pop(); return EndNode(typeDeclaration, type); } } public AstNode VisitUsingAliasDeclaration(CSharp.UsingAliasDeclaration usingAliasDeclaration, object data) { var imports = new ImportsStatement(); var clause = new AliasImportsClause() { Name = new Identifier(usingAliasDeclaration.Alias, TextLocation.Empty), Alias = (AstType)usingAliasDeclaration.Import.AcceptVisitor(this, data) }; imports.AddChild(clause, ImportsStatement.ImportsClauseRole); return EndNode(usingAliasDeclaration, imports); } public AstNode VisitUsingDeclaration(CSharp.UsingDeclaration usingDeclaration, object data) { var imports = new ImportsStatement(); var clause = new MemberImportsClause() { Member = (AstType)usingDeclaration.Import.AcceptVisitor(this, data) }; imports.AddChild(clause, ImportsStatement.ImportsClauseRole); return EndNode(usingDeclaration, imports); } public AstNode VisitExternAliasDeclaration(CSharp.ExternAliasDeclaration externAliasDeclaration, object data) { throw new NotImplementedException(); } public AstNode VisitBlockStatement(CSharp.BlockStatement blockStatement, object data) { var block = new BlockStatement(); blocks.Push(block); ConvertNodes(blockStatement, block.Statements); blocks.Pop(); return EndNode(blockStatement, block); } public AstNode VisitBreakStatement(CSharp.BreakStatement breakStatement, object data) { var exit = new ExitStatement(ExitKind.None); foreach (var stmt in breakStatement.Ancestors) { if (stmt is CSharp.MethodDeclaration) { exit.ExitKind = IsSub(((CSharp.MethodDeclaration)stmt).ReturnType) ? ExitKind.Sub : ExitKind.Function; break; } if (stmt is CSharp.PropertyDeclaration) { exit.ExitKind = ExitKind.Property; break; } if (stmt is CSharp.DoWhileStatement) { exit.ExitKind = ExitKind.Do; break; } if (stmt is CSharp.ForStatement || stmt is CSharp.ForeachStatement) { exit.ExitKind = ExitKind.For; break; } if (stmt is CSharp.WhileStatement) { exit.ExitKind = ExitKind.While; break; } if (stmt is CSharp.SwitchStatement) { exit.ExitKind = ExitKind.Select; break; } if (stmt is CSharp.TryCatchStatement) { exit.ExitKind = ExitKind.Try; break; } } return EndNode(breakStatement, exit); } public AstNode VisitCheckedStatement(CSharp.CheckedStatement checkedStatement, object data) { blocks.Peek().AddChild(new Comment(" The following expression was wrapped in a checked-statement", false), AstNode.Roles.Comment); var body = (BlockStatement)checkedStatement.Body.AcceptVisitor(this, data); foreach (var stmt in body) { stmt.Remove(); blocks.Peek().Add(stmt); } return EndNode(checkedStatement, null); } public AstNode VisitContinueStatement(CSharp.ContinueStatement continueStatement, object data) { var @continue = new ContinueStatement(ContinueKind.None); foreach (var stmt in continueStatement.Ancestors) { if (stmt is CSharp.DoWhileStatement) { @continue.ContinueKind = ContinueKind.Do; break; } if (stmt is CSharp.ForStatement || stmt is CSharp.ForeachStatement) { @continue.ContinueKind = ContinueKind.For; break; } if (stmt is CSharp.WhileStatement) { @continue.ContinueKind = ContinueKind.While; break; } } return EndNode(continueStatement, @continue); } public AstNode VisitDoWhileStatement(CSharp.DoWhileStatement doWhileStatement, object data) { var stmt = new DoLoopStatement(); stmt.ConditionType = ConditionType.LoopWhile; stmt.Expression = (Expression)doWhileStatement.Condition.AcceptVisitor(this, data); stmt.Body = (BlockStatement)doWhileStatement.EmbeddedStatement.AcceptVisitor(this, data); return EndNode(doWhileStatement, stmt); } public AstNode VisitEmptyStatement(CSharp.EmptyStatement emptyStatement, object data) { return EndNode(emptyStatement, null); } public AstNode VisitExpressionStatement(CSharp.ExpressionStatement expressionStatement, object data) { var node = expressionStatement.Expression.AcceptVisitor(this, data); if (node is Expression) node = new ExpressionStatement((Expression)node); return EndNode(expressionStatement, node); } public AstNode VisitFixedStatement(CSharp.FixedStatement fixedStatement, object data) { var block = blocks.Peek(); block.AddChild(new Comment(" Emulating fixed-Statement, might not be entirely correct!", false), AstNode.Roles.Comment); var variables = new LocalDeclarationStatement(); variables.Modifiers = Modifiers.Dim; var stmt = new TryStatement(); stmt.FinallyBlock = new BlockStatement(); foreach (var decl in fixedStatement.Variables) { var v = new VariableDeclaratorWithTypeAndInitializer { Identifiers = { new VariableIdentifier { Name = decl.Name } }, Type = new SimpleType("GCHandle"), Initializer = new InvocationExpression( new MemberAccessExpression { Target = new IdentifierExpression { Identifier = "GCHandle" }, MemberName = "Alloc" }, (Expression)decl.Initializer.AcceptVisitor(this, data), new MemberAccessExpression { Target = new IdentifierExpression { Identifier = "GCHandleType" }, MemberName = "Pinned" } ) }; variables.Variables.Add(v); stmt.FinallyBlock.Add(new IdentifierExpression { Identifier = decl.Name }.Invoke("Free")); } block.Add(variables); stmt.Body = (BlockStatement)fixedStatement.EmbeddedStatement.AcceptVisitor(this, data); foreach (var ident in stmt.Body.Descendants.OfType()) { ident.ReplaceWith(expr => ((Expression)expr).Invoke("AddrOfPinnedObject")); } return EndNode(fixedStatement, stmt); } public AstNode VisitForeachStatement(CSharp.ForeachStatement foreachStatement, object data) { var stmt = new ForEachStatement() { Body = (BlockStatement)foreachStatement.EmbeddedStatement.AcceptVisitor(this, data), InExpression = (Expression)foreachStatement.InExpression.AcceptVisitor(this, data), Variable = new VariableInitializer() { Identifier = new VariableIdentifier() { Name = foreachStatement.VariableName }, Type = (AstType)foreachStatement.VariableType.AcceptVisitor(this, data) } }; return EndNode(foreachStatement, stmt); } public AstNode VisitForStatement(CSharp.ForStatement forStatement, object data) { // for (;;) ; if (!forStatement.Initializers.Any() && forStatement.Condition.IsNull && !forStatement.Iterators.Any()) return EndNode(forStatement, new WhileStatement() { Condition = new PrimitiveExpression(true), Body = (BlockStatement)forStatement.EmbeddedStatement.AcceptVisitor(this, data) }); CSharp.AstNode counterLoop = new CSharp.ForStatement() { Initializers = { new NamedNode( "iteratorVar", new Choice { new CSharp.VariableDeclarationStatement { Type = new Choice { new CSharp.PrimitiveType("long"), new CSharp.PrimitiveType("ulong"), new CSharp.PrimitiveType("int"), new CSharp.PrimitiveType("uint"), new CSharp.PrimitiveType("short"), new CSharp.PrimitiveType("ushort"), new CSharp.PrimitiveType("sbyte"), new CSharp.PrimitiveType("byte") }, Variables = { new AnyNode() } }, new CSharp.ExpressionStatement( new CSharp.AssignmentExpression() ) }) }, Condition = new NamedNode( "condition", new CSharp.BinaryOperatorExpression { Left = new NamedNode("ident", new CSharp.IdentifierExpression(Pattern.AnyString)), Operator = CSharp.BinaryOperatorType.Any, Right = new AnyNode("endExpr") }), Iterators = { new CSharp.ExpressionStatement( new NamedNode( "increment", new CSharp.AssignmentExpression { Left = new Backreference("ident"), Operator = CSharp.AssignmentOperatorType.Any, Right = new NamedNode("factor", new AnyNode()) } ) ) }, EmbeddedStatement = new NamedNode("body", new AnyNode()) }; var match = counterLoop.Match(forStatement); if (match.Success) { var init = match.Get("iteratorVar").SingleOrDefault(); AstNode iteratorVariable; if (init is CSharp.VariableDeclarationStatement) { var var = ((CSharp.VariableDeclarationStatement)init).Variables.First(); iteratorVariable = new VariableInitializer() { Identifier = new VariableIdentifier { Name = var.Name }, Type = (AstType)((CSharp.VariableDeclarationStatement)init).Type.AcceptVisitor(this, data), Expression = (Expression)var.Initializer.AcceptVisitor(this, data) }; } else if (init is CSharp.ExpressionStatement) { iteratorVariable = init.AcceptVisitor(this, data); } else goto end; Expression toExpr = Expression.Null; var cond = match.Get("condition").SingleOrDefault(); var endExpr = (Expression)match.Get("endExpr").SingleOrDefault().AcceptVisitor(this, data); if (cond.Operator == CSharp.BinaryOperatorType.LessThanOrEqual || cond.Operator == CSharp.BinaryOperatorType.GreaterThanOrEqual) { toExpr = endExpr; } if (cond.Operator == CSharp.BinaryOperatorType.LessThan) toExpr = new BinaryOperatorExpression(endExpr, BinaryOperatorType.Subtract, new PrimitiveExpression(1)); if (cond.Operator == CSharp.BinaryOperatorType.GreaterThan) toExpr = new BinaryOperatorExpression(endExpr, BinaryOperatorType.Add, new PrimitiveExpression(1)); Expression stepExpr = Expression.Null; var increment = match.Get("increment").SingleOrDefault(); var factorExpr = (Expression)match.Get("factor").SingleOrDefault().AcceptVisitor(this, data); if (increment.Operator == CSharp.AssignmentOperatorType.Add && (factorExpr is PrimitiveExpression && !IsEqual(((PrimitiveExpression)factorExpr).Value, 1))) stepExpr = factorExpr; if (increment.Operator == CSharp.AssignmentOperatorType.Subtract) stepExpr = new UnaryOperatorExpression(UnaryOperatorType.Minus, factorExpr); return new ForStatement() { Variable = iteratorVariable, ToExpression = toExpr, StepExpression = stepExpr, Body = (BlockStatement)match.Get("body").Single().AcceptVisitor(this, data) }; } end: var stmt = new WhileStatement() { Condition = (Expression)forStatement.Condition.AcceptVisitor(this, data), Body = (BlockStatement)forStatement.EmbeddedStatement.AcceptVisitor(this, data) }; ConvertNodes(forStatement.Iterators, stmt.Body.Statements); foreach (var initializer in forStatement.Initializers) blocks.Peek().Statements.Add((Statement)initializer.AcceptVisitor(this, data)); return EndNode(forStatement, stmt); } bool IsEqual(object value, int num) { if (value is byte) return (byte)value == num; if (value is sbyte) return (sbyte)value == num; if (value is short) return (short)value == num; if (value is ushort) return (ushort)value == num; if (value is int) return (int)value == num; if (value is uint) return (uint)value == num; if (value is long) return (long)value == num; if (value is ulong) return (ulong)value == (ulong)num; throw new InvalidCastException(); } public AstNode VisitGotoCaseStatement(CSharp.GotoCaseStatement gotoCaseStatement, object data) { throw new NotImplementedException(); } public AstNode VisitGotoDefaultStatement(CSharp.GotoDefaultStatement gotoDefaultStatement, object data) { throw new NotImplementedException(); } public AstNode VisitGotoStatement(CSharp.GotoStatement gotoStatement, object data) { return EndNode(gotoStatement, new GoToStatement() { Label = new IdentifierExpression() { Identifier = gotoStatement.Label } }); } public AstNode VisitIfElseStatement(CSharp.IfElseStatement ifElseStatement, object data) { var stmt = new IfElseStatement(); stmt.Condition = (Expression)ifElseStatement.Condition.AcceptVisitor(this, data); stmt.Body = (Statement)ifElseStatement.TrueStatement.AcceptVisitor(this, data); stmt.ElseBlock = (Statement)ifElseStatement.FalseStatement.AcceptVisitor(this, data); return EndNode(ifElseStatement, stmt); } public AstNode VisitLabelStatement(CSharp.LabelStatement labelStatement, object data) { return EndNode(labelStatement, new LabelDeclarationStatement() { Label = new IdentifierExpression() { Identifier = labelStatement.Label } }); } public AstNode VisitLockStatement(CSharp.LockStatement lockStatement, object data) { var stmt = new SyncLockStatement(); stmt.Expression = (Expression)lockStatement.Expression.AcceptVisitor(this, data); stmt.Body = (BlockStatement)lockStatement.EmbeddedStatement.AcceptVisitor(this, data); return EndNode(lockStatement, stmt); } public AstNode VisitReturnStatement(CSharp.ReturnStatement returnStatement, object data) { var stmt = new ReturnStatement((Expression)returnStatement.Expression.AcceptVisitor(this, data)); return EndNode(returnStatement, stmt); } public AstNode VisitSwitchStatement(CSharp.SwitchStatement switchStatement, object data) { 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) { 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) { return EndNode(caseLabel, new SimpleCaseClause() { Expression = (Expression)caseLabel.Expression.AcceptVisitor(this, data) }); } public AstNode VisitThrowStatement(CSharp.ThrowStatement throwStatement, object data) { return EndNode(throwStatement, new ThrowStatement((Expression)throwStatement.Expression.AcceptVisitor(this, data))); } public AstNode VisitTryCatchStatement(CSharp.TryCatchStatement tryCatchStatement, object data) { var stmt = new TryStatement(); stmt.Body = (BlockStatement)tryCatchStatement.TryBlock.AcceptVisitor(this, data); stmt.FinallyBlock = (BlockStatement)tryCatchStatement.FinallyBlock.AcceptVisitor(this, data); ConvertNodes(tryCatchStatement.CatchClauses, stmt.CatchBlocks); return EndNode(tryCatchStatement, stmt); } public AstNode VisitCatchClause(CSharp.CatchClause catchClause, object data) { var clause = new CatchBlock(); clause.ExceptionType = (AstType)catchClause.Type.AcceptVisitor(this, data); clause.ExceptionVariable = catchClause.VariableName; ConvertNodes(catchClause.Body.Statements, clause.Statements); return EndNode(catchClause, clause); } public AstNode VisitUncheckedStatement(CSharp.UncheckedStatement uncheckedStatement, object data) { throw new NotImplementedException(); } public AstNode VisitUnsafeStatement(CSharp.UnsafeStatement unsafeStatement, object data) { throw new NotImplementedException(); } public AstNode VisitUsingStatement(CSharp.UsingStatement usingStatement, object data) { var stmt = new UsingStatement(); stmt.Resources.Add(usingStatement.ResourceAcquisition.AcceptVisitor(this, data)); stmt.Body = (BlockStatement)usingStatement.EmbeddedStatement.AcceptVisitor(this, data); return EndNode(usingStatement, stmt); } public AstNode VisitVariableDeclarationStatement(CSharp.VariableDeclarationStatement variableDeclarationStatement, object data) { var decl = new LocalDeclarationStatement(); decl.Modifiers = Modifiers.Dim; ConvertNodes(variableDeclarationStatement.Variables, decl.Variables); return EndNode(variableDeclarationStatement, decl); } public AstNode VisitWhileStatement(CSharp.WhileStatement whileStatement, object data) { var stmt = new WhileStatement() { Condition = (Expression)whileStatement.Condition.AcceptVisitor(this, data), Body = (BlockStatement)whileStatement.EmbeddedStatement.AcceptVisitor(this, data) }; return EndNode(whileStatement, stmt); } public AstNode VisitYieldBreakStatement(CSharp.YieldBreakStatement yieldBreakStatement, object data) { var frame = members.Peek(); frame.inIterator = true; return EndNode(yieldBreakStatement, new ReturnStatement()); } public AstNode VisitYieldReturnStatement(CSharp.YieldReturnStatement yieldReturnStatement, object data) { var frame = members.Peek(); frame.inIterator = true; return EndNode(yieldReturnStatement, new YieldStatement((Expression)yieldReturnStatement.Expression.AcceptVisitor(this, data))); } public AstNode VisitAccessor(CSharp.Accessor accessor, object data) { var result = new Accessor(); ConvertNodes(accessor.Attributes, result.Attributes); ConvertNodes(accessor.ModifierTokens, result.ModifierTokens); result.Body = (BlockStatement)accessor.Body.AcceptVisitor(this, data); return EndNode(accessor, result); } public AstNode VisitConstructorDeclaration(CSharp.ConstructorDeclaration constructorDeclaration, object data) { var result = new ConstructorDeclaration(); ConvertNodes(constructorDeclaration.Attributes, result.Attributes); 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) { var result = new InvocationExpression( new MemberAccessExpression() { Target = new InstanceExpression(constructorInitializer.ConstructorInitializerType == CSharp.ConstructorInitializerType.This ? InstanceExpressionType.Me : InstanceExpressionType.MyBase, TextLocation.Empty), MemberName = new Identifier("New", TextLocation.Empty) } ); ConvertNodes(constructorInitializer.Arguments, result.Arguments); return EndNode(constructorInitializer, new ExpressionStatement(result)); } public AstNode VisitDestructorDeclaration(CSharp.DestructorDeclaration destructorDeclaration, object data) { var finalizer = new MethodDeclaration() { Name = "Finalize", IsSub = true }; ConvertNodes(destructorDeclaration.Attributes, finalizer.Attributes); ConvertNodes(destructorDeclaration.ModifierTokens, finalizer.ModifierTokens); finalizer.Body = (BlockStatement)destructorDeclaration.Body.AcceptVisitor(this, data); return EndNode(destructorDeclaration, finalizer); } public AstNode VisitEnumMemberDeclaration(CSharp.EnumMemberDeclaration enumMemberDeclaration, object data) { var result = new EnumMemberDeclaration(); ConvertNodes(enumMemberDeclaration.Attributes, result.Attributes); result.Name = new Identifier(enumMemberDeclaration.Name, TextLocation.Empty); result.Value = (Expression)enumMemberDeclaration.Initializer.AcceptVisitor(this, data); return EndNode(enumMemberDeclaration, result); } public AstNode VisitEventDeclaration(CSharp.EventDeclaration eventDeclaration, object data) { members.Push(new MemberInfo()); foreach (var evt in eventDeclaration.Variables) { var result = new EventDeclaration(); ConvertNodes(eventDeclaration.Attributes, result.Attributes); if (types.Any()) { if (types.Peek().ClassType == ClassType.Module) eventDeclaration.Modifiers &= ~CSharp.Modifiers.Static; types.Peek().Members.Add(result); } result.Modifiers = ConvertModifiers(eventDeclaration.Modifiers, eventDeclaration); result.Name = evt.Name; result.ReturnType = (AstType)eventDeclaration.ReturnType.AcceptVisitor(this, data); // CreateImplementsClausesForEvent(result); } members.Pop(); return EndNode(eventDeclaration, null); } public AstNode VisitCustomEventDeclaration(CSharp.CustomEventDeclaration customEventDeclaration, object data) { var result = new EventDeclaration(); members.Push(new MemberInfo()); ConvertNodes(customEventDeclaration.Attributes, result.Attributes); if (types.Any() && types.Peek().ClassType == ClassType.Module) customEventDeclaration.Modifiers &= ~CSharp.Modifiers.Static; result.Modifiers = ConvertModifiers(customEventDeclaration.Modifiers, customEventDeclaration); result.IsCustom = true; result.Name = new Identifier(customEventDeclaration.Name, TextLocation.Empty); result.ReturnType = (AstType)customEventDeclaration.ReturnType.AcceptVisitor(this, data); if (!customEventDeclaration.PrivateImplementationType.IsNull) result.ImplementsClause.Add( new InterfaceMemberSpecifier((AstType)customEventDeclaration.PrivateImplementationType.AcceptVisitor(this, data), customEventDeclaration.Name)); // else // CreateImplementsClausesForEvent(result); result.AddHandlerBlock = (Accessor)customEventDeclaration.AddAccessor.AcceptVisitor(this, data); result.RemoveHandlerBlock = (Accessor)customEventDeclaration.RemoveAccessor.AcceptVisitor(this, data); members.Pop(); return EndNode(customEventDeclaration, result); } public AstNode VisitFieldDeclaration(CSharp.FieldDeclaration fieldDeclaration, object data) { var decl = new FieldDeclaration(); members.Push(new MemberInfo()); ConvertNodes(fieldDeclaration.Attributes, decl.Attributes); if (types.Any() && types.Peek().ClassType == ClassType.Module) fieldDeclaration.Modifiers &= ~CSharp.Modifiers.Static; decl.Modifiers = ConvertModifiers(fieldDeclaration.Modifiers, fieldDeclaration); ConvertNodes(fieldDeclaration.Variables, decl.Variables); members.Pop(); return EndNode(fieldDeclaration, decl); } public AstNode VisitIndexerDeclaration(CSharp.IndexerDeclaration indexerDeclaration, object data) { var decl = new PropertyDeclaration(); members.Push(new MemberInfo()); ConvertNodes(indexerDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), decl.Attributes); decl.Getter = (Accessor)indexerDeclaration.Getter.AcceptVisitor(this, data); if (types.Any() && types.Peek().ClassType == ClassType.Module) indexerDeclaration.Modifiers &= ~CSharp.Modifiers.Static; decl.Modifiers = ConvertModifiers(indexerDeclaration.Modifiers, indexerDeclaration); decl.Name = new Identifier(indexerDeclaration.Name, TextLocation.Empty); ConvertNodes(indexerDeclaration.Parameters, decl.Parameters); ConvertNodes(indexerDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), decl.ReturnTypeAttributes); if (!indexerDeclaration.PrivateImplementationType.IsNull) decl.ImplementsClause.Add( new InterfaceMemberSpecifier((AstType)indexerDeclaration.PrivateImplementationType.AcceptVisitor(this, data), indexerDeclaration.Name)); decl.ReturnType = (AstType)indexerDeclaration.ReturnType.AcceptVisitor(this, data); decl.Setter = (Accessor)indexerDeclaration.Setter.AcceptVisitor(this, data); if (!decl.Setter.IsNull) { decl.Setter.Parameters.Add(new ParameterDeclaration() { Name = new Identifier("value", TextLocation.Empty), Type = (AstType)indexerDeclaration.ReturnType.AcceptVisitor(this, data), }); } members.Pop(); return EndNode(indexerDeclaration, decl); } public AstNode VisitMethodDeclaration(CSharp.MethodDeclaration methodDeclaration, object data) { CSharp.Attribute attr; if (types.Any() && types.Peek().ClassType == ClassType.Module) methodDeclaration.Modifiers &= ~CSharp.Modifiers.Static; if ((methodDeclaration.Modifiers & CSharp.Modifiers.Extern) == CSharp.Modifiers.Extern && HasAttribute(methodDeclaration.Attributes, "System.Runtime.InteropServices.DllImportAttribute", out attr)) { var result = new ExternalMethodDeclaration(); members.Push(new MemberInfo()); // remove AttributeSection if only one attribute is present var attrSec = (CSharp.AttributeSection)attr.Parent; if (attrSec.Attributes.Count == 1) attrSec.Remove(); else attr.Remove(); result.Library = (attr.Arguments.First().AcceptVisitor(this, data) as PrimitiveExpression).Value.ToString(); result.CharsetModifier = ConvertCharset(attr.Arguments); result.Alias = ConvertAlias(attr.Arguments); ConvertNodes(methodDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), result.Attributes); ConvertNodes(methodDeclaration.ModifierTokens, result.ModifierTokens); result.Name = new Identifier(methodDeclaration.Name, TextLocation.Empty); result.IsSub = IsSub(methodDeclaration.ReturnType); ConvertNodes(methodDeclaration.Parameters, result.Parameters); ConvertNodes(methodDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), result.ReturnTypeAttributes); if (!result.IsSub) result.ReturnType = (AstType)methodDeclaration.ReturnType.AcceptVisitor(this, data); if (members.Pop().inIterator) { result.Modifiers |= Modifiers.Iterator; } return EndNode(methodDeclaration, result); } else { var result = new MethodDeclaration(); members.Push(new MemberInfo()); ConvertNodes(methodDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), result.Attributes); ConvertNodes(methodDeclaration.ModifierTokens, result.ModifierTokens); result.Name = new Identifier(methodDeclaration.Name, TextLocation.Empty); result.IsSub = IsSub(methodDeclaration.ReturnType); ConvertNodes(methodDeclaration.Parameters, result.Parameters); ConvertNodes(methodDeclaration.TypeParameters, result.TypeParameters); ConvertNodes(methodDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), result.ReturnTypeAttributes); if (!methodDeclaration.PrivateImplementationType.IsNull) result.ImplementsClause.Add( new InterfaceMemberSpecifier((AstType)methodDeclaration.PrivateImplementationType.AcceptVisitor(this, data), methodDeclaration.Name)); // else // CreateImplementsClausesForMethod(result); if (!result.IsSub) result.ReturnType = (AstType)methodDeclaration.ReturnType.AcceptVisitor(this, data); if (methodDeclaration.IsExtensionMethod) { result.Attributes.Add( new AttributeBlock { Attributes = { new Ast.Attribute { Type = AstType.FromName("System.Runtime.CompilerServices.ExtensionAttribute") } } }); } result.Body = (BlockStatement)methodDeclaration.Body.AcceptVisitor(this, data); if (members.Pop().inIterator) { result.Modifiers |= Modifiers.Iterator; } return EndNode(methodDeclaration, result); } } void CreateImplementsClausesForMethod(MethodDeclaration result) { if (!types.Any()) return; var current = types.Peek(); if (current.ClassType == ClassType.Interface) return; foreach (var type in current.ImplementsTypes) { var resolved = provider.ResolveType(type, current); var found = resolved.GetMembers(m => m.SymbolKind == SymbolKind.Method && m.Name == result.Name.Name); if (found.FirstOrDefault() != null) { result.ImplementsClause.Add(new InterfaceMemberSpecifier((AstType)type.Clone(), found.FirstOrDefault().Name)); } } } void CreateImplementsClausesForEvent(EventDeclaration result) { if (!types.Any()) return; var current = types.Peek(); if (current.ClassType == ClassType.Interface) return; foreach (var type in current.ImplementsTypes) { var resolved = provider.ResolveType(type, current); var found = resolved.GetMembers(m => m.SymbolKind == SymbolKind.Event && m.Name == result.Name.Name); if (found.FirstOrDefault() != null) { result.ImplementsClause.Add(new InterfaceMemberSpecifier((AstType)type.Clone(), found.FirstOrDefault().Name)); } } } string ConvertAlias(CSharp.AstNodeCollection arguments) { var pattern = new CSharp.AssignmentExpression() { Left = new CSharp.IdentifierExpression("EntryPoint"), Operator = CSharp.AssignmentOperatorType.Assign, Right = new AnyNode("alias") }; var result = arguments .Select(expr => pattern.Match(expr)) .FirstOrDefault(r => r.Success); if (result.Success && result.Has("alias")) { return result.Get("alias") .First().Value.ToString(); } return null; } CharsetModifier ConvertCharset(CSharp.AstNodeCollection arguments) { var pattern = new CSharp.AssignmentExpression() { Left = new CSharp.IdentifierExpression("CharSet"), Operator = CSharp.AssignmentOperatorType.Assign, Right = new NamedNode( "modifier", new CSharp.MemberReferenceExpression() { Target = new CSharp.IdentifierExpression("CharSet"), MemberName = Pattern.AnyString }) }; var result = arguments .Select(expr => pattern.Match(expr)) .FirstOrDefault(r => r.Success); if (result.Success && result.Has("modifier")) { switch (result.Get("modifier").First().MemberName) { case "Auto": return CharsetModifier.Auto; case "Ansi": return CharsetModifier.Ansi; case "Unicode": return CharsetModifier.Unicode; } } return CharsetModifier.None; } bool IsSub(CSharp.AstType returnType) { var t = returnType as CSharp.PrimitiveType; return t != null && t.Keyword == "void"; } public AstNode VisitOperatorDeclaration(CSharp.OperatorDeclaration operatorDeclaration, object data) { MemberDeclaration result; members.Push(new MemberInfo()); if (types.Any() && types.Peek().ClassType == ClassType.Module) operatorDeclaration.Modifiers &= ~CSharp.Modifiers.Static; if (operatorDeclaration.OperatorType == CSharp.OperatorType.Increment || operatorDeclaration.OperatorType == CSharp.OperatorType.Decrement) { var m = new MethodDeclaration(); result = m; ConvertNodes(operatorDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), m.Attributes); ConvertNodes(operatorDeclaration.ModifierTokens, m.ModifierTokens); m.Name = operatorDeclaration.OperatorType == CSharp.OperatorType.Increment ? "op_Increment" : "op_Decrement"; ConvertNodes(operatorDeclaration.Parameters, m.Parameters); ConvertNodes(operatorDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), m.ReturnTypeAttributes); m.ReturnType = (AstType)operatorDeclaration.ReturnType.AcceptVisitor(this, data); m.Body = (BlockStatement)operatorDeclaration.Body.AcceptVisitor(this, data); } else { var op = new OperatorDeclaration(); result = op; ConvertNodes(operatorDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), op.Attributes); ConvertNodes(operatorDeclaration.ModifierTokens, op.ModifierTokens); switch (operatorDeclaration.OperatorType) { case CSharp.OperatorType.LogicalNot: case CSharp.OperatorType.OnesComplement: op.Operator = OverloadableOperatorType.Not; break; case CSharp.OperatorType.True: op.Operator = OverloadableOperatorType.IsTrue; break; case CSharp.OperatorType.False: op.Operator = OverloadableOperatorType.IsFalse; break; case CSharp.OperatorType.Implicit: op.Modifiers |= Modifiers.Widening; op.Operator = OverloadableOperatorType.CType; break; case CSharp.OperatorType.Explicit: op.Modifiers |= Modifiers.Narrowing; op.Operator = OverloadableOperatorType.CType; break; case CSharp.OperatorType.Addition: op.Operator = OverloadableOperatorType.Add; break; case CSharp.OperatorType.Subtraction: op.Operator = OverloadableOperatorType.Subtract; break; case CSharp.OperatorType.UnaryPlus: op.Operator = OverloadableOperatorType.UnaryPlus; break; case CSharp.OperatorType.UnaryNegation: op.Operator = OverloadableOperatorType.UnaryMinus; break; case CSharp.OperatorType.Multiply: op.Operator = OverloadableOperatorType.Multiply; break; case CSharp.OperatorType.Division: op.Operator = OverloadableOperatorType.Divide; break; case CSharp.OperatorType.Modulus: op.Operator = OverloadableOperatorType.Modulus; break; case CSharp.OperatorType.BitwiseAnd: op.Operator = OverloadableOperatorType.BitwiseAnd; break; case CSharp.OperatorType.BitwiseOr: op.Operator = OverloadableOperatorType.BitwiseOr; break; case CSharp.OperatorType.ExclusiveOr: op.Operator = OverloadableOperatorType.ExclusiveOr; break; case CSharp.OperatorType.LeftShift: op.Operator = OverloadableOperatorType.ShiftLeft; break; case CSharp.OperatorType.RightShift: op.Operator = OverloadableOperatorType.ShiftRight; break; case CSharp.OperatorType.Equality: op.Operator = OverloadableOperatorType.Equality; break; case CSharp.OperatorType.Inequality: op.Operator = OverloadableOperatorType.InEquality; break; case CSharp.OperatorType.GreaterThan: op.Operator = OverloadableOperatorType.GreaterThan; break; case CSharp.OperatorType.LessThan: op.Operator = OverloadableOperatorType.LessThan; break; case CSharp.OperatorType.GreaterThanOrEqual: op.Operator = OverloadableOperatorType.GreaterThanOrEqual; break; case CSharp.OperatorType.LessThanOrEqual: op.Operator = OverloadableOperatorType.LessThanOrEqual; break; default: throw new Exception("Invalid value for OperatorType"); } ConvertNodes(operatorDeclaration.Parameters, op.Parameters); ConvertNodes(operatorDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), op.ReturnTypeAttributes); op.ReturnType = (AstType)operatorDeclaration.ReturnType.AcceptVisitor(this, data); op.Body = (BlockStatement)operatorDeclaration.Body.AcceptVisitor(this, data); } members.Pop(); return EndNode(operatorDeclaration, result); } public AstNode VisitParameterDeclaration(CSharp.ParameterDeclaration parameterDeclaration, object data) { var param = new ParameterDeclaration(); ConvertNodes(parameterDeclaration.Attributes, param.Attributes); param.Modifiers = ConvertParamModifiers(parameterDeclaration.ParameterModifier); if ((parameterDeclaration.ParameterModifier & CSharp.ParameterModifier.Out) == CSharp.ParameterModifier.Out) { AttributeBlock block = new AttributeBlock(); block.Attributes.Add(new Ast.Attribute() { Type = new SimpleType("Out") }); param.Attributes.Add(block); } param.Name = new Identifier(parameterDeclaration.Name, TextLocation.Empty); param.Type = (AstType)parameterDeclaration.Type.AcceptVisitor(this, data); param.OptionalValue = (Expression)parameterDeclaration.DefaultExpression.AcceptVisitor(this, data); if (!param.OptionalValue.IsNull) param.Modifiers |= Modifiers.Optional; return EndNode(parameterDeclaration, param); } Modifiers ConvertParamModifiers(CSharp.ParameterModifier mods) { switch (mods) { case CSharp.ParameterModifier.None: case CSharp.ParameterModifier.This: return Modifiers.None; case CSharp.ParameterModifier.Ref: case CSharp.ParameterModifier.Out: return Modifiers.ByRef; case CSharp.ParameterModifier.Params: return Modifiers.ParamArray; default: throw new Exception("Invalid value for ParameterModifier"); } } public AstNode VisitPropertyDeclaration(CSharp.PropertyDeclaration propertyDeclaration, object data) { var decl = new PropertyDeclaration(); members.Push(new MemberInfo()); if (types.Any() && types.Peek().ClassType == ClassType.Module) propertyDeclaration.Modifiers &= ~CSharp.Modifiers.Static; ConvertNodes(propertyDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), decl.Attributes); decl.Getter = (Accessor)propertyDeclaration.Getter.AcceptVisitor(this, data); decl.Modifiers = ConvertModifiers(propertyDeclaration.Modifiers, propertyDeclaration); decl.Name = new Identifier(propertyDeclaration.Name, TextLocation.Empty); ConvertNodes(propertyDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), decl.ReturnTypeAttributes); if (!propertyDeclaration.PrivateImplementationType.IsNull) decl.ImplementsClause.Add( new InterfaceMemberSpecifier((AstType)propertyDeclaration.PrivateImplementationType.AcceptVisitor(this, data), propertyDeclaration.Name)); decl.ReturnType = (AstType)propertyDeclaration.ReturnType.AcceptVisitor(this, data); decl.Setter = (Accessor)propertyDeclaration.Setter.AcceptVisitor(this, data); if (!decl.Setter.IsNull) { decl.Setter.Parameters.Add(new ParameterDeclaration() { Name = new Identifier("value", TextLocation.Empty), Type = (AstType)propertyDeclaration.ReturnType.AcceptVisitor(this, data), }); } if (members.Pop().inIterator) { decl.Modifiers |= Modifiers.Iterator; } ConvertNodes(provider.GetParametersForProperty(propertyDeclaration), decl.Parameters); return EndNode(propertyDeclaration, decl); } public AstNode VisitVariableInitializer(CSharp.VariableInitializer variableInitializer, object data) { var decl = new VariableDeclaratorWithTypeAndInitializer(); // look for type in parent decl.Type = (AstType)variableInitializer.Parent .GetChildByRole(CSharp.Roles.Type) .AcceptVisitor(this, data); decl.Identifiers.Add(new VariableIdentifier() { Name = variableInitializer.Name }); decl.Initializer = (Expression)variableInitializer.Initializer.AcceptVisitor(this, data); return EndNode(variableInitializer, decl); } public AstNode VisitFixedFieldDeclaration(CSharp.FixedFieldDeclaration fixedFieldDeclaration, object data) { throw new NotImplementedException(); } public AstNode VisitFixedVariableInitializer(CSharp.FixedVariableInitializer fixedVariableInitializer, object data) { throw new NotImplementedException(); } public AstNode VisitSyntaxTree(CSharp.SyntaxTree syntaxTree, object data) { var unit = new CompilationUnit(); foreach (var node in syntaxTree.Children) unit.AddChild(node.AcceptVisitor(this, null), CompilationUnit.MemberRole); return EndNode(syntaxTree, unit); } public AstNode VisitSimpleType(CSharp.SimpleType simpleType, object data) { var type = new SimpleType(simpleType.Identifier); ConvertNodes(simpleType.TypeArguments, type.TypeArguments); return EndNode(simpleType, type); } public AstNode VisitMemberType(CSharp.MemberType memberType, object data) { AstType target = null; if (memberType.Target is CSharp.SimpleType && ((CSharp.SimpleType)(memberType.Target)).Identifier.Equals("global", StringComparison.Ordinal)) target = new PrimitiveType("Global"); else target = (AstType)memberType.Target.AcceptVisitor(this, data); var type = new QualifiedType(target, new Identifier(memberType.MemberName, TextLocation.Empty)); ConvertNodes(memberType.TypeArguments, type.TypeArguments); return EndNode(memberType, type); } public AstNode VisitComposedType(CSharp.ComposedType composedType, object data) { AstType type = new ComposedType(); ConvertNodes(composedType.ArraySpecifiers, ((ComposedType)type).ArraySpecifiers); ((ComposedType)type).BaseType = (AstType)composedType.BaseType.AcceptVisitor(this, data); ((ComposedType)type).HasNullableSpecifier = composedType.HasNullableSpecifier; for (int i = 0; i < composedType.PointerRank; i++) { var tmp = new SimpleType() { Identifier = "__Pointer" }; tmp.TypeArguments.Add(type); type = tmp; } return EndNode(composedType, type); } public AstNode VisitArraySpecifier(CSharp.ArraySpecifier arraySpecifier, object data) { return EndNode(arraySpecifier, new ArraySpecifier(arraySpecifier.Dimensions)); } public AstNode VisitPrimitiveType(CSharp.PrimitiveType primitiveType, object data) { string typeName; switch (primitiveType.Keyword) { case "object": typeName = "Object"; break; case "bool": typeName = "Boolean"; break; case "char": typeName = "Char"; break; case "sbyte": typeName = "SByte"; break; case "byte": typeName = "Byte"; break; case "short": typeName = "Short"; break; case "ushort": typeName = "UShort"; break; case "int": typeName = "Integer"; break; case "uint": typeName = "UInteger"; break; case "long": typeName = "Long"; break; case "ulong": typeName = "ULong"; break; case "float": typeName = "Single"; break; case "double": typeName = "Double"; break; case "decimal": typeName = "Decimal"; break; case "string": typeName = "String"; break; // generic constraints case "new": typeName = "New"; break; case "struct": typeName = "Structure"; break; case "class": typeName = "Class"; break; case "void": typeName = "Void"; break; default: typeName = "unknown"; break; } return EndNode(primitiveType, new PrimitiveType(typeName)); } public AstNode VisitComment (CSharp.Comment comment, object data) { var c = new Comment (comment.Content, comment.CommentType == CSharp.CommentType.Documentation); if (comment.CommentType == CSharp.CommentType.MultiLine) throw new NotImplementedException (); return EndNode (comment, c); } public AstNode VisitPreProcessorDirective (CSharp.PreProcessorDirective preProcessorDirective, object data) { // TODO return null; } public AstNode VisitTypeParameterDeclaration(CSharp.TypeParameterDeclaration typeParameterDeclaration, object data) { var param = new TypeParameterDeclaration() { Variance = typeParameterDeclaration.Variance, Name = typeParameterDeclaration.Name }; var constraint = typeParameterDeclaration.Parent .GetChildrenByRole(CSharp.Roles.Constraint) .SingleOrDefault(c => c.TypeParameter.Identifier == typeParameterDeclaration.Name); if (constraint != null) ConvertNodes(constraint.BaseTypes, param.Constraints); // TODO : typeParameterDeclaration.Attributes get lost? //ConvertNodes(typeParameterDeclaration.Attributes return EndNode(typeParameterDeclaration, param); } public AstNode VisitConstraint(CSharp.Constraint constraint, object data) { throw new NotImplementedException(); } public AstNode VisitCSharpTokenNode(CSharp.CSharpTokenNode cSharpTokenNode, object data) { var mod = cSharpTokenNode as CSharp.CSharpModifierToken; if (mod != null) { var convertedModifiers = ConvertModifiers(mod.Modifier, mod.Parent); VBModifierToken token = null; if (convertedModifiers != Modifiers.None) { token = new VBModifierToken(TextLocation.Empty, convertedModifiers); return EndNode(cSharpTokenNode, token); } return EndNode(cSharpTokenNode, token); } else { throw new NotSupportedException("Should never visit individual tokens"); } } Modifiers ConvertModifiers(CSharp.Modifiers modifier, CSharp.AstNode container) { if ((modifier & CSharp.Modifiers.Any) == CSharp.Modifiers.Any) return Modifiers.Any; var mod = Modifiers.None; if ((modifier & CSharp.Modifiers.Const) == CSharp.Modifiers.Const) mod |= Modifiers.Const; if ((modifier & CSharp.Modifiers.Abstract) == CSharp.Modifiers.Abstract) { if (container is CSharp.TypeDeclaration) mod |= Modifiers.MustInherit; else mod |= Modifiers.MustOverride; } if ((modifier & CSharp.Modifiers.Static) == CSharp.Modifiers.Static) mod |= Modifiers.Shared; if ((modifier & CSharp.Modifiers.Public) == CSharp.Modifiers.Public) mod |= Modifiers.Public; if ((modifier & CSharp.Modifiers.Protected) == CSharp.Modifiers.Protected) mod |= Modifiers.Protected; if ((modifier & CSharp.Modifiers.Internal) == CSharp.Modifiers.Internal) mod |= Modifiers.Friend; if ((modifier & CSharp.Modifiers.Private) == CSharp.Modifiers.Private) mod |= Modifiers.Private; if (container is CSharp.IndexerDeclaration) mod |= Modifiers.Default; bool writeable = IsWriteableProperty(container); bool readable = IsReadableProperty(container); if (writeable && !readable) mod |= Modifiers.WriteOnly; if (readable && !writeable) mod |= Modifiers.ReadOnly; if ((modifier & CSharp.Modifiers.Override) == CSharp.Modifiers.Override) mod |= Modifiers.Overrides; if ((modifier & CSharp.Modifiers.Virtual) == CSharp.Modifiers.Virtual) mod |= Modifiers.Overridable; if ((modifier & CSharp.Modifiers.Async) == CSharp.Modifiers.Async) mod |= Modifiers.Async; return mod; } bool IsReadableProperty(ICSharpCode.NRefactory.CSharp.AstNode container) { if (container is CSharp.IndexerDeclaration) { var i = container as CSharp.IndexerDeclaration; return !i.Getter.IsNull; } if (container is CSharp.PropertyDeclaration) { var p = container as CSharp.PropertyDeclaration; return !p.Getter.IsNull; } return false; } bool IsWriteableProperty(ICSharpCode.NRefactory.CSharp.AstNode container) { if (container is CSharp.IndexerDeclaration) { var i = container as CSharp.IndexerDeclaration; return !i.Setter.IsNull; } if (container is CSharp.PropertyDeclaration) { var p = container as CSharp.PropertyDeclaration; return !p.Setter.IsNull; } return false; } public AstNode VisitIdentifier(CSharp.Identifier identifier, object data) { var ident = new Identifier(identifier.Name, identifier.StartLocation); return EndNode(identifier, ident); } public AstNode VisitPatternPlaceholder(CSharp.AstNode placeholder, ICSharpCode.NRefactory.PatternMatching.Pattern pattern, object data) { throw new NotImplementedException(); } void ConvertNodes(IEnumerable nodes, VB.AstNodeCollection result, Func transform = null) where T: VB.AstNode { foreach (var node in nodes) { T n = (T)node.AcceptVisitor(this, null); if (transform != null) n = transform(n); if (n != null) result.Add(n); } } void ConvertMembers(CSharp.AstNode parent, T result, Role sourceRole, Role targetRole) where T : VB.AstNode where S : CSharp.AstNode where M : VB.AstNode { foreach (var node in parent.Children) { if (node.Role == CSharp.Roles.Comment) { var n = (Comment)node.AcceptVisitor(this, null); if (n != null) result.AddChild(n, AstNode.Roles.Comment); } if (node.Role == sourceRole) { var n = (M)node.AcceptVisitor(this, null); if (n != null) result.AddChild(n, targetRole); } } } T EndNode(CSharp.AstNode node, T result) where T : VB.AstNode { if (result != null) { CopyAnnotations(node, result); } return result; } void CopyAnnotations(CSharp.AstNode node, T result) where T : VB.AstNode { foreach (var ann in node.Annotations) result.AddAnnotation(ann); } bool HasAttribute(CSharp.AstNodeCollection attributes, string name, out CSharp.Attribute foundAttribute) { foreach (var attr in attributes.SelectMany(a => a.Attributes)) { if (provider.GetTypeNameForAttribute(attr) == name) { foundAttribute = attr; return true; } } foundAttribute = null; return false; } public AstNode VisitDocumentationReference(CSharp.DocumentationReference documentationReference, object data) { throw new NotImplementedException(); } public AstNode VisitNewLine(CSharp.NewLineNode newLineNode, object data) { return null; } public AstNode VisitWhitespace(CSharp.WhitespaceNode whitespaceNode, object data) { return null; } public AstNode VisitText(CSharp.TextNode textNode, object data) { return null; } public AstNode VisitNullNode(ICSharpCode.NRefactory.CSharp.AstNode nullNode, object data) { return null; } public AstNode VisitErrorNode(ICSharpCode.NRefactory.CSharp.AstNode errorNode, object data) { return null; } } }