public static void WriteMember(HaxeWriter writer, ExpressionSyntax expression) { var symbol = Program.GetModel(expression).GetSymbolInfo(expression).Symbol; if (symbol is INamedTypeSymbol) { var translateOpt = TypeTranslation.Get(symbol.ContainingNamespace.FullNameWithDot() + symbol.Name); if (translateOpt != null) { writer.Write(translateOpt.ReplaceWith); } else { writer.Write(symbol.ContainingNamespace.FullNameWithDot().ToLower() + WriteType.TypeName(symbol.As <INamedTypeSymbol>())); } } else { Core.Write(writer, expression); } }
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); } }
private static string ConvertTypeUncached(ITypeSymbol typeSymbol) { if (typeSymbol.IsAnonymousType) { return(WriteAnonymousObjectCreationExpression.TypeName(typeSymbol.As <INamedTypeSymbol>())); } var array = typeSymbol as IArrayTypeSymbol; if (array != null) { return("Array[" + TryConvertType(array.ElementType) + "]"); } 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("() => " + TryConvertType(dlg.ReturnType)); } else { return("(" + string.Join(", ", dlg.Parameters.ToList().Select(o => TryConvertType(o.Type))) + ") => " + TryConvertType(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, if value types, get replaced with the java.lang alternatives. If reference types, just use them as-is var convertedType = TryConvertType(named.TypeArguments.Single()); switch (convertedType) { case "Int": return("java.lang.Integer"); case "Boolean": return("java.lang.Boolean"); case "Byte": return("java.lang.Byte"); case "Short": return("java.lang.Short"); case "Float": return("java.lang.Float"); case "Double": return("java.lang.Double"); case "Char": return("java.lang.Char"); case "Long": return("java.lang.Long"); default: return(convertedType); } } var typeStr = GenericTypeName(typeSymbol); var trans = TypeTranslation.Get(typeStr, named); if (named.IsGenericType() && !named.IsUnboundGenericType && (trans == null || trans.SkipGenericTypes == false)) { return(TryConvertType(named.ConstructUnboundGenericType()) + "[" + string.Join(", ", TypeArguments(named).Select(o => TryConvertType(o))) + "]"); } switch (typeStr) { case "System.Void": return("Unit"); case "System.Boolean": return("Boolean"); case "System.Object": return("Any"); case "System.UInt64": case "System.Double": return("Double"); case "System.Single": return("Float"); case "System.String": return("String"); case "System.Int32": case "System.UInt16": return("Int"); case "System.Int64": case "System.UInt32": return("Long"); case "System.Byte": return("Byte"); case "System.Int16": return("Short"); case "System.Char": return("Char"); case "System.Array": return(null); //in scala, 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#. scala will infer it. default: if (trans != null) { return(trans.As <TypeTranslation>().Replace(named)); } if (named != null) { return(typeSymbol.ContainingNamespace.FullNameWithDot() + WriteType.TypeName(named)); } //This type does not get translated and gets used as-is return(typeSymbol.ContainingNamespace.FullNameWithDot() + typeSymbol.Name); } }
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); } }