protected override Expression VisitPropertyDefinitionExpression(PropertyDefinitionExpression property)
        {
            var name = property.PropertyName.ToCamelCase();

            var propertyDefinition = new PropertyDefinitionExpression(name, property.PropertyType, true, property.Modifiers);

            if (name.StartsWith("new"))
            {
                var attributedPropertyGetter = new MethodDefinitionExpression(name, new Expression[0], property.PropertyType, Expression.Empty(), true, "(objc_method_family(none))", null);

                return new Expression[] { propertyDefinition, attributedPropertyGetter }.ToStatementisedGroupedExpression();
            }
            else
            {
                return propertyDefinition;
            }
        }
        protected override Expression VisitMethodDefinitionExpression(MethodDefinitionExpression method)
        {
            var methodName = method.Name.ToCamelCase();

            var body = new Expression[]
            {
                Expression.Return(Expression.Label(), Expression.Constant(null)).ToStatement()
            };

            var responseType = ObjectiveBinderHelpers.GetWrappedResponseType(this.CodeGenerationContext, method.ReturnType);

            var newParameters = new List<Expression>(method.Parameters)
            {
                FickleExpression.Parameter(new FickleDelegateType(typeof(void), new FickleParameterInfo(responseType, "response")), "callback")
            };

            return new MethodDefinitionExpression(methodName, newParameters.ToReadOnlyCollection(), typeof(void), Expression.Block(body), true, null);
        }
Esempio n. 3
0
        protected override Expression VisitMethodDefinitionExpression(MethodDefinitionExpression method)
        {
            if (this.acceptMethod(method))
            {
                try
                {
                    this.currentMethod = method;

                    return base.VisitMethodDefinitionExpression(method);
                }
                finally
                {
                    this.currentMethod = null;
                }

            }

            return method;
        }
Esempio n. 4
0
        protected override Expression VisitMethodDefinitionExpression(MethodDefinitionExpression method)
        {
            var methodName = method.Name.Uncapitalize();
            var methodParameters = new List<Expression>(method.Parameters);
            var methodVariables = new List<ParameterExpression>();
            var methodStatements = new List<Expression>();

            var requestParameters = new List<Expression>(method.Parameters);

            var httpMethod = method.Attributes["Method"];
            var hostname = currentTypeDefinitionExpression.Attributes["Hostname"];
            var path = "http://" + hostname + method.Attributes["Path"];

            var client = Expression.Variable(webServiceClientType, "webServiceClient");
            var responseType = JavaBinderHelpers.GetWrappedResponseType(this.CodeGenerationContext, method.ReturnType);
            var responseTypeArgument = Expression.Variable(typeof(String), responseType.Name + ".class");
            var callback = Expression.Parameter(new FickleType("RequestCallback<" + responseType.Name + ">"), "callback");

            methodParameters.Add(callback);

            var url = Expression.Variable(typeof(string), "url");

            methodVariables.Add(url);
            methodStatements.Add(Expression.Assign(url, Expression.Constant(path)));

            Object serviceCallArguments;

            if (httpMethod.Equals("post", StringComparison.InvariantCultureIgnoreCase)
                || httpMethod.Equals("put", StringComparison.InvariantCultureIgnoreCase))
            {
                var contentParameterName = method.Attributes["Content"];

                var contentParam = requestParameters.FirstOrDefault(x => ((ParameterExpression)x).Name.Equals(contentParameterName, StringComparison.InvariantCultureIgnoreCase));

                if (contentParam == null)
                {
                    throw new Exception("Post or Put method defined with null Content. You must define a @content field in your FicklefileKeyword");
                }

                requestParameters = requestParameters.Where(x => x != contentParam).ToList();

                var payloadVar = Expression.Variable(typeof(string), "requestPayload");

                methodVariables.Add(payloadVar);

                var jsonBuilder = FickleType.Define("DefaultJsonBuilder");

                var jsonBuilderInstance = FickleExpression.StaticCall(jsonBuilder, "instance");

                var toJsonCall = FickleExpression.Call(jsonBuilderInstance, typeof(String), "toJson", contentParam);

                var payloadAssign = Expression.Assign(payloadVar, toJsonCall);

                methodStatements.Add(payloadAssign);

                serviceCallArguments = new
                {
                    url,
                    responseTypeArgument,
                    payloadVar,
                    callback
                };
            }
            else
            {
                serviceCallArguments = new
                {
                    url,
                    responseTypeArgument,
                    callback
                };
            }

            foreach (var parameter in requestParameters)
            {
                var param = (ParameterExpression)parameter;

                if (param.Type is FickleNullable)
                {
                    param = FickleExpression.Parameter(param.Type.GetUnwrappedNullableType(), param.Name);
                }

                var valueToReplace = Expression.Constant("{" + param.Name + "}", typeof(String));
                var valueAsString = FickleExpression.Call(param, param.Type, typeof(String), SourceCodeGenerator.ToStringMethod, parameter);

                var replaceArgs = new
                {
                    valueToReplace,
                    valueAsString
                };

                methodStatements.Add(Expression.Assign(url, FickleExpression.Call(url, typeof(String), "replace", replaceArgs)));
            }

            methodStatements.Add(FickleExpression.Call(client, httpMethod, serviceCallArguments));

            var methodBody = FickleExpression.Block
            (
                methodVariables.ToArray(),
                methodStatements.ToArray()
            );

            return new MethodDefinitionExpression(methodName, methodParameters.ToReadOnlyCollection(), AccessModifiers.Public, typeof(void), methodBody, false, null);
        }
