Пример #1
0
        public static void Go(ScalaWriter writer, SyntaxTokenList modifiers, string name, TypeSyntax type, EqualsValueClauseSyntax initializerOpt = null)
        {
            writer.WriteIndent();

            var isConst = IsConst(modifiers, initializerOpt, type);

            WriteFieldModifiers(writer, modifiers);
            if (isConst)
            {
                writer.Write("final val ");
            }
            else
            {
                writer.Write("var ");
            }

            writer.Write(name);
            writer.Write(TypeProcessor.ConvertTypeWithColon(type));
            writer.Write(" = ");

            if (initializerOpt != null)
            {
                Core.Write(writer, initializerOpt.Value);
            }
            else
            {
                writer.Write(TypeProcessor.DefaultValue(type));
            }

            writer.Write(";");
            writer.WriteLine();
        }
        public static void Go(ScalaWriter writer, LocalDeclarationStatementSyntax declaration)
        {
            foreach (var variable in declaration.Declaration.Variables)
            {
                var symbol = Program.GetModel(declaration).GetDeclaredSymbol(variable);

                var isRef = UsedAsRef(variable, symbol);

                writer.WriteIndent();
                writer.Write("var ");
                writer.Write(WriteIdentifierName.TransformIdentifier(variable.Identifier.ValueText));

                if (isRef)
                {
                    var typeStr = TypeProcessor.ConvertType(declaration.Declaration.Type);

                    writer.Write(":CsRef[");
                    writer.Write(typeStr);
                    writer.Write("]");

                    Program.RefOutSymbols.TryAdd(symbol, null);

                    writer.Write(" = new CsRef[");
                    writer.Write(typeStr);
                    writer.Write("](");

                    if (variable.Initializer == null)
                    {
                        writer.Write(TypeProcessor.DefaultValue(declaration.Declaration.Type));
                    }
                    else
                    {
                        Core.Write(writer, variable.Initializer.As <EqualsValueClauseSyntax>().Value);
                    }

                    writer.Write(")");
                }
                else
                {
                    writer.Write(TypeProcessor.ConvertTypeWithColon(declaration.Declaration.Type));
                    writer.Write(" = ");

                    if (variable.Initializer != null)
                    {
                        Core.Write(writer, variable.Initializer.As <EqualsValueClauseSyntax>().Value);
                    }
                    else
                    {
                        writer.Write(TypeProcessor.DefaultValue(declaration.Declaration.Type));
                    }
                }

                writer.Write(";\r\n");
            }
        }
Пример #3
0
        public static void WriteAnonymousType(AnonymousObjectCreationExpressionSyntax syntax)
        {
            var type     = Program.GetModel(syntax).GetTypeInfo(syntax).Type.As <INamedTypeSymbol>();
            var anonName = TypeName(type);

            using (var writer = new ScalaWriter("anonymoustypes", StripGeneric(anonName)))
            {
                var fields = type.GetMembers().OfType <IPropertySymbol>().OrderBy(o => o.Name).ToList();

                writer.WriteLine("package anonymoustypes;");
                WriteImports.Go(writer);

                writer.WriteIndent();
                writer.Write("class ");
                writer.Write(anonName);
                writer.Write("(");
                bool first = true;
                foreach (var field in fields)
                {
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        writer.Write(", ");
                    }

                    writer.Write("_");
                    writer.Write(WriteIdentifierName.TransformIdentifier(field.Name));
                    writer.Write(TypeProcessor.ConvertTypeWithColon(field.Type));
                }
                writer.Write(")\r\n");


                writer.WriteOpenBrace();



                foreach (var field in fields)
                {
                    writer.WriteIndent();
                    writer.Write("final var ");
                    writer.Write(WriteIdentifierName.TransformIdentifier(field.Name));
                    writer.Write(TypeProcessor.ConvertTypeWithColon(field.Type));
                    writer.Write(" = _");
                    writer.Write(WriteIdentifierName.TransformIdentifier(field.Name));
                    writer.Write(";\r\n");
                }



                writer.WriteCloseBrace();
            }
        }
        public static void Go(ScalaWriter writer, ConversionOperatorDeclarationSyntax method)
        {
            if (method.ImplicitOrExplicitKeyword.Kind() != SyntaxKind.ExplicitKeyword)
            {
                throw new Exception("Implicit cast operators are not supported " + Utility.Descriptor(method));
            }

            writer.WriteIndent();
            writer.Write("def op_Explicit_");
            writer.Write(TypeProcessor.ConvertType(method.Type));
            writer.Write("(");

            bool firstParam = true;

            foreach (var param in method.ParameterList.Parameters)
            {
                if (firstParam)
                {
                    firstParam = false;
                }
                else
                {
                    writer.Write(", ");
                }

                writer.Write(WriteIdentifierName.TransformIdentifier(param.Identifier.ValueText));
                writer.Write(TypeProcessor.ConvertTypeWithColon(param.Type));
            }

            writer.Write(")");
            writer.Write(TypeProcessor.ConvertTypeWithColon(method.Type));
            writer.Write(" =\r\n");

            writer.WriteOpenBrace();

            foreach (var statement in method.Body.Statements)
            {
                Core.Write(writer, statement);
            }

            writer.WriteCloseBrace();
        }
