public static void WriteIt(OutputWriter writer, MethodDeclarationSyntax method, bool isProxy = true, IEnumerable<ITypeSymbol> virtualGenericClasses=null)
        {
            var methodSymbol = (IMethodSymbol) TypeProcessor.GetDeclaredSymbol(method);
            var isYield = YieldChecker.HasYield(method);//method.DescendantNodes().OfType<YieldStatementSyntax>().Any();


            writer.WriteLine();




            var pinvokeAttributes = method.GetAttribute(Context.DllImport);
            var isInternalPInvoke = pinvokeAttributes == null && method.Modifiers.Any(SyntaxKind.ExternKeyword);

            //TODO: Improve partial class / method support -- partials classes work, methods need minor work ...
            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 (Context.Instance.Partials.SelectMany(o => o.Syntax.As<ClassDeclarationSyntax>().Members)
                    .OfType<MethodDeclarationSyntax>()
                    .Except(method).Any(o => o.Identifier.Text == method.Identifier.Text))
                    return;
            }



            var accessString = "";



            var isInterface = method.Parent is InterfaceDeclarationSyntax;

            ITypeSymbol iface;
            ISymbol[] proxies;
            var methodName = MemberUtilities.GetMethodName(method, ref isInterface, out iface, out proxies); //
            var originalMethodName = methodName;
            var containingType = iface == null ? methodSymbol.ContainingType : iface;
            if (virtualGenericClasses != null)
            {
                methodName = TypeProcessor.ConvertType(containingType, false, false, false).Replace(".","_") + "_"+methodName;
                accessString = "public static final ";
            }
            else if (methodName == "Main" /*&& method.Modifiers.Any(SyntaxKind.PublicKeyword)*/&&
                method.Modifiers.Any(SyntaxKind.StaticKeyword))
            {
                accessString = ("public ");

                accessString += ("static ");

                var methodCall = methodSymbol.ContainingNamespace.FullName() + "." +
                                 methodSymbol.ContainingType.FullName() +
                                 "." + methodName + (method.ParameterList.Parameters.Count < 1 ? "();" : "(null);");
                //: "(new Array_T!(String)(args));"); // for now args not supported
                Context.Instance.EntryMethod = methodCall;
            }

            else
            {
                accessString = MemberUtilities.GetAccessModifiers(method, isInterface || methodSymbol.IsAbstract);
            }


            var returnTypeString = TypeProcessor.ConvertType(method.ReturnType, true) + " ";
            var methodSignatureString = "";
            if (method.ReturnType.ToString() == "void")
                returnTypeString = ("void ");

            methodSignatureString += methodName;

            var genericParameters = "";

            if (method.TypeParameterList != null)
            {
                var genericArgs = method.TypeParameterList.Parameters.ToList();

                //				if (genericArgs.Count > 0)
                //				{
                //					writer.Write("( ");
                //					writer.Write(string.Join(" , ", genericArgs.Select(o => " " + o)));
                //					writer.Write(" )\r\n");
                //				}

                if (genericArgs.Count > 0) // && !methodSymbol.ContainingType.IsGenericType) // doesnt matter
                {
                    genericParameters += ("(");
                    genericParameters += (string.Join(",", genericArgs.Select(o => o)));
                    genericParameters += (")");
                }
            }
            methodSignatureString += genericParameters;
            var @params = GetParameterListAsString(method.ParameterList.Parameters,
                iface: proxies == null ? iface : null, genericClass: virtualGenericClasses != null ? containingType : null);


