예제 #1
0
        public static void Go(OutputWriter writer, BasePropertyDeclarationSyntax property, bool isProxy = false)
        {
            writer.WriteLine();
            //TODO, doesnt ref make things slower ?, though it makes proprties behave as in c#

            var isInterface = property.Parent is InterfaceDeclarationSyntax;

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

            var isYield  = getter != null && getter.DescendantNodes().OfType <YieldStatementSyntax>().Any();
            var isStatic = property.Modifiers.Any(k => k.IsKind(SyntaxKind.StaticKeyword));

            ITypeSymbol iface;

            ISymbol[] proxies;

            var name = MemberUtilities.GetMethodName(property, ref isInterface, out iface, out proxies);

            var modifiers      = property.Modifiers;
            var propertySymbol = (IPropertySymbol)TypeProcessor.GetDeclaredSymbol(property);
            var type           = propertySymbol.Type;


            var acccessmodifiers = MemberUtilities.GetAccessModifiers(property, isInterface || propertySymbol.IsAbstract);

            var typeString = TypeProcessor.ConvertType(type);

            var hasGetter     = getter != null;
            var getterHasBody = hasGetter && getter.Body != null;

            var hasSetter     = setter != null;
            var setterHasBody = hasSetter && setter.Body != null;



            var    indexerDeclarationSyntax = property as IndexerDeclarationSyntax;
            var    isindexer  = indexerDeclarationSyntax != null;
            string getterbody = null;

            if (getterHasBody)
            {
                getterbody = Core.WriteBlock(getter.Body, false, writer.Indent + 2);

                if (!isProxy && isYield)
                {
                    var namedTypeSymbol = propertySymbol.Type as INamedTypeSymbol;
                    if (namedTypeSymbol != null)
                    {
                        //                        var iteratortype = namedTypeSymbol.TypeArguments[0];
                        //                        getterbody=String.Format("return new __IteratorBlock!({0})(delegate(__IteratorBlock!({0}) __iter){{ {1} }});",
                        //                            TypeProcessor.ConvertType(iteratortype),getterbody);

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



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

                        //writer.OpenBrace();

                        if (!propertySymbol.IsStatic)
                        {
                            getterbody = writer.WriteIndentToString() + ("return new " + className + "(this);");
                        }
                        else
                        {
                            getterbody = writer.WriteIndentToString() + ("return new " + className + "();");
                        }
                    }
                }
            }
            string setterbody = null;

            if (setterHasBody)
            {
                setterbody = Core.WriteString(setter.Body, false, writer.Indent + 2);
                if (isindexer)
                {
                    setterbody += writer.WriteIndentToString() + "return value;";
                }
                else
                {
                    if (hasGetter)
                    {
                        setterbody += writer.WriteIndentToString() + "return " + name + ";";
                    }
                }
            }

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

            string isOverride;

            var fieldName = WriteAutoFieldName(writer, name, modifiers, isInterface, hasGetter, getterHasBody,
                                               hasSetter, setterHasBody, typeString, out isOverride, (property is IndexerDeclarationSyntax));


            BracketedParameterListSyntax @params = null;

            if (indexerDeclarationSyntax != null)
            {
                @params = indexerDeclarationSyntax.ParameterList;
            }

            string parameters = null;

            if (@params != null)
            {
                parameters = WriteMethod.GetParameterListAsString(@params.Parameters, iface: proxies == null ? iface : null, writebraces: false);
            }

            WriteGetter(writer, isProxy, hasGetter, acccessmodifiers, typeString, name, proxies == null ? iface : null, getterHasBody, modifiers, isInterface, fieldName, getterbody, parameters, indexerDeclarationSyntax != null);

            WriteSetter(writer, isProxy, hasSetter, acccessmodifiers, name, typeString, proxies == null ? iface : null, isOverride, setterHasBody, modifiers, isInterface, fieldName, setterbody, parameters, isindexer, hasGetter);

//			if (!isindexer && !isInterface) //TODO: Find a better solution
//			{
//				var fieldacccessmodifiers = acccessmodifiers.Replace ("abstract", "").Replace ("virtual","").Replace("override","");
//
//				writer.WriteLine(fieldacccessmodifiers +  "__Property!(" + typeString + ")" + name + ";");
//				if (isStatic)
//				{
//					var staticWriter = new TempWriter ();
//
//					staticWriter.WriteLine (name + String.Format (" = __Property!(" + typeString + ")(__ToDelegate(&set{0}), __ToDelegate(&get{0}));", name));
//					Context.Instance.StaticInits.Add (staticWriter.ToString ());
//				}
//				else
//				{
//					var instanceWriter = new TempWriter ();
//
//					instanceWriter.WriteLine (name + String.Format (" = __Property!(" + typeString + ")((&set{0}), (&get{0}));", name));
//					Context.Instance.InstanceInits.Add (instanceWriter.ToString ());
//				}
//			}


            if (proxies != null)
            {
                foreach (var proxy in proxies)
                {
                    if (indexerDeclarationSyntax == null)
                    {
                        setterbody = writer.WriteIndentToString() + name + "=" + "value" + ";";
                        getterbody = writer.WriteIndentToString() + "return " + name + ";";
                    }
                    else
                    {
                        string parameters2 = "";
                        if (@params != null)
                        {
                            parameters2 = WriteMethod.GetParameterListAsString(@params.Parameters, iface: null, includeTypes: false, writebraces: false);
                            // parameters2 = WriteMethod.GetParameterListAsString(@params.Parameters, iface: proxies == null ? iface : null, writebraces: false);
                        }

                        setterbody = writer.WriteIndentToString() + "return opIndexAssign(value," + parameters2 + ");";// + "=" + "value" + ";";
                        getterbody = writer.WriteIndentToString() + "return opIndex(" + parameters2 + ");";
                    }


                    parameters = null;
                    if (@params != null)
                    {
                        parameters = WriteMethod.GetParameterListAsString(@params.Parameters, iface: proxy.ContainingType, writebraces: false);
                    }

                    WriteGetter(writer, isProxy, hasGetter, acccessmodifiers, typeString, name, proxy.ContainingType, getterHasBody, modifiers, isInterface, fieldName, getterbody, parameters, isindexer);

                    WriteSetter(writer, isProxy, hasSetter, acccessmodifiers, name, typeString, proxy.ContainingType, isOverride, setterHasBody, modifiers, isInterface, fieldName, setterbody, parameters, isindexer, hasGetter);
                }
            }
        }
예제 #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();
                }
            }
        }