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(); } } }