Esempio n. 5
0
        protected override Expression VisitPropertyDefinitionExpression(PropertyDefinitionExpression property)
        {
            var name = property.PropertyName.Uncapitalize();

            fieldDefinitionsForProperties.Add(new FieldDefinitionExpression(name, property.PropertyType, AccessModifiers.Protected));

            var thisProperty = FickleExpression.Variable(property.PropertyType, "this." + name);

            var getterBody = FickleExpression.Block
            (
                new Expression[] { FickleExpression.Return(thisProperty) }
            );

            var setterParam = FickleExpression.Parameter(property.PropertyType, name);

            var setterBody = FickleExpression.Block
            (
                new Expression[] { Expression.Assign(thisProperty, setterParam) }
            );

            var propertyGetter = new MethodDefinitionExpression("get" + property.PropertyName, new List<Expression>(), AccessModifiers.Public, property.PropertyType, getterBody, false);
            var propertySetter = new MethodDefinitionExpression("set" + property.PropertyName, new List<Expression> { setterParam }, AccessModifiers.Public, typeof(void), setterBody, false);

            return new Expression[] { propertyGetter, propertySetter }.ToStatementisedGroupedExpression();
        }
        protected override Expression VisitMethodDefinitionExpression(MethodDefinitionExpression method)
        {
            var client = Expression.Variable(this.httpClientType, HttpClientFieldName);

            var methodName = method.Name;
            var methodParameters = new List<Expression>(method.Parameters);
            var methodVariables = new List<ParameterExpression>();
            var methodStatements = new List<Expression>();

            var hostname = this.currentTypeDefinitionExpression.Attributes["Hostname"];
            var fullPath = "http://" + hostname + method.Attributes["Path"];
            var relativePath = method.Attributes["Path"];

            if (relativePath.StartsWith("/"))
            {
                relativePath = relativePath.Substring(1);
            }

            var requestUrl = Expression.Variable(typeof(InterpolatedString), "requestUrl");
            methodVariables.Add(requestUrl);

            var baseAddressProperty = FickleExpression.Property(client, this.httpClientType, "BaseAddress");
            methodStatements.Add(Expression.IfThenElse(Expression.Equal(baseAddressProperty, Expression.Constant(null)),
                Expression.Assign(requestUrl, Expression.Constant(new InterpolatedString(fullPath))).ToStatementBlock(),
                Expression.Assign(requestUrl, Expression.Constant(new InterpolatedString(relativePath))).ToStatementBlock()));

            var httpMethodType = FickleType.Define("HttpMethod");
            var httpRequestMessageType = FickleType.Define("HttpRequestMessage");
            var httpRequestMessagesArgs = new
            {
                httpMethod = FickleExpression.New(httpMethodType, "HttpMethod", method.Attributes["Method"]),
                requestUrl
            };

            var httpRequestMessageNew = FickleExpression.New(httpRequestMessageType, "HttpRequestMessage", httpRequestMessagesArgs);
            var httpRequestMessage = Expression.Variable(httpRequestMessageType, "httpRequestMessage");
            methodVariables.Add(httpRequestMessage);
            methodStatements.Add(Expression.Assign(httpRequestMessage, httpRequestMessageNew));

            var streamType = FickleType.Define("Stream");
            var httpStreamSerializer = Expression.Variable(this.httpStreamSerializerType, HttpStreamSerializerFieldName);

            var contentParameterName = method.Attributes["Content"];

            if (!string.IsNullOrEmpty(contentParameterName))
            {
                var contentParam = method.Parameters.FirstOrDefault(x => ((ParameterExpression)x).Name.Equals(contentParameterName, StringComparison.InvariantCultureIgnoreCase));

                if (contentParam == null)
                {
                    throw new Exception("Content paramter not found");
                }

                var serializeCall = FickleExpression.Call(httpStreamSerializer, typeof(string), "Serialize", contentParam);
                var stringContentNew = FickleExpression.New(FickleType.Define("StringContent"), "StringContent", serializeCall);
                methodStatements.Add(Expression.Assign(FickleExpression.Property(httpRequestMessage, httpRequestMessageType, "Content"), stringContentNew));
            }

            var httpResponseMessageType = FickleType.Define("HttpResponseMessage");
            var httpResponseMessage = Expression.Variable(httpResponseMessageType, "httpResponseMessage");
            methodVariables.Add(httpResponseMessage);

            var clientCall = FickleExpression.Call(client, new CSharpAwaitedTaskType(httpResponseMessageType), "SendAsync", httpRequestMessage);
            methodStatements.Add(Expression.Assign(httpResponseMessage, clientCall));
            methodStatements.Add(FickleExpression.Call(httpResponseMessage, "EnsureSuccessStatusCode", null));

            if (method.ReturnType != typeof (void))
            {
                var result = Expression.Variable(method.ReturnType, "result");
                methodVariables.Add(result);

                var contentStream = Expression.Variable(streamType, "contentStream");
                methodVariables.Add(contentStream);
                methodStatements.Add(Expression.Assign(contentStream, Expression.Constant(null)));

                var responseContent = Expression.Property(httpResponseMessage, "Content");
                var contentStreamCall = FickleExpression.Call(responseContent, new CSharpAwaitedTaskType(streamType), "ReadAsStreamAsync", null);

                var deserializeCall = FickleExpression.Call(httpStreamSerializer, method.ReturnType, "Deserialize", contentStream);
                deserializeCall.Method.MakeGenericMethod(method.ReturnType);

                var tryBlock = FickleExpression.Grouped(
                    Expression.Assign(contentStream, contentStreamCall).ToStatement(),
                    Expression.Assign(result, deserializeCall).ToStatement()
                    );

                var diposeStream = Expression.IfThen(Expression.NotEqual(contentStream, Expression.Constant(null)), FickleExpression.Call(contentStream, "Dispose", null).ToStatementBlock());

                var tryFinally = Expression.TryFinally(tryBlock, diposeStream);
                methodStatements.Add(tryFinally);

                methodStatements.Add(FickleExpression.Return(result));
            }

            var methodBody = FickleExpression.Block
            (
                methodVariables.ToArray(),
                methodStatements.ToArray()
            );

            var returnType = method.ReturnType != typeof (void) ? method.ReturnType : null;
            var returnTaskType = new CSharpAwaitedTaskType(returnType);

            return new MethodDefinitionExpression(methodName, methodParameters.ToReadOnlyCollection(), AccessModifiers.Public, returnTaskType, methodBody, false, null);
        }