Пример #5
0
        public static void Go(ScalaWriter writer, PropertyDeclarationSyntax property)
        {
            Action <AccessorDeclarationSyntax, bool> writeRegion = (region, get) =>
            {
                writer.WriteIndent();

                if (property.Modifiers.Any(SyntaxKind.OverrideKeyword))
                {
                    writer.Write("override ");
                }
                if (property.Modifiers.Any(SyntaxKind.PrivateKeyword))
                {
                    writer.Write("private ");
                }

                writer.Write("def ");
                writer.Write(WriteIdentifierName.TransformIdentifier(property.Identifier.ValueText));

                if (get)
                {
                    writer.Write(TypeProcessor.ConvertTypeWithColon(property.Type));
                }
                else
                {
                    writer.Write("_=(value");
                    writer.Write(TypeProcessor.ConvertTypeWithColon(property.Type));
                    writer.Write(")");
                }

                if (property.Modifiers.Any(SyntaxKind.AbstractKeyword) || region.Body == null)
                {
                    writer.Write(";\r\n");
                }
                else
                {
                    writer.Write(" =\r\n");
                    Core.WriteBlock(writer, region.Body.As <BlockSyntax>());
                }
            };

            var getter = property.AccessorList.Accessors.SingleOrDefault(o => o.Keyword.Kind() == SyntaxKind.GetKeyword);
            var setter = property.AccessorList.Accessors.SingleOrDefault(o => o.Keyword.Kind() == SyntaxKind.SetKeyword);

            if (getter == null && setter == null)
            {
                throw new Exception("Property must have either a get or a set");
            }

            if (getter != null && setter != null && setter.Body == null && getter.Body == null)
            {
                //Both get and set are null, which means this is an automatic property.  For our purposes, this is the equivilant of a field
                WriteField.Go(writer, property.Modifiers, WriteIdentifierName.TransformIdentifier(property.Identifier.ValueText), property.Type);
            }
            else
            {
                if (getter != null)
                {
                    writeRegion(getter, true);
                }
                else if (setter != null)
                {
                    //Scala does not allow having a setter without a getter. Write out a getter.
                    writer.Write("def ");
                    writer.Write(WriteIdentifierName.TransformIdentifier(property.Identifier.ValueText));
                    writer.Write(TypeProcessor.ConvertTypeWithColon(property.Type));
                    writer.Write(" =\r\n");
                    writer.WriteOpenBrace();
                    writer.WriteLine("throw new Exception(\"No getter defined\");");
                    writer.WriteCloseBrace();
                }

                if (setter != null)
                {
                    writeRegion(setter, false);
                }
            }
        }