//            if (virtualGenericClasses != null)
//            {
//                @params = TypeProcessor.ConvertType() +  ", " + @params;
//            }
            string constraints = GetMethodConstraints(method);

            if (isInterface || method.Modifiers.Any(SyntaxKind.AbstractKeyword))
            {
                writer.WriteLine(accessString + returnTypeString + methodSignatureString + @params + constraints + ";");

                return;
            }

            writer.WriteLine(accessString + returnTypeString + methodSignatureString + @params + constraints);

            writer.OpenBrace();

            if (isProxy)
            {
                @params = GetParameterListAsString(method.ParameterList.Parameters, includeTypes: false);

                if (virtualGenericClasses !=null)
                {
                    /*
                      public final static void Program_IBase_GenericVirtual_Dispatch(T)(Program.IBase aobj)
      {
        Object obj = cast(Object) aobj;
        if((typeid(obj)==typeid(Program.B)))
            (cast(Program.B)obj).GenericVirtual!(T)();
        if((typeid(obj)==typeid(Program.A)))
            (cast(Program.A)obj).GenericVirtual!(T)();

      }    
                    */
                    writer.WriteLine("NObject ___obj = cast(NObject)__obj;");
                    foreach (var virtualGenericClass in virtualGenericClasses)
                    {
                        var className = TypeProcessor.ConvertType(virtualGenericClass);
                        writer.WriteLine("if(typeid(___obj)==typeid({0}))", className);

                        if (method.ReturnType.ToString() == "void")
                            writer.WriteLine("(cast({0})___obj)." +   originalMethodName + "!" + genericParameters + @params + ";", className);
                        else
                            writer.WriteLine("return (cast({0})___obj)."  + methodSignatureString + "!" + genericParameters + ";", className);
                    }
                }
                else
                {
                    if (method.ReturnType.ToString() == "void")
                        writer.WriteLine("__Value." + methodName + @params + ";");
                    else
                        writer.WriteLine("return __Value." + methodName + @params + ";");
                }
            }
            else
            {

                if (!isProxy && isYield)
                {
                    var namedTypeSymbol = methodSymbol.ReturnType as INamedTypeSymbol;
                    if (namedTypeSymbol != null)
                    {
                       // var iteratortype = namedTypeSymbol.TypeArguments[0];

                        var className =  methodSymbol.GetYieldClassName() +(
                   ( ((INamedTypeSymbol)methodSymbol.ReturnType).TypeArguments.Any() && ((INamedTypeSymbol)methodSymbol.ReturnType).TypeArguments[0].TypeKind==TypeKind.TypeParameter) ? "__G" : "");


                        methodSignatureString = methodName + genericParameters;

                        if (!String.IsNullOrEmpty(genericParameters))
                        {
                            className = className + "!" + genericParameters;
                        }
                        var @params2 = GetParameterListAsString(method.ParameterList.Parameters, iface: methodSymbol.ContainingType);
                        var @params3 = GetParameterListAsString(method.ParameterList.Parameters, iface: null,
                            includeTypes: false,writebraces:false);

                        // writer.WriteLine(accessString + returnTypeString + methodSignatureString + @params2 + constraints);

                        //writer.OpenBrace();

                        if (!methodSymbol.IsStatic)
                        {
                            if(method.ParameterList.Parameters.Count >0)
                            writer.WriteLine("return new " + className + "(this," + @params3  +");");
                            else
                            {
                            writer.WriteLine("return new " + className + "(this);");

                            }
                        }
                        else
                        {
                            writer.WriteLine("return new " + className + "(" + @params3 + ");");

                        }

                       

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

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

                if (pinvokeAttributes != null)
                    WritePInvokeMethodBody.Go(writer, methodName, methodSymbol, pinvokeAttributes);

                if (isInternalPInvoke)
                    WritePInvokeMethodBody.Go(writer, methodName, methodSymbol, null);

                if (!isProxy && isYield)
                {
                    //writer.WriteLine("});");

                }
            }

            writer.CloseBrace();

            if (proxies != null)
            {
                foreach (var proxy in proxies)
                {
                    //Need to write proxy signature here ...

                    methodSignatureString = methodName + genericParameters;
                    var @params2 = GetParameterListAsString(method.ParameterList.Parameters, iface: proxy.ContainingType);
                    var @params3 = GetParameterListAsString(method.ParameterList.Parameters, iface: null,
                        includeTypes: false);

                    writer.WriteLine(accessString + returnTypeString + methodSignatureString + @params2 + constraints);

                    writer.OpenBrace();

                    if (method.ReturnType.ToString() == "void")
                        writer.WriteLine("" + methodName + @params3 + ";");
                    else
                        writer.WriteLine("return " + methodName + @params3 + ";");

                    writer.CloseBrace();
                }
            }

          
        }