Esempio n. 7
0
        protected virtual Expression VisitMethodDefinitionExpression(MethodDefinitionExpression method)
        {
            var expressions = this.VisitExpressionList(method.Parameters);
            var body = this.Visit(method.Body);

            if (expressions != method.Parameters || body != method.Body)
            {
                return new MethodDefinitionExpression(method.Name, expressions, method.AccessModifiers, method.ReturnType, body, method.IsPredeclaration, method.RawAttributes, method.Attributes);
            }

            return method;
        }
Esempio n. 8
0
        protected override Expression VisitMethodDefinitionExpression(MethodDefinitionExpression method)
        {
            if ((method.AccessModifiers & AccessModifiers.ClasseslessFunction) != 0)
            {
                if ((method.AccessModifiers & AccessModifiers.Static) != 0)
                {
                    this.Write("static ");
                }

                if (method.RawAttributes != null)
                {
                    this.Write(method.RawAttributes);
                    this.Write(' ');
                }

                this.Write(method.ReturnType);
                this.Write(" ");
                this.Write(method.Name);
                this.Write("(");
                for (var i = 0; i < method.Parameters.Count; i++)
                {
                    var parameter = (ParameterExpression)method.Parameters[i];

                    this.Write(parameter.Type);
                    this.Write(" ");
                    this.Write(parameter.Name);

                    if (i != method.Parameters.Count - 1)
                    {
                        this.Write(", ");
                    }
                }
                this.Write(")");

                if (method.IsPredeclaration)
                {
                    this.Write(";");

                    return method;
                }

                this.WriteLine();
                this.Visit(method.Body);
                this.WriteLine();
            }
            else
            {
                if ((method.AccessModifiers & AccessModifiers.Static) == AccessModifiers.Static)
                {
                    this.Write("+");
                }
                else
                {
                    this.Write("-");
                }

                this.Write('(');
                this.Write(method.ReturnType);
                this.Write(')');
                this.WriteSpace();
                this.Write(method.Name);

                for (var i = 0; i < method.Parameters.Count; i++)
                {
                    var parameter = (ParameterExpression)method.Parameters[i];

                    if (i != 0)
                    {
                        this.Write(parameter.Name);
                    }

                    this.Write(':');
                    this.Write('(');
                    this.Write(parameter.Type);
                    this.Write(')');

                    this.Write(parameter.Name);

                    if (i != method.Parameters.Count - 1)
                    {
                        this.Write(" ");
                    }
                }

                if (!string.IsNullOrEmpty(method.RawAttributes) && method.IsPredeclaration)
                {
                    this.Write(" __attribute__({0})", method.RawAttributes);
                }

                if (method.IsPredeclaration)
                {
                    this.WriteLine(';');
                }
                else
                {
                    this.WriteLine();
                    this.Visit(method.Body);
                    this.WriteLine();
                }
            }

            return method;
        }
        protected override Expression VisitMethodDefinitionExpression(MethodDefinitionExpression method)
        {
            var methodName = method.Name.ToCamelCase();

            methodCount++;

            var self = Expression.Variable(currentType, "self");
            var hostname = Expression.Variable(typeof(string), "hostname");
            var options = FickleExpression.Variable("NSMutableDictionary", "localOptions");
            var url = Expression.Variable(typeof(string), "url");
            var client = Expression.Variable(FickleType.Define(this.CodeGenerationContext.Options.ServiceClientTypeName ?? "PKWebServiceClient"), "client");
            var responseType = ObjectiveBinderHelpers.GetWrappedResponseType(this.CodeGenerationContext, method.ReturnType);
            var variables = new [] { url, client, options, hostname };
            var declaredHostname = currentTypeDefinitionExpression.Attributes["Hostname"];
            var declaredPath = method.Attributes["Path"];
            var path = StringUriUtils.Combine("http://%@", declaredPath);
            var httpMethod = method.Attributes["Method"];

            var parametersByName = method.Parameters.ToDictionary(c => ((ParameterExpression)c).Name, c => (ParameterExpression)c, StringComparer.InvariantCultureIgnoreCase);

            var formatInfo = ObjectiveStringFormatInfo.GetObjectiveStringFormatInfo(path, c => parametersByName[c]);

            var args = formatInfo.ValueExpressions;
            var parameters = formatInfo.ParameterExpressions;

            var parameterInfos = new List<FickleParameterInfo>
            {
                new ObjectiveParameterInfo(typeof(string), "s"),
                new ObjectiveParameterInfo(typeof(string), "hostname", true)
            };

            parameterInfos.AddRange(parameters.Select(c => new ObjectiveParameterInfo(c.Type, c.Name, true)));

            var methodInfo = new FickleMethodInfo(typeof(string), typeof(string), "stringWithFormat", parameterInfos.ToArray(), true);

            args.InsertRange(0, new Expression[] { Expression.Constant(formatInfo.Format), hostname });

            var newParameters = new List<Expression>(method.Parameters);
            var callback = Expression.Parameter(new FickleDelegateType(typeof(void), new FickleParameterInfo(responseType, "response")), "callback");

            newParameters.Add(callback);

            Expression blockArg = Expression.Parameter(FickleType.Define("id"), "arg1");

            var returnType = method.ReturnType;

            if (ObjectiveBinderHelpers.NeedsValueResponseWrapper(method.ReturnType))
            {
                returnType = FickleType.Define(ObjectiveBinderHelpers.GetValueResponseWrapperTypeName(method.ReturnType));
            }

            var conversion = Expression.Convert(blockArg, returnType);
            var body = FickleExpression.Call(callback, "Invoke", conversion).ToStatement();
            var conversionBlock = FickleExpression.SimpleLambda(null, body, new Expression[0], blockArg);

            Expression clientCallExpression;

            if (httpMethod.Equals("get", StringComparison.InvariantCultureIgnoreCase))
            {
                clientCallExpression = FickleExpression.Call(client, "getWithCallback", conversionBlock);
            }
            else
            {
                var contentParameterName = method.Attributes["Content"];
                var contentFormat = method.Attributes["ContentFormat"];

                if (string.IsNullOrEmpty(contentParameterName))
                {
                    clientCallExpression = FickleExpression.Call(client, "postWithRequestObject", new
                    {
                        requestObject = Expression.Constant(null, typeof(object)),
                        andCallback = conversionBlock
                    });
                }
                else
                {
                    var content = parametersByName[contentParameterName];

                    clientCallExpression = FickleExpression.Call(client, "postWithRequestObject", new
                    {
                        requestObject = FickleExpression.Call(self, typeof(object), this.GetNormalizeRequestMethodName(content.Type, contentFormat), new { serializeRequest=Expression.Convert(content, typeof(object)), paramName=Expression.Constant(contentParameterName) }),
                        andCallback = conversionBlock
                    });
                }
            }

            var error = FickleExpression.Variable("NSError", "error");

            var parseErrorResult = FickleExpression.Call(self, "webServiceClient", new
            {
                client,
                createErrorResponseWithErrorCode = "JsonDeserializationError",
                andMessage = FickleExpression.Call(error, "localizedDescription", null)
            });

            Expression parseResultBlock;

            var nsdataParam = Expression.Parameter(FickleType.Define("NSData"), "data");
            var jsonObjectWithDataParameters = new[] { new FickleParameterInfo(FickleType.Define("NSDictionary"), "obj"), new FickleParameterInfo(typeof(int), "options"), new FickleParameterInfo(FickleType.Define("NSError", true), "error", true) };
            var objectWithDataMethodInfo = new FickleMethodInfo(FickleType.Define("NSJSONSerialization"), FickleType.Define("NSData"), "JSONObjectWithData", jsonObjectWithDataParameters, true);
            var deserializedValue = Expression.Parameter(FickleType.Define("id"), "deserializedValue");

            if (method.ReturnType == typeof(void))
            {
                var responseObject = FickleExpression.Variable(responseType, "responseObject");

                parseResultBlock = FickleExpression.SimpleLambda
                (
                    FickleType.Define("id"),
                    FickleExpression.GroupedWide
                    (
                        Expression.Assign(responseObject, FickleExpression.New(responseType, "init", null)).ToStatement(),
                        Expression.Assign(deserializedValue, Expression.Call(objectWithDataMethodInfo, nsdataParam, FickleExpression.Variable(typeof(int), "NSJSONReadingAllowFragments"), error)).ToStatement(),
                        Expression.IfThen(Expression.Equal(deserializedValue, Expression.Constant(null)), FickleExpression.Return(parseErrorResult).ToStatement().ToBlock()),
                        FickleExpression.Return(responseObject).ToStatement()
                    ),
                    new Expression[] { deserializedValue, responseObject, error },
                    nsdataParam
                );
            }
            else if (TypeSystem.IsPrimitiveType(method.ReturnType) || method.ReturnType is FickleListType)
            {
                var responseObject = FickleExpression.Variable(responseType, "responseObject");
                var needToBoxValue = ObjectiveBinderHelpers.ValueResponseValueNeedsBoxing(method.ReturnType);

                parseResultBlock = FickleExpression.SimpleLambda
                (
                    FickleType.Define("id"),
                    FickleExpression.GroupedWide
                    (
                        Expression.Assign(responseObject, FickleExpression.New(responseType, "init", null)).ToStatement(),
                        Expression.Assign(deserializedValue, Expression.Call(objectWithDataMethodInfo, nsdataParam, FickleExpression.Variable(typeof(int), "NSJSONReadingAllowFragments"), error)).ToStatement(),
                        Expression.IfThen(Expression.Equal(deserializedValue, Expression.Constant(null)), FickleExpression.Return(parseErrorResult).ToStatement().ToBlock()),
                        PropertiesFromDictionaryExpressonBinder.GetDeserializeExpressionProcessValueDeserializer(method.ReturnType, deserializedValue, c => FickleExpression.Call(responseObject, typeof(void), "setValue", needToBoxValue  ? Expression.Convert(c, typeof(object)) : c).ToStatement()),
                        FickleExpression.Return(responseObject).ToStatement()
                    ),
                    new Expression[] { deserializedValue, responseObject, error },
                    nsdataParam
                );
            }
            else
            {
                parseResultBlock = FickleExpression.SimpleLambda
                (
                    FickleType.Define("id"),
                    FickleExpression.GroupedWide
                    (
                        Expression.Assign(deserializedValue, Expression.Call(objectWithDataMethodInfo, nsdataParam, FickleExpression.Variable(typeof(int), "NSJSONReadingAllowFragments"), error)).ToStatement(),
                        PropertiesFromDictionaryExpressonBinder.GetDeserializeExpressionProcessValueDeserializer(method.ReturnType, deserializedValue, c => FickleExpression.Return(c).ToStatement()),
                        FickleExpression.Return(parseErrorResult).ToStatement()
                    ),
                    new Expression[] { deserializedValue, error },
                    nsdataParam
                );
            }

            parseResultBlock = FickleExpression.Call(parseResultBlock, parseResultBlock.Type, "copy", null);

            var block = FickleExpression.Block
            (
                variables,
                Expression.Assign(callback, FickleExpression.Call(callback, callback.Type, "copy", null)),
                Expression.Assign(options, FickleExpression.Call(FickleExpression.Property(self, FickleType.Define("NSDictionary"), "options"), "NSMutableDictionary", "mutableCopyWithZone", new
                {
                    zone = Expression.Constant(null, FickleType.Define("NSZone"))
                })),
                FickleExpression.Call(options, typeof(void), "setObject", new { value = FickleExpression.StaticCall(responseType, "class", null), forKey = "$ResponseClass" }).ToStatement(),
                Expression.Assign(hostname, FickleExpression.Call(options, typeof(string), "objectForKey", Expression.Constant("hostname"))),
                Expression.IfThen(Expression.Equal(hostname, Expression.Constant(null)), Expression.Assign(hostname, Expression.Constant(declaredHostname)).ToStatement().ToBlock()),
                FickleExpression.Grouped
                (
                    FickleExpression.Call(options, "setObject", new
                    {
                        obj = parseResultBlock,
                        forKey = "$ParseResultBlock"
                    }).ToStatement(),
                    method.ReturnType.GetUnwrappedNullableType() == typeof(bool) ?
                    FickleExpression.Call(options, "setObject", new
                    {
                        obj = Expression.Convert(Expression.Constant(1), typeof(object))
                    }).ToStatement() : null
                ),
                Expression.Assign(url, Expression.Call(null, methodInfo, args)),
                Expression.Assign(client, FickleExpression.Call(Expression.Variable(currentType, "self"), "PKWebServiceClient", "createClientWithURL", new
                {
                    url,
                    options
                })),
                Expression.Assign(FickleExpression.Property(client, currentType, "delegate"), self),
                clientCallExpression
            );

            return new MethodDefinitionExpression(methodName, newParameters.ToReadOnlyCollection(), typeof(void), block, false, null);
        }
        protected override Expression VisitMethodDefinitionExpression(MethodDefinitionExpression method)
        {
            ParameterExpression optionsParameter;
            var self = Expression.Variable(currentType, "self");
            var gatewayCall = (MethodDefinitionExpression)this.CreateGatewayCallMethod(method, out optionsParameter);
            var newArgs = gatewayCall.Parameters.Select(c => c != optionsParameter ? c : Expression.Constant(null, c.Type)).ToList();
            var newMethodParams = gatewayCall.Parameters.Where(c => c != optionsParameter).ToList();

            var methodInfo = new FickleMethodInfo(self.Type, gatewayCall.ReturnType, gatewayCall.Name, gatewayCall.Parameters.Cast<ParameterExpression>().Select(c => new FickleParameterInfo(c.Type, c.Name)).ToArray());
            var newBody = Expression.Call(self, methodInfo, newArgs).ToStatementBlock();
            var gatewayCallMethodWithoutOptions = new MethodDefinitionExpression(gatewayCall.Name, newMethodParams, gatewayCall.ReturnType, newBody, false, gatewayCall.RawAttributes, gatewayCall.Attributes);

            return new GroupedExpressionsExpression(new [] { gatewayCall, gatewayCallMethodWithoutOptions }, GroupedExpressionsExpressionStyle.Wide);
        }
        protected Expression CreateGatewayCallMethod(MethodDefinitionExpression method, out ParameterExpression optionsParameter)
        {
            var methodName = method.Name.ToCamelCase();

            methodCount++;

            var self = Expression.Variable(currentType, "self");
            var hostname = Expression.Variable(typeof(string), "hostname");
            var port = Expression.Variable(typeof(string), "port");
            var protocol = Expression.Variable(typeof(string), "protocol");
            var optionsParam = FickleExpression.Parameter("NSDictionary", "options");
            var localOptions = FickleExpression.Variable("NSMutableDictionary", "localOptions");
            var requestObject = FickleExpression.Variable("NSObject", "requestObject");
            var requestObjectValue = (Expression)Expression.Constant(null, typeof(object));
            var url = Expression.Variable(typeof(string), "url");
            var responseType = ObjectiveBinderHelpers.GetWrappedResponseType(this.CodeGenerationContext, method.ReturnType);
            var variables = new [] { url, localOptions, protocol, hostname, requestObject, port };
            var declaredHostname = currentTypeDefinitionExpression.Attributes["Hostname"];
            var declaredPath = method.Attributes["Path"];
            var path = StringUriUtils.Combine("%@://%@%@", declaredPath);
            var httpMethod = method.Attributes["Method"];
            var declaredProtocol = Convert.ToBoolean(method.Attributes["Secure"]) ? "https" : "http";
            var retryBlockVariable = Expression.Variable(new FickleDelegateType(typeof(void), new FickleParameterInfo(FickleType.Define("id"), "block")), "retryBlock");
            var retryBlockParameter = Expression.Variable(FickleType.Define("id"), "block");

            var parametersByName = method.Parameters.ToDictionary(c => ((ParameterExpression)c).Name, c => (ParameterExpression)c, StringComparer.InvariantCultureIgnoreCase);

            var formatInfo = ObjectiveStringFormatInfo.GetObjectiveStringFormatInfo(path, c => parametersByName[c]);

            var args = formatInfo.ValueExpressions;
            var parameters = formatInfo.ParameterExpressions;

            var parameterInfos = new List<FickleParameterInfo>
            {
                new ObjectiveParameterInfo(typeof(string), "s"),
                new ObjectiveParameterInfo(typeof(string), "protocol", true),
                new ObjectiveParameterInfo(typeof(string), "hostname", true),
                new ObjectiveParameterInfo(typeof(string), "port", true),
            };

            parameterInfos.AddRange(parameters.Select(c => new ObjectiveParameterInfo(c.Type, c.Name, true)));

            var methodInfo = new FickleMethodInfo(typeof(string), typeof(string), "stringWithFormat", parameterInfos.ToArray(), true);

            args.InsertRange(0, new Expression[] { Expression.Constant(formatInfo.Format), protocol, hostname, port });

            var newParameters = new List<Expression>(method.Parameters) { optionsParam };
            var callback = Expression.Parameter(new FickleDelegateType(typeof(void), new FickleParameterInfo(responseType, "response")), "callback");

            newParameters.Add(callback);

            Expression blockArg = Expression.Parameter(FickleType.Define("id"), "arg1");

            var returnType = method.ReturnType;

            if (ObjectiveBinderHelpers.NeedsValueResponseWrapper(method.ReturnType))
            {
                returnType = FickleType.Define(ObjectiveBinderHelpers.GetValueResponseWrapperTypeName(method.ReturnType));
            }

            var responseFilter = FickleExpression.Property(self, "FKGatewayResponseFilter", "responseFilter");
            var conversion = Expression.Convert(blockArg, returnType);

            var innerRetryBlockBody = FickleExpression.Block
            (
                FickleExpression.Call(Expression.Convert(retryBlockParameter, retryBlockVariable.Type), typeof(void), "Invoke", new { block = retryBlockParameter }).ToStatement()
            );

            var innerRetryBlock = (Expression)FickleExpression.SimpleLambda
            (
                typeof(void), innerRetryBlockBody, new Expression[0]
            );

            var body = FickleExpression.GroupedWide
            (
                Expression.IfThen(Expression.NotEqual(responseFilter, Expression.Constant(null, responseFilter.Type)), Expression.Assign(blockArg, FickleExpression.Call(responseFilter, typeof(object), "gateway", new { value = self, receivedResponse = blockArg, fromRequestURL = url, withRequestObject = requestObject, retryBlock = innerRetryBlock, andOptions = localOptions })).ToStatementBlock()),
                Expression.IfThen
                (
                    Expression.AndAlso(Expression.NotEqual(blockArg, Expression.Constant(null, blockArg.Type)), Expression.NotEqual(callback, Expression.Constant(null, callback.Type))),
                    FickleExpression.Call(callback, "Invoke", conversion).ToStatementBlock()
                )
            );

            var conversionBlock = FickleExpression.SimpleLambda(null, body, new Expression[0], blockArg);

            var error = FickleExpression.Variable("NSError", "error");

            Expression parseResultBlock;

            var nsdataParam = Expression.Parameter(FickleType.Define("NSData"), "data");
            var clientParam = Expression.Parameter(FickleType.Define("PKWebServiceClient"), "client");
            var jsonObjectWithDataParameters = new[] { new FickleParameterInfo(FickleType.Define("NSDictionary"), "obj"), new FickleParameterInfo(typeof(int), "options"), new FickleParameterInfo(FickleType.Define("NSError", true), "error", true) };
            var objectWithDataMethodInfo = new FickleMethodInfo(FickleType.Define("NSJSONSerialization"), FickleType.Define("NSData"), "JSONObjectWithData", jsonObjectWithDataParameters, true);
            var deserializedValue = Expression.Parameter(FickleType.Define("id"), "deserializedValue");

            var parseErrorResult = FickleExpression.Call(self, "webServiceClient", new
            {
                clientParam,
                createErrorResponseWithErrorCode = "JsonDeserializationError",
                andMessage = FickleExpression.Call(error, "localizedDescription", null)
            });

            if (method.ReturnType == typeof(void))
            {
                var responseObject = FickleExpression.Variable(responseType, "responseObject");

                parseResultBlock = FickleExpression.SimpleLambda
                (
                    FickleType.Define("id"),
                    FickleExpression.GroupedWide
                    (
                        Expression.Assign(responseObject, FickleExpression.New(responseType, "init", null)).ToStatement(),
                        Expression.Assign(deserializedValue, Expression.Call(objectWithDataMethodInfo, nsdataParam, FickleExpression.Variable(typeof(int), "NSJSONReadingAllowFragments"), error)).ToStatement(),
                        Expression.IfThen(Expression.Equal(deserializedValue, Expression.Constant(null)), FickleExpression.Return(parseErrorResult).ToStatementBlock()),
                        FickleExpression.Return(responseObject).ToStatement()
                    ),
                    new Expression[] { deserializedValue, responseObject, error },
                    clientParam, nsdataParam
                );
            }
            else if (TypeSystem.IsPrimitiveType(method.ReturnType) || method.ReturnType is FickleListType)
            {
                var responseObject = FickleExpression.Variable(responseType, "responseObject");
                var needToBoxValue = ObjectiveBinderHelpers.ValueResponseValueNeedsBoxing(method.ReturnType);

                parseResultBlock = FickleExpression.SimpleLambda
                (
                    FickleType.Define("id"),
                    FickleExpression.GroupedWide
                    (
                        Expression.Assign(responseObject, FickleExpression.New(responseType, "init", null)).ToStatement(),
                        Expression.Assign(deserializedValue, Expression.Call(objectWithDataMethodInfo, nsdataParam, FickleExpression.Variable(typeof(int), "NSJSONReadingAllowFragments"), error)).ToStatement(),
                        Expression.IfThen(Expression.Equal(deserializedValue, Expression.Constant(null)), FickleExpression.Return(parseErrorResult).ToStatementBlock()),
                        PropertiesFromDictionaryExpressonBinder.GetDeserializeExpressionProcessValueDeserializer(method.ReturnType, deserializedValue, c => FickleExpression.Call(responseObject, typeof(void), "setValue", needToBoxValue  ? Expression.Convert(c, typeof(object)) : c).ToStatement()),
                        FickleExpression.Return(responseObject).ToStatement()
                    ),
                    new Expression[] { deserializedValue, responseObject, error },
                    clientParam, nsdataParam
                );
            }
            else
            {
                parseResultBlock = FickleExpression.SimpleLambda
                (
                    FickleType.Define("id"),
                    FickleExpression.GroupedWide
                    (
                        Expression.Assign(deserializedValue, Expression.Call(objectWithDataMethodInfo, nsdataParam, FickleExpression.Variable(typeof(int), "NSJSONReadingAllowFragments"), error)).ToStatement(),
                        PropertiesFromDictionaryExpressonBinder.GetDeserializeExpressionProcessValueDeserializer(method.ReturnType, deserializedValue, c => FickleExpression.Return(c).ToStatement()),
                        FickleExpression.Return(parseErrorResult).ToStatement()
                    ),
                    new Expression[] { deserializedValue, error },
                    clientParam, nsdataParam
                );
            }

            var uniqueNameMaker = new UniqueNameMaker(c => newParameters.Cast<ParameterExpression>().Any(d => d.Name.EqualsIgnoreCaseInvariant(c)));

            var key = FickleExpression.Variable(typeof(string), uniqueNameMaker.Make("key"));

            var integrateOptions = FickleExpression.ForEach
            (
                key,
                optionsParam,
                FickleExpression.Call(localOptions, typeof(void), "setObject", new { value = FickleExpression.Call(optionsParam, typeof(object), "objectForKey", key), forKey = key }).ToStatementBlock()
            );

            parseResultBlock = FickleExpression.Call(parseResultBlock, parseResultBlock.Type, "copy", null);

            var client = Expression.Variable(FickleType.Define(this.CodeGenerationContext.Options.ServiceClientTypeName ?? "PKWebServiceClient"), "client");

            Expression clientCallExpression;

            if (httpMethod.Equals("get", StringComparison.InvariantCultureIgnoreCase))
            {
                clientCallExpression = FickleExpression.Call(client, "getWithCallback", conversionBlock);
            }
            else
            {
                var contentParameterName = method.Attributes["Content"];
                var contentFormat = method.Attributes["ContentFormat"];

                if (string.IsNullOrEmpty(contentParameterName))
                {
                    clientCallExpression = FickleExpression.Call(client, "postWithRequestObject", new
                    {
                        requestObject,
                        andCallback = conversionBlock
                    });
                }
                else
                {
                    var content = parametersByName[contentParameterName];

                    requestObjectValue = content.Type == typeof(byte[]) ? (Expression)content : FickleExpression.Call(self, typeof(object), this.GetNormalizeRequestMethodName(content.Type, contentFormat), new { serializeRequest = Expression.Convert(content, typeof(object)), paramName = Expression.Constant(contentParameterName) });

                    clientCallExpression = FickleExpression.Call(client, "postWithRequestObject", new
                    {
                        requestObject,
                        andCallback = conversionBlock
                    });
                }
            }

            var retryBlock = (Expression)FickleExpression.SimpleLambda
            (
                typeof(void),
                FickleExpression.StatementisedGroupedExpression
                (
                    Expression.Assign(client, FickleExpression.Call(Expression.Variable(currentType, "self"), "PKWebServiceClient", "createClientWithURL", new
                    {
                        url,
                        options = localOptions
                    })),
                    Expression.Assign(FickleExpression.Property(client, currentType, "delegate"), self),
                    clientCallExpression
                ),
                new Expression[] { client },
                retryBlockParameter
            );

            retryBlock = FickleExpression.Call(retryBlock, retryBlock.Type, "copy", null);

            var block = FickleExpression.Block
            (
                variables.Concat(retryBlockVariable).ToArray(),
                Expression.Assign(requestObject, requestObjectValue),
                Expression.Assign(callback, FickleExpression.Call(callback, callback.Type, "copy", null)),
                Expression.Assign(localOptions, FickleExpression.Call(FickleExpression.Property(self, FickleType.Define("NSDictionary"), "options"), "NSMutableDictionary", "mutableCopyWithZone", new
                {
                    zone = Expression.Constant(null, FickleType.Define("NSZone"))
                })),
                Expression.IfThen(Expression.NotEqual(requestObject, Expression.Constant(null)), FickleExpression.Call(localOptions, typeof(void), "setObject", new { value = requestObject, forKey = "$RequestObject" }).ToStatementBlock()),
                FickleExpression.Call(localOptions, typeof(void), "setObject", new { value = FickleExpression.StaticCall(responseType, "class", null), forKey = "$ResponseClass" }).ToStatement(),
                Expression.Assign(hostname, FickleExpression.Call(localOptions, typeof(string), "objectForKey", Expression.Constant("hostname"))),
                Expression.IfThen(Expression.Equal(hostname, Expression.Constant(null)), Expression.Assign(hostname, Expression.Constant(declaredHostname)).ToStatementBlock()),
                Expression.Assign(protocol, FickleExpression.Call(localOptions, typeof(string), "objectForKey", Expression.Constant("protocol"))),
                Expression.IfThen(Expression.Equal(protocol, Expression.Constant(null)), Expression.Assign(protocol, Expression.Constant(declaredProtocol)).ToStatementBlock()),
                Expression.Assign(port, FickleExpression.Call(FickleExpression.Call(localOptions, FickleType.Define("NSNumber"), "objectForKey", Expression.Constant("port")), typeof(string), "stringValue", null)),
                Expression.IfThenElse(Expression.Equal(port, Expression.Constant(null)), Expression.Assign(port, Expression.Constant("")).ToStatementBlock(), Expression.Assign(port, FickleExpression.Call(Expression.Constant(":"), typeof(string), "stringByAppendingString", port)).ToStatementBlock()),
                FickleExpression.Grouped
                (
                    FickleExpression.Call(localOptions, "setObject", new
                    {
                        obj = parseResultBlock,
                        forKey = "$ParseResultBlock"
                    }).ToStatement(),
                    method.ReturnType.GetUnwrappedNullableType() == typeof(bool) ?
                    FickleExpression.Call(localOptions, "setObject", new
                    {
                        obj = Expression.Convert(Expression.Constant(1), typeof(object))
                    }).ToStatement() : null
                ),
                Expression.Assign(url, Expression.Call(null, methodInfo, args)),
                FickleExpression.Call(localOptions, typeof(void), "setObject", new { value = url, forKey = "$RequestURL" }).ToStatement(),
                integrateOptions,
                Expression.Assign(retryBlockVariable, retryBlock),
                FickleExpression.Call(retryBlockVariable, typeof(void), "Invoke", retryBlockVariable).ToStatement()
            );

            optionsParameter = optionsParam;

            return new MethodDefinitionExpression(methodName, newParameters.ToReadOnlyCollection(), typeof(void), block, false, null);
        }