Пример #6
0
        public static void Go(ScalaWriter writer, ForStatementSyntax forStatement)
        {
            var info = new LoopInfo(forStatement);

            writer.WriteLine("{ //for");
            writer.Indent++;
            info.WritePreLoop(writer);

            if (forStatement.Declaration != null)
            {
                foreach (var variable in forStatement.Declaration.Variables)
                {
                    writer.WriteIndent();
                    writer.Write("var ");
                    writer.Write(WriteIdentifierName.TransformIdentifier(variable.Identifier.ValueText));
                    writer.Write(TypeProcessor.ConvertTypeWithColon(forStatement.Declaration.Type));

                    if (variable.Initializer != null)
                    {
                        writer.Write(" = ");
                        Core.Write(writer, variable.Initializer.Value);
                    }

                    writer.Write(";\r\n");
                }
            }

            foreach (var init in forStatement.Initializers)
            {
                writer.WriteIndent();
                Core.Write(writer, init);
                writer.Write(";\r\n");
            }

            writer.WriteIndent();
            writer.Write("while (");

            if (forStatement.Condition == null)
            {
                writer.Write("true");
            }
            else
            {
                Core.Write(writer, forStatement.Condition);
            }

            writer.Write(")\r\n");
            writer.WriteOpenBrace();

            info.WriteLoopOpening(writer);
            Core.WriteStatementAsBlock(writer, forStatement.Statement, false);
            info.WriteLoopClosing(writer);

            foreach (var iterator in forStatement.Incrementors)
            {
                writer.WriteIndent();
                Core.Write(writer, iterator);
                writer.Write(";\r\n");
            }

            writer.WriteCloseBrace();
            info.WritePostLoop(writer);
            writer.Indent--;
            writer.WriteLine("} //end for");
        }
