Example #1
0
        private static void Generate(IEnumerable <string> extraTranslation)
        {
            Console.WriteLine("Parsing...");
            var sw = Stopwatch.StartNew();


            TranslationManager.Init(extraTranslation);

            if (!Directory.Exists(OutDir))
            {
                Directory.CreateDirectory(OutDir);
            }

            var allTypes = Compilation.SyntaxTrees
                           .SelectMany(o => o.GetRoot().DescendantNodes().OfType <BaseTypeDeclarationSyntax>())
                           .Select(o => new { Syntax = o, Symbol = GetModel(o).GetDeclaredSymbol(o), TypeName = WriteType.TypeName(GetModel(o).GetDeclaredSymbol(o)) })
                           .GroupBy(o => o.Symbol.ContainingNamespace.FullName() + "." + o.TypeName)
                           .ToList();

            Utility.Parallel(Compilation.SyntaxTrees.ToList(), tree =>
            {
                foreach (var n in TriviaProcessor.DoNotWrite(tree))
                {
                    DoNotWrite.TryAdd(n, null);
                }
            });

            Console.WriteLine("Parsed in " + sw.Elapsed + ". Writing out haxe...");
            sw.Restart();

            Compilation.SyntaxTrees.SelectMany(o => o.GetRoot().DescendantNodes().OfType <AnonymousObjectCreationExpressionSyntax>())
            .Select(o => new { Syntax = o, Name = WriteAnonymousObjectCreationExpression.TypeName(o) })
            .GroupBy(o => o.Name)
            .Parallel(o => WriteAnonymousObjectCreationExpression.WriteAnonymousType(o.First().Syntax));


            allTypes.Parallel(type =>
            {
                TypeState.Instance          = new TypeState();
                TypeState.Instance.TypeName = type.First().TypeName;
                TypeState.Instance.Partials = type.Select(o => new TypeState.SyntaxAndSymbol {
                    Symbol = o.Symbol, Syntax = o.Syntax
                })
                                              .Where(o => !DoNotWrite.ContainsKey(o.Syntax))
                                              .ToList();

                if (TypeState.Instance.Partials.Count > 0)
                {
                    WriteType.Go();
                }
            });

            WriteConstructor.WriteConstructorsHelper(allTypes.SelectMany(o => o).Where(o => !DoNotWrite.ContainsKey(o.Syntax)).Select(o => o.Symbol));

            Console.WriteLine("Haxe written out in " + sw.Elapsed);
        }
