Ejemplo n.º 1
0
        public static void WriteIt(OutputWriter writer, MethodDeclarationSyntax method, bool isProxy = true)
        {
            writer.WriteLine();
            var methodSymbol = (IMethodSymbol)TypeProcessor.GetDeclaredSymbol(method);
            var methodName   = OverloadResolver.MethodName(methodSymbol);

            var pinvokeAttributes = method.GetAttribute(Context.DllImport);

            // Fix this to actually look for the type, not just by name ...

            //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.ValueText == method.Identifier.ValueText))
                {
                    return;
                }
            }

            bool isoverride = ShouldUseOverrideKeyword(method, methodSymbol);

            var accessString = "";

            if (isoverride)
            {
                accessString += (" override ");
            }

            var isInterface = method.Parent is InterfaceDeclarationSyntax;

            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
            {
                if (method.Modifiers.Any(SyntaxKind.PublicKeyword) || method.Modifiers.Any(SyntaxKind.InternalKeyword) ||
                    method.Modifiers.Any(SyntaxKind.ProtectedKeyword) ||
                    method.Modifiers.Any(SyntaxKind.AbstractKeyword) || isInterface)
                {
                    accessString += ("public ");
                }

                if (method.Modifiers.Any(SyntaxKind.PrivateKeyword))
                {
                    accessString += ("private ");
                }

                //	            if (method.Modifiers.Any(SyntaxKind.VirtualKeyword) || isInterface)
                //	                writer.Write("virtual ");

                //				if (!(method.Modifiers.Any (SyntaxKind.VirtualKeyword) || (method.Modifiers.Any (SyntaxKind.AbstractKeyword) || isInterface || isoverride))) {
                //					writer.Write(" final ");
                //				}

                if (method.Modifiers.Any(SyntaxKind.AbstractKeyword))
                {
                    accessString += (" abstract ");
                }

                if (method.Modifiers.Any(SyntaxKind.StaticKeyword))
                {
                    accessString += ("static ");
                }
            }

            //	        if (isInterface)
            //	        {
            //                writer.IsInterface = true;
            //	        }

            var returnTypeString      = TypeProcessor.ConvertType(method.ReturnType) + " ";
            var methodSignatureString = "";

            if (method.ReturnType.ToString() == "void")
            {
                returnTypeString = ("void ");
            }
            else
            //  bool returnsVoid = method.ReturnType.ToString() == "void";
            //if (!returnsVoid)
            {
                var typeSymbol = TypeProcessor.GetTypeInfo(method.ReturnType).Type;

                //   var isPtr = typeSymbol != null && (typeSymbol.IsValueType || typeSymbol.TypeKind == TypeKind.TypeParameter) ? "" : "";
                //     var typeString = TypeProcessor.ConvertType(method.ReturnType) + isPtr + " ";

                //	            writer.Write(typeString);
                //	            writer.HeaderWriter.Write(typeString);

                var isPtr = typeSymbol != null &&
                            (!typeSymbol.IsValueType || typeSymbol.TypeKind == TypeKind.TypeParameter);
            }

            if (methodSymbol.ContainingType.TypeKind == TypeKind.Interface ||
                Equals(methodSymbol.ContainingType.FindImplementationForInterfaceMember(methodSymbol), methodSymbol))
            {
                methodName =
                    Regex.Replace(
                        TypeProcessor.ConvertType(methodSymbol.ContainingType.ConstructedFrom) + "_" + methodName,
                        @" ?!\(.*?\)", string.Empty);
            }

            if (methodName.Contains(".")) // Explicit Interface method
            {
                //
                methodName = methodName.SubstringAfterLast('.');
                methodName = methodName.Replace('.', '_');
            }

            //			var typenameI = Regex.Replace (TypeProcessor.ConvertType (interfaceMethod.ContainingType), @" ?!\(.*?\)", string.Empty);

            var interfaceMethods =
                methodSymbol.ContainingType.AllInterfaces.SelectMany(
                    u =>
                    u.GetMembers(methodName)).ToArray();

            ISymbol interfaceMethod =
                interfaceMethods.FirstOrDefault(
                    o => methodSymbol.ContainingType.FindImplementationForInterfaceMember(o) == methodSymbol);

            if (interfaceMethod == null)
            {
                //TODO: fix this for virtual method test 7, seems roslyn cannot deal with virtual
                // overrides of interface methods ... so i'll provide a kludge
                if (!method.Modifiers.Any(SyntaxKind.NewKeyword))
                {
                    interfaceMethod =
                        interfaceMethods.FirstOrDefault(k => CompareMethods(k as IMethodSymbol, methodSymbol));
                }
            }

            if (interfaceMethod != null)
            // && CompareMethods(interfaceMethod ,methodSymbol)) {
            {
//This is an interface method //TO
                if (methodSymbol.ContainingType.SpecialType == SpecialType.System_Array)
                {
                    methodSignatureString += ("");
                }
                else
                {
                    var typenameI =
                        Regex.Replace(TypeProcessor.ConvertType(interfaceMethod.ContainingType.ConstructedFrom),
                                      @" ?!\(.*?\)", string.Empty);
                    //TODO: we should be able to get the original interface name, or just remove all generics from this
                    if (typenameI.Contains('.'))
                    {
                        typenameI = typenameI.SubstringAfterLast('.');
                    }
                    methodName = (typenameI + "_") + methodName;
                }
            }

            //            var explicitHeaderNAme = "";
            //FIX ME: To support explicits, all method calls are going to be prequalified with the interface name, lets just hope we dont have similar interfaces
            //
            // if (methodSymbol.MethodKind == MethodKind.ExplicitInterfaceImplementation)
            //	        {
            //	           // var implementations = methodSymbol.ExplicitInterfaceImplementations[0];
            //	            if (implementations != null)
            //	            {
            //	              //  explicitHeaderNAme = implementations.Name;
            //                     methodName = TypeProcessor.ConvertType(implementations.ReceiverType) + "_" +implementations.Name; //Explicit fix ?
            //
            //	                //			writer.Write(methodSymbol.ContainingType + "." + methodName);
            //	                //Looks like internal classes are not handled properly here ...
            //	            }
            //	        }
            // methodName = methodName.Replace(methodSymbol.ContainingNamespace.FullName() + ".", methodSymbol.ContainingNamespace.FullName().Replace(".", "::") + "::");
            //           (methodSymbol as).Is
            //	        (methodSymbol as Microsoft.CodeAnalysis.CSharp.Symbols.SourceMethodSymbol);
            if (method.Modifiers.Any(SyntaxKind.NewKeyword))
            {
                methodName += "_";
            }

            //            writer.Write( TypeProcessor.ConvertType(methodSymbol.ContainingType)+ "." + methodName); //Dealting with explicit VMT7
            // writer.Write(!String.IsNullOrEmpty(explicitHeaderNAme)? explicitHeaderNAme : methodName);
            //            writer.Write(methodName);
            methodSignatureString += methodName;

            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
                {
                    methodSignatureString += ("(");
                    methodSignatureString += (string.Join(",", genericArgs.Select(o => " " + o)));
                    methodSignatureString += (")");
                }
            }

            var @params = GetParameterListAsString(method.ParameterList);

            var constraints = "";

            if (method.ConstraintClauses.Count > 0)
            {
                constraints += (" if (");
                bool isFirst = true;
                foreach (var constraint in method.ConstraintClauses)
                {
                    foreach (var condition in constraint.Constraints)
                    {
                        string dlangCondition = condition.ToString();

                        if (dlangCondition == "new()")
                        {
                            continue;
                        }
                        if (dlangCondition == "class") // TODO: is there a better way to do this ?
                        {
                            dlangCondition = "NObject";
                        }

                        if (dlangCondition == "struct")
                        {
                            constraints += ((isFirst ? "" : "&&") + " !is(" + constraint.Name + " : NObject)");
                        }
                        else
                        {
                            constraints += ((isFirst ? "" : "&&") + " is(" + constraint.Name + " : " + dlangCondition +
                                            ")");
                        }

                        isFirst = false;

                        //								Console.WriteLine (condition);
                    }
                }

                constraints += (")");
            }

            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, false);

                if (method.ReturnType.ToString() == "void")
                {
                    writer.WriteLine("Value." + methodName + @params + ";");
                }
                else
                {
                    writer.WriteLine("return Value." + methodName + @params + ";");
                }
            }
            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);
                }
            }

            writer.CloseBrace();
        }
Ejemplo n.º 2
0
        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();
                }
            }
        }