private bool WriteSingleEnumItem(
            JavascriptConversionContext context,
            JavascriptWriter writer,
            long numValue,
            object enumValue,
            bool inStringAlready)
        {
            if ((this.opts & EnumOptions.UseStrings) != 0)
            {
                if (inStringAlready)
                {
                    if ((this.opts & EnumOptions.UseNumbers) != 0)
                    {
                        writer.WriteLiteralStringContent(numValue.ToString());
                    }
                    else
                    {
                        var str = enumValue.ToString();
                        if (numValue == 0 && str == "0")
                        {
                            writer.WriteLiteralStringContent("");
                        }
                        else
                        {
                            writer.WriteLiteralStringContent(str);
                        }
                    }
                    return(true);
                }

                using (writer.Operation(JavascriptOperationTypes.Literal))
                {
                    if ((this.opts & EnumOptions.UseNumbers) != 0)
                    {
                        writer.WriteLiteral(numValue.ToString());
                    }
                    else
                    {
                        var str = enumValue.ToString();
                        if (numValue == 0 && str == "0")
                        {
                            writer.WriteLiteral("");
                        }
                        else
                        {
                            writer.WriteLiteral(str);
                        }
                    }
                    return(true);
                }
            }

            if ((this.opts & EnumOptions.UseNumbers) != 0)
            {
                using (writer.Operation(JavascriptOperationTypes.Literal))
                    writer.WriteLiteral(numValue);
                return(true);
            }

            if ((this.opts & EnumOptions.UseStaticFields) != 0)
            {
                using (writer.Operation(JavascriptOperationTypes.IndexerProperty))
                    context.Write(enumValue.GetType().Name).WriteAccessor(enumValue.ToString());
                return(true);
            }

            return(false);
        }
Ejemplo n.º 2
0
        public override void ConvertToJavascript(JavascriptConversionContext context)
        {
            var methodCall = context.Node as MethodCallExpression;

            if (methodCall != null)
            {
                if (methodCall.Method.DeclaringType == typeof(Math))
                {
                    NameLength jsInfo;
                    if (membersMap.TryGetValue(methodCall.Method.Name, out jsInfo))
                    {
                        if (methodCall.Arguments.Count == jsInfo.length)
                        {
                            using (context.Operation(JavascriptOperationTypes.Call))
                            {
                                using (context.Operation(JavascriptOperationTypes.IndexerProperty))
                                    context.Write("Math." + jsInfo.name);
                                context.WriteManyIsolated('(', ')', ',', methodCall.Arguments);
                            }

                            return;
                        }
                        else if (methodCall.Method.Name == "Log" &&
                                 methodCall.Arguments.Count == 2)
                        {
                            // JavaScript does not support `Math.log` with 2 parameters,
                            // But it is easy enough for us to give a little help!
                            using (context.Operation(JavascriptOperationTypes.MulDivMod))
                            {
                                using (context.Operation(JavascriptOperationTypes.Call))
                                {
                                    using (context.Operation(JavascriptOperationTypes.IndexerProperty))
                                        context.Write("Math.log");
                                    context.Write('(');
                                    using (context.Operation(0))
                                        context.Write(methodCall.Arguments[0]);
                                    context.Write(')');
                                }

                                context.Write('/');

                                using (context.Operation(JavascriptOperationTypes.Call))
                                {
                                    using (context.Operation(JavascriptOperationTypes.IndexerProperty))
                                        context.Write("Math.log");
                                    context.Write('(');
                                    using (context.Operation(0))
                                        context.Write(methodCall.Arguments[1]);
                                    context.Write(')');
                                }
                            }

                            return;
                        }
                        else if (methodCall.Method.Name == "Round" &&
                                 methodCall.Arguments.Count == 2 &&
                                 TypeHelpers.IsNumericType(methodCall.Arguments[1].Type))
                        {
                            // We won't support `Math.Round` with two parameters by default.
                            // To do it, we'd have to repeat an input value in the expression (unacceptable):
                            //      Math.Round(A, B) => Math.round(A * Math.pow(10, B)) / Math.pow(10, B)
                            // Or start helping with hacky things (acceptable, but not by default):
                            //      Math.Round(A, B) => (function(a, b) { return Math.round(a * b) / b; })(A, Math.pow(10, B));
                            if (this.round2)
                            {
                                using (context.Operation(JavascriptOperationTypes.Call))
                                {
                                    context.WriteLambda <Func <double, double, double> >((a, b) => Math.Round(a * b) / b);
                                    context.Write('(');
                                    using (context.Operation(0))
                                        context.Write(methodCall.Arguments[0]);
                                    context.Write(',');
                                    using (context.Operation(0))
                                        using (context.Operation(JavascriptOperationTypes.Call))
                                        {
                                            using (context.Operation(JavascriptOperationTypes.IndexerProperty))
                                                context.Write("Math.pow");
                                            context.Write('(');
                                            context.Write("10");
                                            context.Write(',');
                                            using (context.Operation(0))
                                                context.Write(methodCall.Arguments[1]);
                                            context.Write(')');
                                        }

                                    context.Write(')');

                                    return;
                                }
                            }
                        }
                    }
                }
            }

            // E and PI are constant values, they will never result in
            // a member access expression. We will have to catch the
            // exact numbers, and convert them instead.
            var constVal = context.Node as ConstantExpression;

            if (constVal != null)
            {
                if (constVal.Value.Equals(Math.E))
                {
                    using (context.Operation(JavascriptOperationTypes.IndexerProperty))
                        context.Write("Math.E");
                }
                else if (constVal.Value.Equals(Math.PI))
                {
                    using (context.Operation(JavascriptOperationTypes.IndexerProperty))
                        context.Write("Math.PI");
                }
            }
        }