Example #2
0
 private static void Factory(HaxeWriter writer, SyntaxNode node)
 {
     if (node is MethodDeclarationSyntax)
     {
         WriteMethod.Go(writer, node.As <MethodDeclarationSyntax>());
     }
     else if (node is PropertyDeclarationSyntax)
     {
         WriteProperty.Go(writer, node.As <PropertyDeclarationSyntax>());
     }
     else if (node is FieldDeclarationSyntax)
     {
         WriteField.Go(writer, node.As <FieldDeclarationSyntax>());
     }
     else if (node is ConstructorDeclarationSyntax)
     {
         WriteConstructor.Go(writer, node.As <ConstructorDeclarationSyntax>());
     }
     else if (node is ExpressionStatementSyntax)
     {
         WriteStatement(writer, node.As <ExpressionStatementSyntax>());
     }
     else if (node is LocalDeclarationStatementSyntax)
     {
         WriteLocalDeclaration.Go(writer, node.As <LocalDeclarationStatementSyntax>());
     }
     else if (node is BlockSyntax)
     {
         WriteBlock(writer, node.As <BlockSyntax>());
     }
     else if (node is InvocationExpressionSyntax)
     {
         WriteInvocationExpression.Go(writer, node.As <InvocationExpressionSyntax>());
     }
     else if (node is LiteralExpressionSyntax)
     {
         WriteLiteralExpression.Go(writer, node.As <LiteralExpressionSyntax>());
     }
     else if (node is IdentifierNameSyntax)
     {
         WriteIdentifierName.Go(writer, node.As <IdentifierNameSyntax>());
     }
     else if (node is ImplicitArrayCreationExpressionSyntax)
     {
         WriteArrayCreationExpression.Go(writer, node.As <ImplicitArrayCreationExpressionSyntax>());
     }
     else if (node is ArrayCreationExpressionSyntax)
     {
         WriteArrayCreationExpression.Go(writer, node.As <ArrayCreationExpressionSyntax>());
     }
     else if (node is MemberAccessExpressionSyntax)
     {
         WriteMemberAccessExpression.Go(writer, node.As <MemberAccessExpressionSyntax>());
     }
     else if (node is ParenthesizedLambdaExpressionSyntax)
     {
         WriteLambdaExpression.Go(writer, node.As <ParenthesizedLambdaExpressionSyntax>());
     }
     else if (node is SimpleLambdaExpressionSyntax)
     {
         WriteLambdaExpression.Go(writer, node.As <SimpleLambdaExpressionSyntax>());
     }
     else if (node is ReturnStatementSyntax)
     {
         WriteReturnStatement.Go(writer, node.As <ReturnStatementSyntax>());
     }
     else if (node is ObjectCreationExpressionSyntax)
     {
         WriteObjectCreationExpression.Go(writer, node.As <ObjectCreationExpressionSyntax>());
     }
     else if (node is ElementAccessExpressionSyntax)
     {
         WriteElementAccessExpression.Go(writer, node.As <ElementAccessExpressionSyntax>());
     }
     else if (node is ForEachStatementSyntax)
     {
         WriteForEachStatement.Go(writer, node.As <ForEachStatementSyntax>());
     }
     else if (node is IfStatementSyntax)
     {
         WriteIfStatement.Go(writer, node.As <IfStatementSyntax>());
     }
     else if (node is BinaryExpressionSyntax)
     {
         WriteBinaryExpression.Go(writer, node.As <BinaryExpressionSyntax>());
     }
     else if (node is ConditionalExpressionSyntax)
     {
         WriteConditionalExpression.Go(writer, node.As <ConditionalExpressionSyntax>());
     }
     else if (node is BaseExpressionSyntax)
     {
         WriteBaseExpression.Go(writer, node.As <BaseExpressionSyntax>());
     }
     else if (node is ThisExpressionSyntax)
     {
         WriteThisExpression.Go(writer, node.As <ThisExpressionSyntax>());
     }
     else if (node is CastExpressionSyntax)
     {
         WriteCastExpression.Go(writer, node.As <CastExpressionSyntax>());
     }
     else if (node is ThrowStatementSyntax)
     {
         WriteThrowStatement.Go(writer, node.As <ThrowStatementSyntax>());
     }
     else if (node is ThrowExpressionSyntax)
     {
         WriteThrowStatement.GoExpression(writer, node.As <ThrowExpressionSyntax>());
     }
     else if (node is PrefixUnaryExpressionSyntax)
     {
         WriteUnaryExpression.Go(writer, node.As <PrefixUnaryExpressionSyntax>());
     }
     else if (node is PostfixUnaryExpressionSyntax)
     {
         WriteUnaryExpression.Go(writer, node.As <PostfixUnaryExpressionSyntax>());
     }
     else if (node is EqualsValueClauseSyntax)
     {
         WriteEqualsValueClause.Go(writer, node.As <EqualsValueClauseSyntax>());
     }
     else if (node is ForStatementSyntax)
     {
         WriteForStatement.Go(writer, node.As <ForStatementSyntax>());
     }
     else if (node is WhileStatementSyntax)
     {
         WriteWhileStatement.Go(writer, node.As <WhileStatementSyntax>());
     }
     else if (node is BreakStatementSyntax)
     {
         WriteBreakStatement.Go(writer, node.As <BreakStatementSyntax>());
     }
     else if (node is DoStatementSyntax)
     {
         WriteDoStatement.Go(writer, node.As <DoStatementSyntax>());
     }
     else if (node is SwitchStatementSyntax)
     {
         WriteSwitchStatement.Go(writer, node.As <SwitchStatementSyntax>());
     }
     else if (node is TryStatementSyntax)
     {
         WriteTryStatement.Go(writer, node.As <TryStatementSyntax>());
     }
     else if (node is UsingStatementSyntax)
     {
         WriteUsingStatement.Go(writer, node.As <UsingStatementSyntax>());
     }
     else if (node is ParenthesizedExpressionSyntax)
     {
         WriteParenthesizedExpression.Go(writer, node.As <ParenthesizedExpressionSyntax>());
     }
     else if (node is LockStatementSyntax)
     {
         WriteLockStatement.Go(writer, node.As <LockStatementSyntax>());
     }
     else if (node is ContinueStatementSyntax)
     {
         WriteContinueStatement.Go(writer, node.As <ContinueStatementSyntax>());
     }
     else if (node is TypeOfExpressionSyntax)
     {
         WriteTypeOfExpression.Go(writer, node.As <TypeOfExpressionSyntax>());
     }
     else if (node is AnonymousObjectCreationExpressionSyntax)
     {
         WriteAnonymousObjectCreationExpression.Go(writer, node.As <AnonymousObjectCreationExpressionSyntax>());
     }
     else if (node is EmptyStatementSyntax)
     {
         return; //ignore empty statements
     }
     else if (node is DelegateDeclarationSyntax)
     {
         return; //don't write delegates - we convert them to types directly
     }
     else if (node is EventFieldDeclarationSyntax)
     {
         WriteEventFieldDeclaration.Go(writer, node.As <EventFieldDeclarationSyntax>());
     }
     else if (node is DefaultExpressionSyntax)
     {
         WriteDefaultExpression.Go(writer, node.As <DefaultExpressionSyntax>());
     }
     else if (node is GenericNameSyntax)
     {
         WriteGenericName.Go(writer, node.As <GenericNameSyntax>());
     }
     else if (node is ConversionOperatorDeclarationSyntax)
     {
         WriteConversionOperatorDeclaration.Go(writer, node.As <ConversionOperatorDeclarationSyntax>());
     }
     else if (node is AssignmentExpressionSyntax)
     {
         WriteAssignmentExpressionSyntax.Go(writer, node.As <AssignmentExpressionSyntax>());
     }
     else if (node is OperatorDeclarationSyntax)
     {
         WriteMethod.WriteOperatorDeclaration(writer, node.As <OperatorDeclarationSyntax>());
     }
     else if (node is IndexerDeclarationSyntax)
     {
         WriteMethod.WriteIndexerDeclaration(writer, node.As <IndexerDeclarationSyntax>());
     }
     else
     {
         throw new NotImplementedException(node.GetType().Name + " is not supported. " + Utility.Descriptor(node));
     }
 }