Esempio n. 12
0
        protected override Expression VisitMethodDefinitionExpression(MethodDefinitionExpression method)
        {
            WriteLine();

            if (method.ReturnType != null) //null for constructors
            {
                this.Write(method.ReturnType);
                this.Write(" ");
            }

            this.Write(method.Name);

            this.Write("(");
            for (var i = 0; i < method.Parameters.Count; i++)
            {
                var parameter = (ParameterExpression)method.Parameters[i];

                if (parameter.Type is FickleNullable)
                {
                    this.Write(parameter.Type.GetUnwrappedNullableType());
                }
                else
                {
                    this.Write(parameter.Type);
                }

                this.Write(" ");
                this.Write(parameter.Name);

                if (i != method.Parameters.Count - 1)
                {
                    this.Write(", ");
                }
            }

            this.Write(")");

            if (method.Exceptions != null && method.Exceptions.Count > 0)
            {
                this.Write(" throws");

                foreach (var exception in method.Exceptions)
                {
                    this.Write(" ");
                    this.Write(exception.GetType());
                }
            }

            this.WriteLine();

            this.Visit(method.Body);

            return method;
        }
Esempio n. 13
0
        protected override Expression VisitMethodDefinitionExpression(MethodDefinitionExpression method)
        {
            AddType(method.ReturnType);

            return base.VisitMethodDefinitionExpression(method);
        }
Esempio n. 14
0
        protected override Expression VisitMethodDefinitionExpression(MethodDefinitionExpression method)
        {
            this.WriteLine();

            this.Write(AccessModifiersToString(method.AccessModifiers));

            if (method.ReturnType != null) //null for constructors
            {
                var fickleTaskReturnType = method.ReturnType as CSharpAwaitedTaskType;
                if (fickleTaskReturnType != null)
                {
                    this.Write("async ");
                }

                this.Write(method.ReturnType);
                this.Write(" ");
            }

            this.Write(method.Name);

            this.Write("(");
            for (var i = 0; i < method.Parameters.Count; i++)
            {
                var parameter = (ParameterExpression)method.Parameters[i];

                if (parameter.Type is FickleNullable)
                {
                    this.Write(parameter.Type.GetUnwrappedNullableType());
                }
                else
                {
                    this.Write(parameter.Type);
                }

                this.Write(" ");
                this.Write(parameter.Name);

                if (i != method.Parameters.Count - 1)
                {
                    this.Write(", ");
                }
            }

            this.Write(")");

            this.WriteLine();

            this.Visit(method.Body);

            return method;
        }