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); }
public static void Write(HaxeWriter writer, SyntaxNode node) { TriviaProcessor.ProcessNode(writer, node); if (Program.DoNotWrite.ContainsKey(node)) { return; } if (!(node is ExpressionSyntax) || node is ParenthesizedExpressionSyntax) { Factory(writer, node); } else { var typeInfo = Program.GetModel(node).GetTypeInfo((ExpressionSyntax)node); if (typeInfo.ConvertedType != null && typeInfo.ConvertedType.Name == "Nullable" && (typeInfo.Type == null || (TypeProcessor.ConvertType(typeInfo.Type) != TypeProcessor.ConvertType(typeInfo.ConvertedType)))) { //When assigning into a nullable, we must construct the nullable type. writer.Write("new "); writer.Write(TypeProcessor.ConvertType(typeInfo.ConvertedType)); writer.Write("("); if (typeInfo.Type != null) { Factory(writer, node); } writer.Write(")"); } else { Factory(writer, node); } } }
private static void GoInternal(HaxeWriter writer, BaseMethodDeclarationSyntax method, TypeSyntax returnType, TypeParameterListSyntax typeParameterListOpt, SyntaxList <TypeParameterConstraintClauseSyntax>?constraintClassesOpt) { var methodSymbol = Program.GetModel(method).GetDeclaredSymbol(method); if (method.Modifiers.Any(SyntaxKind.PartialKeyword) && method.Body == null) { //We only want to render out one of the two partial methods. If there's another, skip this one. if (TypeState.Instance.Partials.SelectMany(o => o.Syntax.As <ClassDeclarationSyntax>().Members) .OfType <MethodDeclarationSyntax>() .Except(method as MethodDeclarationSyntax) .Where(o => o.Identifier.ValueText == methodSymbol.Name) .Any()) { return; } } if (methodSymbol.Name == "System.Collections.IEnumerable.GetEnumerator") { return; //we don't support the non-generic enumerator } if (methodSymbol.Name == "GetEnumerator") { WriteGetEnumeratorFunction(writer, method, methodSymbol); return; } writer.WriteIndent(); if (ShouldUseOverrideKeyword(method, methodSymbol)) { writer.Write("override "); } if (method.Modifiers.Any(SyntaxKind.PublicKeyword) || method.Modifiers.Any(SyntaxKind.ProtectedKeyword) || method.Modifiers.Any(SyntaxKind.InternalKeyword)) { writer.Write("public "); } if (method.Modifiers.Any(SyntaxKind.PrivateKeyword)) { writer.Write("private "); } if (method.Modifiers.Any(SyntaxKind.StaticKeyword)) { writer.Write("static "); } writer.Write("function "); var methodName = OverloadResolver.MethodName(methodSymbol); if (methodName == "ToString") { methodName = "toString"; } writer.Write(methodName); if (typeParameterListOpt != null) { writer.Write("<"); writer.Write(string.Join(", ", typeParameterListOpt.Parameters.Select(o => TypeParameter(o, constraintClassesOpt)))); writer.Write(">"); } writer.Write("("); Dictionary <string, ExpressionSyntax> deferredDefaults; WriteParameters(writer, method, methodSymbol, out deferredDefaults); writer.Write(")"); writer.Write(TypeProcessor.ConvertTypeWithColon(returnType)); if (method.Modifiers.Any(SyntaxKind.AbstractKeyword)) { writer.WriteLine(); writer.WriteOpenBrace(); writer.WriteIndent(); if (returnType.ToString() != "void") { writer.Write("return "); //"return" the throw statement to work around haxe limitations } writer.Write("throw new Exception(\"Abstract item called\");\r\n"); writer.WriteCloseBrace(); } else if (method.Parent is InterfaceDeclarationSyntax) { writer.Write(";\r\n"); } else { writer.WriteLine(); writer.WriteOpenBrace(); foreach (var defer in deferredDefaults) { writer.WriteLine("if (" + defer.Key + " == null)"); writer.Indent++; writer.WriteIndent(); writer.Write(defer.Key); writer.Write(" = "); Core.Write(writer, defer.Value); writer.Write(";\r\n"); writer.Indent--; } if (method.Body != null) { foreach (var statement in method.Body.Statements) { Core.Write(writer, statement); } TriviaProcessor.ProcessTrivias(writer, method.Body.DescendantTrivia()); } writer.WriteCloseBrace(); } }
public static void WriteInstanceConstructor(HaxeWriter writer, ConstructorDeclarationSyntax ctorOpt) { writer.WriteIndent(); writer.Write("public function new("); Dictionary <string, ExpressionSyntax> deferredDefaults = null; if (ctorOpt != null) { var methodSymbol = Program.GetModel(ctorOpt).GetDeclaredSymbol(ctorOpt); WriteMethod.WriteParameters(writer, ctorOpt, methodSymbol, out deferredDefaults); } writer.Write(")\r\n"); writer.WriteOpenBrace(); if (deferredDefaults != null) { foreach (var defer in deferredDefaults) { writer.WriteLine("if (" + defer.Key + " == null)"); writer.Indent++; writer.WriteIndent(); writer.Write(defer.Key); writer.Write(" = "); Core.Write(writer, defer.Value); writer.Write(";\r\n"); writer.Indent--; } } if (!TypeState.Instance.DerivesFromObject) { if (ctorOpt == null || ctorOpt.Initializer == null) { writer.WriteLine("super();"); } else { if (ctorOpt.Initializer.ThisOrBaseKeyword.ToString() != "base") { throw new Exception("Constructor overloading not supported " + Utility.Descriptor(ctorOpt)); } writer.WriteIndent(); writer.Write("super("); bool first = true; foreach (var init in ctorOpt.Initializer.ArgumentList.Arguments) { if (first) { first = false; } else { writer.Write(", "); } Core.Write(writer, init.Expression); } writer.Write(");\r\n"); } } if (ctorOpt != null && ctorOpt.Body != null) { foreach (var statement in ctorOpt.Body.As <BlockSyntax>().Statements) { Core.Write(writer, statement); } TriviaProcessor.ProcessTrivias(writer, ctorOpt.Body.DescendantTrivia()); } writer.WriteCloseBrace(); }
public static void WriteInstanceConstructor(HaxeWriter writer, ConstructorDeclarationSyntax ctorOpt) { writer.WriteIndent(); writer.Write("public function new("); if (ctorOpt != null) { var firstParameter = true; foreach (var parameter in ctorOpt.ParameterList.Parameters) { if (firstParameter) { firstParameter = false; } else { writer.Write(", "); } writer.Write(parameter.Identifier.ValueText); writer.Write(TypeProcessor.ConvertTypeWithColon(parameter.Type)); if (parameter.Default != null) { writer.Write(" = "); Core.Write(writer, parameter.Default.Value); } } } writer.Write(")\r\n"); writer.WriteOpenBrace(); if (!TypeState.Instance.DerivesFromObject) { if (ctorOpt == null || ctorOpt.Initializer == null) { writer.WriteLine("super();"); } else { if (ctorOpt.Initializer.ThisOrBaseKeyword.ToString() != "base") { throw new Exception("Constructor overloading not supported " + Utility.Descriptor(ctorOpt)); } writer.WriteIndent(); writer.Write("super("); bool first = true; foreach (var init in ctorOpt.Initializer.ArgumentList.Arguments) { if (first) { first = false; } else { writer.Write(", "); } Core.Write(writer, init.Expression); } writer.Write(");\r\n"); } } foreach (var field in TypeState.Instance.AllMembers .OfType <BaseFieldDeclarationSyntax>() .Where(o => !o.Modifiers.Any(SyntaxKind.StaticKeyword)) .SelectMany(o => o.Declaration.Variables) .Where(o => (o.Initializer != null && !WriteField.IsConst(o.Parent.Parent.As <BaseFieldDeclarationSyntax>().Modifiers, o.Initializer, o.Parent.As <VariableDeclarationSyntax>().Type)) || (o.Initializer == null && GenerateInitializerForFieldWithoutInitializer(o.Parent.As <VariableDeclarationSyntax>().Type)) || o.Parent.Parent is EventFieldDeclarationSyntax)) { var parentType = field.Parent.As <VariableDeclarationSyntax>().Type; writer.WriteIndent(); writer.Write(field.Identifier.ValueText); writer.Write(" = "); if (field.Parent.Parent is EventFieldDeclarationSyntax) { writer.Write("new CsEvent<"); writer.Write(TypeProcessor.ConvertType(parentType)); writer.Write(">()"); } else if (field.Initializer == null) { if (TypeProcessor.ValueToReference(parentType)) { writer.Write("new "); writer.Write(TypeProcessor.ConvertType(parentType)); writer.Write("()"); } else { writer.Write(TypeProcessor.DefaultValue(TypeProcessor.ConvertType(parentType))); } } else { Core.Write(writer, field.Initializer.Value); } writer.Write(";\r\n"); } if (ctorOpt != null && ctorOpt.Body != null) { foreach (var statement in ctorOpt.Body.As <BlockSyntax>().Statements) { Core.Write(writer, statement); } TriviaProcessor.ProcessTrivias(writer, ctorOpt.Body.DescendantTrivia()); } writer.WriteCloseBrace(); }
public static void Go(HaxeWriter writer, MethodDeclarationSyntax method) { if (method.Modifiers.Any(SyntaxKind.PartialKeyword) && method.Body == null) { //We only want to render out one of the two partial methods. If there's another, skip this one. if (TypeState.Instance.Partials.SelectMany(o => o.Syntax.As <ClassDeclarationSyntax>().Members) .OfType <MethodDeclarationSyntax>() .Except(method) .Where(o => o.Identifier.ValueText == method.Identifier.ValueText) .Any()) { return; } } if (method.Identifier.ValueText == "GetEnumerator") { return; //skip GetEnumerator methods -- haxe can't enumerate on objects. TODO: Render these out, but convert them to array-returning methods } var methodSymbol = Program.GetModel(method).GetDeclaredSymbol(method); writer.WriteIndent(); if (ShouldUseOverrideKeyword(method, methodSymbol)) { writer.Write("override "); } if (method.Modifiers.Any(SyntaxKind.PublicKeyword) || method.Modifiers.Any(SyntaxKind.ProtectedKeyword) || method.Modifiers.Any(SyntaxKind.InternalKeyword)) { writer.Write("public "); } if (method.Modifiers.Any(SyntaxKind.PrivateKeyword)) { writer.Write("private "); } if (method.Modifiers.Any(SyntaxKind.StaticKeyword)) { writer.Write("static "); } writer.Write("function "); var methodName = OverloadResolver.MethodName(methodSymbol); if (methodName == "ToString") { methodName = "toString"; } writer.Write(methodName); if (method.TypeParameterList != null) { writer.Write("<"); writer.Write(string.Join(", ", method.TypeParameterList.Parameters.Select(o => TypeParameter(o, method.ConstraintClauses)))); writer.Write(">"); } writer.Write("("); var deferredDefaults = new Dictionary <string, ExpressionSyntax>(); var firstParam = true; foreach (var parameter in method.ParameterList.Parameters) { bool isRef = parameter.Modifiers.Any(SyntaxKind.OutKeyword) || parameter.Modifiers.Any(SyntaxKind.RefKeyword); if (firstParam) { firstParam = false; } else { writer.Write(", "); } writer.Write(parameter.Identifier.ValueText); if (isRef) { writer.Write(":CsRef<"); writer.Write(TypeProcessor.ConvertType(parameter.Type)); writer.Write(">"); Program.RefOutSymbols.TryAdd(Program.GetModel(method).GetDeclaredSymbol(parameter), null); } else { writer.Write(TypeProcessor.ConvertTypeWithColon(parameter.Type)); } if (parameter.Default != null) { writer.Write(" = "); if (TypeProcessor.ConvertType(parameter.Type).StartsWith("Nullable")) { writer.Write("null"); deferredDefaults.Add(parameter.Identifier.ValueText, parameter.Default.Value); } else { Core.Write(writer, parameter.Default.Value); } } } writer.Write(")"); writer.Write(TypeProcessor.ConvertTypeWithColon(method.ReturnType)); if (method.Modifiers.Any(SyntaxKind.AbstractKeyword)) { writer.WriteLine(); writer.WriteOpenBrace(); writer.WriteIndent(); if (method.ReturnType.ToString() != "void") { writer.Write("return "); //"return" the throw statement to work around haxe limitations } writer.Write("throw new Exception(\"Abstract item called\");\r\n"); writer.WriteCloseBrace(); } else if (method.Parent is InterfaceDeclarationSyntax) { writer.Write(";\r\n"); } else { writer.WriteLine(); writer.WriteOpenBrace(); foreach (var defer in deferredDefaults) { writer.WriteLine("if (" + defer.Key + " == null)"); writer.Indent++; writer.WriteIndent(); writer.Write(defer.Key); writer.Write(" = "); Core.Write(writer, defer.Value); writer.Write(";\r\n"); writer.Indent--; } if (method.Body != null) { foreach (var statement in method.Body.Statements) { Core.Write(writer, statement); } TriviaProcessor.ProcessTrivias(writer, method.Body.DescendantTrivia()); } writer.WriteCloseBrace(); } }