Example #3
0
        private static string ConvertTypeUncached(ITypeSymbol typeSymbol)
        {
            if (typeSymbol.IsAnonymousType)
            {
                return(WriteAnonymousObjectCreationExpression.TypeName(typeSymbol.As <INamedTypeSymbol>()));
            }

            var array = typeSymbol as IArrayTypeSymbol;

            if (array != null)
            {
                if (array.ElementType.ToString() == "byte")
                {
                    return("haxe.io.Bytes");                    //byte arrays become haxe.io.Bytes
                }
                else
                {
                    return("Array<" + (ConvertType(array.ElementType) ?? "Dynamic") + ">");
                }
            }

            var typeInfoStr = typeSymbol.ToString();

            var named = typeSymbol as INamedTypeSymbol;

            if (typeSymbol.TypeKind == TypeKind.TypeParameter)
            {
                return(typeSymbol.Name);
            }

            if (typeSymbol.TypeKind == TypeKind.Delegate)
            {
                var dlg = named.DelegateInvokeMethod.As <IMethodSymbol>();
                if (dlg.Parameters.Length == 0)
                {
                    return("(Void -> " + ConvertType(dlg.ReturnType) + ")");
                }
                else
                {
                    return("(" + string.Join("", dlg.Parameters.ToList().Select(o => ConvertType(o.Type) + " -> ")) + ConvertType(dlg.ReturnType) + ")");
                }
            }

            if (typeSymbol.TypeKind == TypeKind.Enum)
            {
                return("Int");                //enums are always ints
            }
            if (named != null && named.Name == "Nullable" && named.ContainingNamespace.ToString() == "System")
            {
                //Nullable types get replaced by our Nullable_ alternatives
                var nullableType = ConvertType(named.TypeArguments.Single());
                if (nullableType == "Int" || nullableType == "Bool" || nullableType == "Float")
                {
                    return("Nullable_" + nullableType);
                }
                else
                {
                    return("Nullable<" + nullableType + ">");
                }
            }

            var typeStr = GenericTypeName(typeSymbol);


            var trans = TypeTranslation.Get(typeStr);

            if (named != null && named.IsGenericType && !named.IsUnboundGenericType && TypeArguments(named).Any() && (trans == null || trans.SkipGenericTypes == false))
            {
                //Generic type
                var genericTypeRoot          = ConvertType(named.ConstructUnboundGenericType());
                var genericTypeArgs          = TypeArguments(named).ToList();
                var genericTypeArgsConverted = genericTypeArgs.Select(o => ConvertType(o) ?? "Dynamic").ToList();

                if (genericTypeRoot == "system.collections.generic.Dictionary" || genericTypeRoot == "system.collections.generic.HashSet")
                {
                    //Cs2hx does not support the GetHashCode() or Equals() functions, and therefore will only work correctly with basic types as the keys of dictionaries and hash sets.  We should throw on any improper usage since it may not run the same as the original C#
                    var hashArg = genericTypeArgsConverted[0];

                    if (genericTypeArgs[0].TypeKind != TypeKind.TypeParameter && hashArg != "Int" && hashArg != "String" && hashArg != "Dynamic") //TODO: Is Dynamic really ok in this list?  This will happen on a Dictionary<object, ...>, which could be a problem unless it was used carefully.
                    {
                        throw new Exception("Improper hash type: " + hashArg + " used on " + genericTypeRoot);                                    //TODO: How can we provide code location?
                    }
                }

                return(genericTypeRoot + "<" + string.Join(", ", genericTypeArgsConverted) + ">");
            }

            switch (typeStr)
            {
            case "System.Void":
                return("Void");

            case "System.Boolean":
                return("Bool");

            case "System.Object":
                return("Dynamic");

            case "System.Int64":
            case "System.UInt64":
            case "System.Single":
            case "System.Double":
                return("Float");

            case "System.String":
                return("String");

            case "System.Int32":
            case "System.UInt32":
            case "System.Byte":
            case "System.Int16":
            case "System.UInt16":
            case "System.Char":
                return("Int");


            case "System.Collections.Generic.List<>":
            case "System.Collections.Generic.IList<>":
            case "System.Collections.Generic.Queue<>":
            case "System.Collections.Generic.IEnumerable<>":
            case "System.Collections.Generic.Dictionary<,>.ValueCollection":
            case "System.Collections.Generic.Dictionary<,>.KeyCollection":
            case "System.Collections.Generic.ICollection<>":
            case "System.Linq.IOrderedEnumerable<>":
            case "System.Collections.IEnumerable":
            case "System.Collections.Specialized.NameObjectCollectionBase.KeysCollection":
                return("Array");

            case "System.Array":
                return(null);                        //in haxe, unlike C#, array must always have type arguments.  To work around this, just avoid printing the type anytime we see a bare Array type in C#. haxe will infer it.

            case "System.Collections.Generic.LinkedList<>":
                return("List");

            default:


                if (trans != null)
                {
                    return(trans.As <Translations.TypeTranslation>().Replace(named));
                }

                if (named != null)
                {
                    return(typeSymbol.ContainingNamespace.FullNameWithDot().ToLower() + WriteType.TypeName(named));
                }

                //This type does not get translated and gets used as-is
                return(typeSymbol.ContainingNamespace.FullNameWithDot().ToLower() + typeSymbol.Name);
            }
        }
