Beispiel #1
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (node.Method.IsSpecialName)
            {
                var isIndexer = node.Method.Name == "get_Item" || node.Method.Name == "get_Chars";
                if (isIndexer)
                {
                    using (this.result.Operation(JavascriptOperationTypes.IndexerProperty))
                    {
                        this.Visit(node.Object);
                        this.result.Write('[');

                        using (this.result.Operation(0))
                        {
                            var posStart0 = this.result.Length;
                            foreach (var arg in node.Arguments)
                            {
                                if (this.result.Length != posStart0)
                                {
                                    this.result.Write(',');
                                }

                                this.Visit(arg);
                            }
                        }

                        this.result.Write(']');
                        return(node);
                    }
                }

                if (node.Method.Name == "set_Item")
                {
                    using (this.result.Operation(0))
                    {
                        using (this.result.Operation(JavascriptOperationTypes.AssignRhs))
                        {
                            using (this.result.Operation(JavascriptOperationTypes.IndexerProperty))
                            {
                                this.Visit(node.Object);
                                this.result.Write('[');

                                using (this.result.Operation(0))
                                {
                                    var posStart0 = this.result.Length;
                                    foreach (var arg in node.Arguments)
                                    {
                                        if (this.result.Length != posStart0)
                                        {
                                            this.result.Write(',');
                                        }

                                        this.Visit(arg);
                                    }
                                }

                                this.result.Write(']');
                            }
                        }

                        this.result.Write('=');
                        this.Visit(node.Arguments.Single());
                    }

                    return(node);
                }
            }
            else
            {
                if (node.Method.DeclaringType != null &&
                    (node.Method.Name == "ContainsKey" &&
                     TypeHelpers.IsDictionaryType(node.Method.DeclaringType)))
                {
                    using (this.result.Operation(JavascriptOperationTypes.Call))
                    {
                        using (this.result.Operation(JavascriptOperationTypes.IndexerProperty))
                            this.Visit(node.Object);
                        this.result.Write(".hasOwnProperty(");
                        using (this.result.Operation(0))
                            this.Visit(node.Arguments.Single());
                        this.result.Write(')');
                        return(node);
                    }
                }
            }

            if (node.Method.DeclaringType == typeof(string))
            {
                if (node.Method.Name == "Contains")
                {
                    using (this.result.Operation(JavascriptOperationTypes.Comparison))
                    {
                        using (this.result.Operation(JavascriptOperationTypes.Call))
                        {
                            using (this.result.Operation(JavascriptOperationTypes.IndexerProperty))
                                this.Visit(node.Object);
                            this.result.Write(".indexOf(");
                            using (this.result.Operation(0))
                            {
                                var posStart = this.result.Length;
                                foreach (var arg in node.Arguments)
                                {
                                    if (this.result.Length > posStart)
                                    {
                                        this.result.Write(',');
                                    }
                                    this.Visit(arg);
                                }
                            }

                            this.result.Write(')');
                        }

                        this.result.Write(">=0");
                        return(node);
                    }
                }
            }

            if (node.Method.Name == "ToString" && node.Type == typeof(string) && node.Object != null)
            {
                string methodName = null;
                if (node.Arguments.Count == 0 || typeof(IFormatProvider).IsAssignableFrom(node.Arguments[0].Type))
                {
                    methodName = "toString()";
                }
                else if (TypeHelpers.IsNumericType(node.Object.Type) &&
                         node.Arguments.Count >= 1 &&
                         node.Arguments[0].Type == typeof(string) &&
                         node.Arguments[0].NodeType == ExpressionType.Constant)
                {
                    var str   = (string)((ConstantExpression)node.Arguments[0]).Value;
                    var match = Regex.Match(str, @"^([DEFGNX])(\d*)$", RegexOptions.IgnoreCase);
                    var f     = match.Groups[1].Value.ToUpper();
                    var n     = match.Groups[2].Value;
                    if (f == "D")
                    {
                        methodName = "toString()";
                    }
                    else if (f == "E")
                    {
                        methodName = "toExponential(" + n + ")";
                    }
                    else if (f == "F" || f == "G")
                    {
                        methodName = "toFixed(" + n + ")";
                    }
                    else if (f == "N")
                    {
                        methodName = "toLocaleString()";
                    }
                    else if (f == "X")
                    {
                        methodName = "toString(16)";
                    }
                }

                if (methodName != null)
                {
                    using (this.result.Operation(JavascriptOperationTypes.Call))
                    {
                        using (this.result.Operation(JavascriptOperationTypes.IndexerProperty))
                            this.Visit(node.Object);
                        this.result.WriteFormat(".{0}", methodName);
                        return(node);
                    }
                }
            }

            if (!node.Method.IsStatic)
            {
                throw new NotSupportedException(string.Format("By default, Lambda2Js cannot convert custom instance methods, only static ones. `{0}` is not static.", node.Method.Name));
            }

            using (this.result.Operation(JavascriptOperationTypes.Call))
                if (node.Method.DeclaringType != null)
                {
                    this.result.Write(node.Method.DeclaringType.FullName);
                    this.result.Write('.');
                    this.result.Write(node.Method.Name);
                    this.result.Write('(');

                    var posStart = this.result.Length;
                    using (this.result.Operation(0))
                        foreach (var arg in node.Arguments)
                        {
                            if (this.result.Length != posStart)
                            {
                                this.result.Write(',');
                            }

                            this.Visit(arg);
                        }

                    this.result.Write(')');

                    return(node);
                }

            return(node);
        }
Beispiel #2
0
        protected override Expression VisitListInit(ListInitExpression node)
        {
            // Detecting a new dictionary
            if (TypeHelpers.IsDictionaryType(node.Type))
            {
                using (this.result.Operation(0))
                {
                    this.result.Write('{');

                    var posStart = this.result.Length;
                    foreach (var init in node.Initializers)
                    {
                        if (this.result.Length > posStart)
                        {
                            this.result.Write(',');
                        }

                        if (init.Arguments.Count != 2)
                        {
                            throw new NotSupportedException(
                                      "Objects can only be initialized with methods that receive pairs: key -> name");
                        }

                        var nameArg = init.Arguments[0];
                        if (nameArg.NodeType != ExpressionType.Constant || nameArg.Type != typeof(string))
                        {
                            throw new NotSupportedException("The key of an object must be a constant string value");
                        }

                        var name = (string)((ConstantExpression)nameArg).Value;
                        if (Regex.IsMatch(name, @"^\w[\d\w]*$"))
                        {
                            this.result.Write(name);
                        }
                        else
                        {
                            this.WriteStringLiteral(name);
                        }

                        this.result.Write(':');
                        this.Visit(init.Arguments[1]);
                    }

                    this.result.Write('}');
                }

                return(node);
            }

            // Detecting a new dictionary
            if (TypeHelpers.IsListType(node.Type))
            {
                using (this.result.Operation(0))
                {
                    this.result.Write('[');

                    var posStart = this.result.Length;
                    foreach (var init in node.Initializers)
                    {
                        if (this.result.Length > posStart)
                        {
                            this.result.Write(',');
                        }

                        if (init.Arguments.Count != 1)
                        {
                            throw new Exception(
                                      "Arrays can only be initialized with methods that receive a single parameter for the value");
                        }

                        this.Visit(init.Arguments[0]);
                    }

                    this.result.Write(']');
                }

                return(node);
            }

            return(node);
        }