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 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 #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))
            {
                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);
            }
        }