public override bool VisitClassDecl(Class @class)
        {
            var @object   = IsByRefParameter ? $"{Context.ArgName}.get()" : Context.ArgName;
            var objectRef = @class.IsInterface ? "__getObject()" : "__object";

            if (IsByRefParameter)
            {
                CheckRefOutParameter(Context.Parameter.IsInOut);

                TypePrinter.PushContext(TypePrinterContextKind.Native);
                var typeName = Context.Parameter.Visit(TypePrinter);
                TypePrinter.PopContext();

                var varName = JavaGenerator.GeneratedIdentifier(Context.ArgName);
                var marshal = Context.Parameter.IsInOut ?
                              $"new {typeName}({@object}.{objectRef})" : $"new {typeName}()";
                Context.SupportBefore.WriteLine($"{typeName} {varName} = {marshal};");

                var marshalContext = new MarshalContext(Context.Context)
                {
                    Parameter     = Context.Parameter,
                    ReturnVarName = $"{varName}.getValue()"
                };

                var marshaler = new JavaMarshalNativeToManaged(marshalContext);
                @class.Visit(marshaler);

                Context.SupportAfter.WriteLine($"{Context.ArgName}.set({marshaler.Context.Return});");

                Context.Return.Write(varName);
                return(true);
            }

            Context.Return.Write($"{Context.ArgName} == null ? null : {Context.ArgName}.{objectRef}");
            return(true);
        }
        public void GenerateMethodInvocation(Method method)
        {
            var contexts = new List<MarshalContext>();
            var @params = new List<string>();

            if (!method.IsStatic && !(method.IsConstructor || method.IsDestructor))
                @params.Add("__object");

            int paramIndex = 0;
            foreach (var param in method.Parameters.Where(m => !m.IsImplicit))
            {
                var ctx = new MarshalContext(Context)
                {
                    ArgName = param.Name,
                    Parameter = param,
                    ParameterIndex = paramIndex++
                };
                contexts.Add(ctx);

                var marshal = new JavaMarshalManagedToNative(ctx);
                param.Visit(marshal);

                if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
                        Write(marshal.Context.SupportBefore);

                @params.Add(marshal.Context.Return);
            }

            PrimitiveType primitive;
            method.ReturnType.Type.IsPrimitiveType(out primitive);

            var hasReturn = primitive != PrimitiveType.Void && !(method.IsConstructor || method.IsDestructor);
            if (hasReturn)
            {
                TypePrinter.PushContext(TypePrinterContextKind.Native);
                var typeName = method.ReturnType.Visit(TypePrinter);
                TypePrinter.PopContext();
                Write($"{typeName.Type} __ret = ");
            }

            if (method.IsConstructor)
                Write("__object = ");

            var unit = method.TranslationUnit;
            var package = string.Join(".", GetPackageNames(unit));
            Write($"{package}.{JavaNative.GetNativeLibClassName(unit)}.INSTANCE.{JavaNative.GetCMethodIdentifier(method)}(");

            Write(string.Join(", ", @params));
            WriteLine(");");

            WriteLine("mono.embeddinator.Runtime.checkExceptions();");

            foreach (var marshal in contexts)
            {
                if (!string.IsNullOrWhiteSpace(marshal.SupportAfter))
                    Write(marshal.SupportAfter);
            }

            if (hasReturn)
            {
                var ctx = new MarshalContext(Context)
                {
                    ReturnType = method.ReturnType,
                    ReturnVarName = "__ret"
                };

                var marshal = new JavaMarshalNativeToManaged(ctx);
                method.ReturnType.Visit(marshal);

                if (marshal.Context.Return.ToString().Length == 0)
                    throw new System.Exception();

                if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
                        Write(marshal.Context.SupportBefore);

                WriteLine($"return {marshal.Context.Return};");
            }
        }