Пример #7
0
        public static void Go()
        {
            var partials = TypeState.Instance.Partials;
            var first    = partials.First();



            using (var writer = new ScalaWriter(first.Symbol.ContainingNamespace.FullName(), TypeState.Instance.TypeName))
            {
                var bases = partials
                            .Select(o => o.Syntax.BaseList)
                            .Where(o => o != null)
                            .SelectMany(o => o.Types)
                            .Select(o => Program.GetModel(o).GetTypeInfo(o.Type).ConvertedType)
                            .Distinct()
                            .ToList();

                var interfaces = bases.Where(o => o.TypeKind == TypeKind.Interface).ToList();

                //TypeState.Instance.DerivesFromObject = bases.Count == interfaces.Count;

                var package = first.Symbol.ContainingNamespace.FullName();
                if (package.Length > 0)
                {
                    writer.WriteLine("package " + package + @";");
                }

                WriteImports.Go(writer);

                if (first.Syntax is EnumDeclarationSyntax)
                {
                    WriteEnum.Go(writer, TypeState.Instance.Partials.Select(o => o.Syntax).Cast <EnumDeclarationSyntax>().SelectMany(o => o.Members).Where(o => !Program.DoNotWrite.ContainsKey(o)));
                    return;
                }


                TypeState.Instance.AllMembers = partials.Select(o => o.Syntax).Cast <TypeDeclarationSyntax>().SelectMany(o => o.Members).Where(o => !Program.DoNotWrite.ContainsKey(o)).ToList();

                var allMembersToWrite = TypeState.Instance.AllMembers
                                        .Where(member => !(member is TypeDeclarationSyntax) &&
                                               !(member is EnumDeclarationSyntax) &&
                                               !(member is DelegateDeclarationSyntax))
                                        .ToList();

                var instanceCtors = TypeState.Instance.AllMembers.OfType <ConstructorDeclarationSyntax>()
                                    .Where(o => !o.Modifiers.Any(SyntaxKind.StaticKeyword))
                                    .ToList();

                if (instanceCtors.Count > 1)
                {
                    throw new Exception("Overloaded constructors are not supported.  Consider changing all but one to static Create methods " + Utility.Descriptor(first.Syntax));
                }

                var ctorOpt = instanceCtors.SingleOrDefault();

                foreach (var staticMembers in new[] { true, false })
                {
                    var membersToWrite = allMembersToWrite.Where(o => IsStatic(o) == staticMembers).ToList();

                    if (membersToWrite.Count == 0 && (staticMembers || partials.Any(o => o.Syntax.Modifiers.Any(SyntaxKind.StaticKeyword))))
                    {
                        continue;
                    }

                    if (staticMembers)
                    {
                        writer.Write("object ");
                    }
                    else if (first.Syntax.Kind() == SyntaxKind.InterfaceDeclaration)
                    {
                        writer.Write("trait ");
                    }
                    else
                    {
                        if (partials.Any(o => o.Syntax.Modifiers.Any(SyntaxKind.AbstractKeyword)))
                        {
                            writer.Write("abstract ");
                        }

                        writer.Write("class ");
                    }

                    writer.Write(TypeState.Instance.TypeName);



                    if (!staticMembers && first.Syntax is TypeDeclarationSyntax)
                    {
                        //Look for generic arguments
                        var genericArgs = partials
                                          .Select(o => o.Syntax)
                                          .Cast <TypeDeclarationSyntax>()
                                          .Where(o => o.TypeParameterList != null)
                                          .SelectMany(o => o.TypeParameterList.Parameters)
                                          .ToList();

                        if (genericArgs.Count > 0)
                        {
                            writer.Write("[");
                            writer.Write(string.Join(", ", genericArgs.Select(o => TypeParameter(o))));
                            writer.Write("]");
                        }

                        //Write constructor arguments
                        if (ctorOpt != null && ctorOpt.ParameterList.Parameters.Count > 0)
                        {
                            writer.Write("(");
                            var firstParameter = true;
                            foreach (var parameter in ctorOpt.ParameterList.Parameters)
                            {
                                if (firstParameter)
                                {
                                    firstParameter = false;
                                }
                                else
                                {
                                    writer.Write(", ");
                                }

                                writer.Write(WriteIdentifierName.TransformIdentifier(parameter.Identifier.ValueText));
                                writer.Write(TypeProcessor.ConvertTypeWithColon(parameter.Type));

                                if (parameter.Default != null)
                                {
                                    writer.Write(" = ");
                                    Core.Write(writer, parameter.Default.Value);
                                }
                            }
                            writer.Write(")");
                        }

                        bool firstBase = true;
                        foreach (var baseType in bases.OrderBy(o => o.TypeKind == TypeKind.Interface ? 1 : 0))
                        {
                            if (firstBase)
                            {
                                writer.Write(" extends ");
                            }
                            else
                            {
                                writer.Write(" with ");
                            }

                            writer.Write(TypeProcessor.ConvertType(baseType));


                            if (firstBase && ctorOpt != null && ctorOpt.Initializer != null && ctorOpt.Initializer.ArgumentList.Arguments.Count > 0)
                            {
                                writer.Write("(");
                                bool firstArg = true;
                                foreach (var init in ctorOpt.Initializer.ArgumentList.Arguments)
                                {
                                    if (firstArg)
                                    {
                                        firstArg = false;
                                    }
                                    else
                                    {
                                        writer.Write(", ");
                                    }

                                    Core.Write(writer, init.Expression);
                                }
                                writer.Write(")");
                            }

                            firstBase = false;
                        }
                    }

                    writer.Write("\r\n");

                    writer.WriteOpenBrace();

                    var fields    = membersToWrite.OfType <FieldDeclarationSyntax>().ToList();
                    var nonFields = membersToWrite.Except(fields);

                    fields = SortFields(fields);

                    foreach (var member in fields)
                    {
                        Core.Write(writer, member);
                    }
                    foreach (var member in nonFields)
                    {
                        Core.Write(writer, member);
                    }


                    if (!staticMembers && ctorOpt != null && ctorOpt.Body != null && ctorOpt.Body.As <BlockSyntax>().Statements.Count > 0)
                    {
                        writer.WriteLine();
                        Core.WriteBlock(writer, ctorOpt.Body.As <BlockSyntax>(), true); //render braces so local ctor variables don't bleed out into fields
                    }


                    writer.WriteCloseBrace();
                }
            }
        }