Example #4
0
        private static string ConvertTypeUncached(ITypeSymbol typeSymbol)
        {
            if (typeSymbol.IsAnonymousType)
            {
                return(WriteAnonymousObjectCreationExpression.TypeName(typeSymbol.As <INamedTypeSymbol>()));
            }

            var array = typeSymbol as IArrayTypeSymbol;

            if (array != null)
            {
                if (array.ElementType.ToString() == "byte")
                {
                    return("haxe.io.Bytes");                    //byte arrays become haxe.io.Bytes
                }
                else
                {
                    return("Array<" + (ConvertType(array.ElementType) ?? "Dynamic") + ">");
                }
            }

            var typeInfoStr = typeSymbol.ToString();

            var named = typeSymbol as INamedTypeSymbol;

            if (typeSymbol.TypeKind == TypeKind.TypeParameter)
            {
                return(typeSymbol.Name);
            }

            if (typeSymbol.TypeKind == TypeKind.Delegate)
            {
                var dlg = named.DelegateInvokeMethod.As <IMethodSymbol>();
                if (dlg.Parameters.Length == 0)
                {
                    return("(Void -> " + ConvertType(dlg.ReturnType) + ")");
                }
                else
                {
                    return("(" + string.Join("", dlg.Parameters.ToList().Select(o => ConvertType(o.Type) + " -> ")) + ConvertType(dlg.ReturnType) + ")");
                }
            }

            if (typeSymbol.TypeKind == TypeKind.Enum)
            {
                return("Int");                //enums are always ints
            }
            if (named != null && named.Name == "Nullable" && named.ContainingNamespace.ToString() == "System")
            {
                //Nullable types get replaced by our Nullable_ alternatives
                var nullableType = ConvertType(named.TypeArguments.Single());
                if (nullableType == "Int" || nullableType == "Bool" || nullableType == "Float")
                {
                    return("Nullable_" + nullableType);
                }
                else
                {
                    return("Nullable<" + nullableType + ">");
                }
            }

            var typeStr = GenericTypeName(typeSymbol);

            var trans = TypeTranslation.Get(typeStr);

            if (named != null && named.IsGenericType && !named.IsUnboundGenericType && TypeArguments(named).Any() && (trans == null || trans.SkipGenericTypes == false))
            {
                return(ConvertType(named.ConstructUnboundGenericType()) + "<" + string.Join(", ", TypeArguments(named).Select(o => ConvertType(o) ?? "Dynamic")) + ">");
            }


            switch (typeStr)
            {
            case "System.Void":
                return("Void");

            case "System.Boolean":
                return("Bool");

            case "System.Object":
                return("Dynamic");

            case "System.Int64":
            case "System.UInt64":
            case "System.Single":
            case "System.Double":
                return("Float");

            case "System.String":
                return("String");

            case "System.Int32":
            case "System.UInt32":
            case "System.Byte":
            case "System.Int16":
            case "System.UInt16":
            case "System.Char":
                return("Int");


            case "System.Collections.Generic.List<>":
            case "System.Collections.Generic.IList<>":
            case "System.Collections.Generic.Queue<>":
            case "System.Collections.Generic.IEnumerable<>":
            case "System.Collections.Generic.Dictionary<,>.ValueCollection":
            case "System.Collections.Generic.Dictionary<,>.KeyCollection":
            case "System.Collections.Generic.ICollection<>":
            case "System.Linq.IOrderedEnumerable<>":
            case "System.Collections.IEnumerable":
            case "System.Collections.Specialized.NameObjectCollectionBase.KeysCollection":
                return("Array");

            case "System.Array":
                return(null);                        //in haxe, unlike C#, array must always have type arguments.  To work around this, just avoid printing the type anytime we see a bare Array type in C#. haxe will infer it.

            case "System.Collections.Generic.LinkedList<>":
                return("List");

            default:


                if (trans != null)
                {
                    return(trans.As <Translations.TypeTranslation>().Replace(named));
                }

                if (named != null)
                {
                    return(typeSymbol.ContainingNamespace.FullNameWithDot().ToLower() + WriteType.TypeName(named));
                }

                //This type does not get translated and gets used as-is
                return(typeSymbol.ContainingNamespace.FullNameWithDot().ToLower() + typeSymbol.Name);
            }
        }