Пример #8
0
        public static void Go(ScalaWriter 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;
                }
            }

            var methodSymbol = Program.GetModel(method).GetDeclaredSymbol(method);


            if (method.Identifier.ValueText == "GetEnumerator")
            {
                WriteGetEnumeratorFunction(writer, method, methodSymbol);
                return;
            }


            writer.WriteIndent();

            if (ShouldUseOverrideKeyword(method, methodSymbol))
            {
                writer.Write("override ");
            }
            if (method.Modifiers.Any(SyntaxKind.PrivateKeyword))
            {
                writer.Write("private ");
            }

            writer.Write("def ");
            var methodName = OverloadResolver.MethodName(methodSymbol);

            if (methodName == "ToString")
            {
                methodName = "toString";
            }
            else if (methodName == "Equals")
            {
                methodName = "equals";
            }
            else if (methodName == "GetHashCode")
            {
                methodName = "hashCode";
            }
            else if (methodName == "Main")
            {
                methodName = "main";
            }

            writer.Write(methodName);

            if (method.TypeParameterList != null)
            {
                writer.Write("[");
                writer.Write(string.Join(", ", method.TypeParameterList.Parameters.Select(o => TypeParameter(o, methodSymbol, method))));
                writer.Write("]");
            }

            writer.Write("(");

            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(WriteIdentifierName.TransformIdentifier(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(" = ");
                    Core.Write(writer, parameter.Default.Value);
                }
            }

            writer.Write(")");
            bool returnsVoid = method.ReturnType.ToString() == "void";

            if (!returnsVoid)
            {
                writer.Write(TypeProcessor.ConvertTypeWithColon(method.ReturnType));
            }

            if (method.Modifiers.Any(SyntaxKind.AbstractKeyword) || method.Parent is InterfaceDeclarationSyntax)
            {
                writer.Write(";\r\n");
            }
            else
            {
                if (!returnsVoid)
                {
                    writer.Write(" =");
                }

                writer.Write("\r\n");
                writer.WriteOpenBrace();

                if (method.Body != null)
                {
                    foreach (var statement in method.Body.Statements)
                    {
                        Core.Write(writer, statement);
                    }

                    TriviaProcessor.ProcessTrivias(writer, method.Body.DescendantTrivia());
                }

                writer.WriteCloseBrace();
            }
        }
Пример #9
0
        public static void Go(ScalaWriter writer, MemberAccessExpressionSyntax expression)
        {
            var model = Program.GetModel(expression);

            var memberName = expression.Name.Identifier.ValueText;
            var type       = model.GetTypeInfo(expression.Expression).ConvertedType;
            var typeStr    = TypeProcessor.GenericTypeName(type);

            if (expression.Expression is PredefinedTypeSyntax)
            {
                if (memberName == "MaxValue" || memberName == "MinValue" || memberName == "NaN")
                {
                    var predefined = expression.Expression.ToString();

                    if (predefined.StartsWith("u"))
                    {
                        //Scala does not have unsigned types. Forward these to CsScala
                        writer.Write("System.CsScala.");
                        writer.Write(predefined);
                        writer.Write(memberName);
                    }
                    else
                    {
                        writer.Write(predefined[0].ToString().ToUpper());
                        writer.Write(predefined.Substring(1));
                        writer.Write(".");
                        writer.Write(memberName);
                    }
                }
                else
                {
                    var field = System.Type.GetType(typeStr).GetField(memberName);

                    if (field == null)
                    {
                        throw new Exception("Cannot use " + memberName + " as a field.  If you're passing a function, wrap a closure around it. " + Utility.Descriptor(expression));
                    }
                    var val = field.GetValue(null);
                    if (val is string)
                    {
                        writer.Write("\"" + val + "\"");
                    }
                    else
                    {
                        writer.Write(val.ToString());
                    }
                }
            }
            else if (type.OriginalDefinition is INamedTypeSymbol && type.OriginalDefinition.As <INamedTypeSymbol>().SpecialType == SpecialType.System_Nullable_T)
            {
                switch (memberName)
                {
                case "HasValue":
                    writer.Write("(");
                    WriteMember(writer, expression.Expression);
                    writer.Write(" != null)");
                    break;

                case "Value":
                    var nullableType = TypeProcessor.ConvertType(type.As <INamedTypeSymbol>().TypeArguments.Single());
                    WriteMember(writer, expression.Expression);

                    if (TypeProcessor.IsPrimitiveType(nullableType))
                    {
                        writer.Write(".");
                        writer.Write(nullableType[0].ToString().ToLower());
                        writer.Write(nullableType.Substring(1));
                        writer.Write("Value()");
                    }
                    break;

                default:
                    throw new Exception("Need handler for Nullable." + memberName + " " + Utility.Descriptor(expression));
                }
            }
            else
            {
                var translate = PropertyTranslation.Get(typeStr, memberName);

                if (translate != null && translate.ExtensionMethod != null)
                {
                    writer.Write(translate.ExtensionMethod);
                    writer.Write("(");
                    if (!(model.GetSymbolInfo(expression.Expression).Symbol is INamedTypeSymbol))
                    {
                        Core.Write(writer, expression.Expression);
                    }
                    writer.Write(")");
                    return;
                }

                if (translate != null)
                {
                    memberName = translate.ReplaceWith;
                }
                else
                {
                    memberName = WriteIdentifierName.TransformIdentifier(memberName);
                }

                if (type != null) //if type is null, then we're just a namespace.  We can ignore these.
                {
                    WriteMember(writer, expression.Expression);
                    writer.Write(".");
                }

                writer.Write(memberName);

                if (expression.Name is GenericNameSyntax)
                {
                    var gen = expression.Name.As <GenericNameSyntax>();

                    writer.Write("[");

                    bool first = true;
                    foreach (var g in gen.TypeArgumentList.Arguments)
                    {
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            writer.Write(", ");
                        }

                        writer.Write(TypeProcessor.ConvertTypeWithColon(g));
                    }

                    writer.Write("]");
                }
            }
        }
Пример #10
0
        private static void Go(ScalaWriter writer, IEnumerable <ParameterSyntax> parameters, SyntaxNode body, TypeInfo type)
        {
            var methodSymbol = type.ConvertedType.As <INamedTypeSymbol>().DelegateInvokeMethod.As <IMethodSymbol>();

            writer.Write("(");

            for (int pi = 0; pi < parameters.Count(); pi++)
            {
                var parameter = parameters.ElementAt(pi);
                if (pi > 0)
                {
                    writer.Write(", ");
                }

                writer.Write(WriteIdentifierName.TransformIdentifier(parameter.Identifier.ValueText));
                if (parameter.Type != null)
                {
                    writer.Write(TypeProcessor.ConvertTypeWithColon(parameter.Type));
                }
                else
                {
                    writer.Write(TypeProcessor.ConvertTypeWithColon(methodSymbol.Parameters[pi].Type));
                }
            }

            writer.Write(") => ");

            bool returnsVoid = methodSymbol.ReturnType.ToString() == "void";

            if (body is BlockSyntax)
            {
                writer.Write("\r\n");
                writer.WriteOpenBrace();

                var statements = body.As <BlockSyntax>().Statements;

                var lastStatement = statements.LastOrDefault() as ReturnStatementSyntax;

                var returnStatements = FindReturnStatements(body);

                if (returnStatements.Count > 0 && (lastStatement == null || returnStatements.Except(lastStatement).Any()))
                {
                    //Lambda has branching returns.  We must use a breakable block since scala can't return from a lambda like C# can
                    TypeState.Instance.InLambdaBreakable++;

                    writer.WriteLine("val __lambdabreak = new Breaks;");

                    if (!returnsVoid)
                    {
                        writer.WriteIndent();
                        writer.Write("var __lambdareturn:");
                        writer.Write(TypeProcessor.ConvertType(methodSymbol.ReturnType));
                        writer.Write(" = ");
                        writer.Write(TypeProcessor.DefaultValue(methodSymbol.ReturnType));
                        writer.Write(";\r\n");
                    }

                    writer.WriteLine("__lambdabreak.breakable");
                    writer.WriteOpenBrace();

                    foreach (var statement in statements)
                    {
                        if (statement == lastStatement && !returnsVoid)
                        {
                            //Manually write it so we avoid the final break that WriteReturnStatement does
                            writer.WriteIndent();
                            writer.Write("__lambdareturn = ");
                            Core.Write(writer, lastStatement.Expression);
                            writer.Write(";\r\n");
                        }
                        else
                        {
                            Core.Write(writer, statement);
                        }
                    }

                    TriviaProcessor.ProcessTrivias(writer, body.DescendantTrivia());

                    writer.WriteCloseBrace();

                    if (!returnsVoid)
                    {
                        writer.WriteLine("__lambdareturn;");
                    }

                    TypeState.Instance.InLambdaBreakable--;
                }
                else
                {
                    foreach (var statement in statements)
                    {
                        if (statement == lastStatement)
                        {
                            writer.WriteIndent();
                            Core.Write(writer, lastStatement.Expression);
                            writer.Write(";\r\n");
                        }
                        else
                        {
                            Core.Write(writer, statement);
                        }
                    }
                }

                writer.Indent--;
                writer.WriteIndent();
                writer.Write("}");
            }
            else
            {
                writer.Write(" { ");
                Core.Write(writer, body);
                writer.Write("; }");
            }

            if (!returnsVoid)
            {
                writer.Write(TypeProcessor.ConvertTypeWithColon(methodSymbol.ReturnType));
            }
        }