コード例 #1
0
        /// <summary>
        /// Writes a property accessor.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="propertyName">The property to access. Anything that can be converted to a string.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static JavascriptConversionContext WriteAccessor(
            [NotNull] this JavascriptConversionContext context,
            [NotNull] string propertyName)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (propertyName == null)
            {
                throw new ArgumentNullException(nameof(propertyName));
            }

            if (Regex.IsMatch(propertyName, @"^\w[\d\w]*$"))
            {
                context.GetWriter().Write('.');
                context.GetWriter().Write(propertyName);
            }
            else if (Regex.IsMatch(propertyName, @"^\d+$"))
            {
                context.GetWriter().Write('[');
                context.GetWriter().Write(propertyName);
                context.GetWriter().Write(']');
            }
            else
            {
                context.GetWriter().Write('[');
                context.GetWriter().WriteLiteral(propertyName);
                context.GetWriter().Write(']');
            }

            return(context);
        }
コード例 #2
0
ファイル: MemberInitAsJson.cs プロジェクト: ppekrol/lambda2js
        public override void ConvertToJavascript(JavascriptConversionContext context)
        {
            var initExpr = context.Node as MemberInitExpression;

            if (initExpr == null)
            {
                return;
            }
            var typeOk1 = this.NewObjectTypes?.Contains(initExpr.Type) ?? false;
            var typeOk2 = this.TypePredicate?.Invoke(initExpr.Type) ?? false;
            var typeOk3 = this.NewObjectTypes == null && this.TypePredicate == null;

            if (!typeOk1 && !typeOk2 && !typeOk3)
            {
                return;
            }
            if (initExpr.NewExpression.Arguments.Count > 0)
            {
                return;
            }
            if (initExpr.Bindings.Any(mb => mb.BindingType != MemberBindingType.Assignment))
            {
                return;
            }

            context.PreventDefault();
            var writer = context.GetWriter();

            using (writer.Operation(0))
            {
                writer.Write('{');

                var posStart = writer.Length;
                foreach (var assignExpr in initExpr.Bindings.Cast <MemberAssignment>())
                {
                    if (writer.Length > posStart)
                    {
                        writer.Write(',');
                    }

                    var metadataProvider = context.Options.GetMetadataProvider();
                    var meta             = metadataProvider.GetMemberMetadata(assignExpr.Member);
                    var memberName       = meta?.MemberName;
                    Debug.Assert(!string.IsNullOrEmpty(memberName), "!string.IsNullOrEmpty(memberName)");
                    if (Regex.IsMatch(memberName, @"^\w[\d\w]*$"))
                    {
                        writer.Write(memberName);
                    }
                    else
                    {
                        writer.WriteLiteral(memberName);
                    }

                    writer.Write(':');
                    context.Visitor.Visit(assignExpr.Expression);
                }

                writer.Write('}');
            }
        }
コード例 #3
0
        /// <summary>
        /// Writes a single character.
        /// </summary>
        /// <param name="context">The Javascript conversion context.</param>
        /// <param name="ch">Character to write.</param>
        /// <returns>The Javascript conversion context itself, to allow fluent style rendering.</returns>
        public static JavascriptConversionContext Write(this JavascriptConversionContext context, char ch)
        {
            var writer = context.GetWriter();

            writer.Write(ch);
            return(context);
        }
コード例 #4
0
        /// <summary>
        /// Writes many expressions isolated from outer and inner operations by opening, closing and separator characters.
        /// </summary>
        /// <param name="context">The Javascript conversion context.</param>
        /// <param name="opening">First character to render, isolating from outer operation.</param>
        /// <param name="closing">Last character to render, isolating from outer operation.</param>
        /// <param name="separator">Separator character to render, isolating one parameter from the other.</param>
        /// <param name="nodes">Nodes to render.</param>
        public static JavascriptConversionContext WriteManyIsolated(
            this JavascriptConversionContext context,
            char opening,
            char closing,
            char separator,
            IEnumerable <Expression> nodes)
        {
            var writer = context.GetWriter();

            writer.Write(opening);
            using (writer.Operation(0))
                context.WriteMany(separator, nodes);
            writer.Write(closing);
            return(context);
        }
コード例 #5
0
        /// <summary>
        /// Writes many expression nodes, separated by the given separator.
        /// </summary>
        /// <param name="context">The Javascript conversion context.</param>
        /// <param name="separator">Separator to be used.</param>
        /// <param name="nodes">A list of nodes to write.</param>
        /// <returns>The Javascript conversion context itself, to allow fluent style rendering.</returns>
        public static JavascriptConversionContext WriteMany(
            this JavascriptConversionContext context,
            char separator,
            IEnumerable <Expression> nodes)
        {
            var writer = context.GetWriter();
            int count  = 0;

            foreach (var node in nodes)
            {
                if (count++ > 0)
                {
                    writer.Write(separator);
                }

                context.Visitor.Visit(node);
            }
            return(context);
        }
コード例 #6
0
ファイル: LinqMethods.cs プロジェクト: timbrown81/lambda2js
        public override void ConvertToJavascript(JavascriptConversionContext context)
        {
            var methodCall = context.Node as MethodCallExpression;

            if (methodCall != null)
            {
                if (methodCall.Method.DeclaringType == typeof(Enumerable))
                {
                    switch (methodCall.Method.Name)
                    {
                    case "Select":
                    {
                        var writer = context.GetWriter();
                        using (writer.Operation(JavascriptOperationTypes.Call))
                        {
                            using (writer.Operation(JavascriptOperationTypes.IndexerProperty))
                            {
                                // public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
                                // public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
                                var pars = methodCall.Method.GetParameters();
                                if (pars.Length != 2)
                                {
                                    throw new NotSupportedException("The `Enumerable.Select` method must have 2 parameters.");
                                }

                                context.Visitor.Visit(methodCall.Arguments[0]);
                                writer.Write(".map");
                            }

                            writer.Write('(');

                            // separator
                            using (writer.Operation(0))
                                context.Visitor.Visit(methodCall.Arguments[1]);

                            writer.Write(')');
                        }

                        return;
                    }

                    case "Where":
                    {
                        var writer = context.GetWriter();
                        using (writer.Operation(JavascriptOperationTypes.Call))
                        {
                            using (writer.Operation(JavascriptOperationTypes.IndexerProperty))
                            {
                                // public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
                                // public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
                                var pars = methodCall.Method.GetParameters();
                                if (pars.Length != 2)
                                {
                                    throw new NotSupportedException("The `Enumerable.Where` method must have 2 parameters.");
                                }

                                context.Visitor.Visit(methodCall.Arguments[0]);
                                writer.Write(".filter");
                            }

                            writer.Write('(');

                            // separator
                            using (writer.Operation(0))
                                context.Visitor.Visit(methodCall.Arguments[1]);

                            writer.Write(')');
                        }

                        return;
                    }

                    case "ToArray":
                    {
                        // Ecma Script 6+: use spread operator
                        // Other: use array `slice`
                        if (context.Options.ScriptVersion.Supports(JavascriptSyntax.ArraySpread))
                        {
                            var writer = context.GetWriter();
                            using (writer.Operation(0))
                            {
                                writer.Write('[');
                                writer.Write("...");
                                using (writer.Operation(JavascriptOperationTypes.ParamIsolatedLhs))
                                    context.Visitor.Visit(methodCall.Arguments[0]);
                                writer.Write(']');
                            }
                        }
                        else
                        {
                            var writer = context.GetWriter();
                            using (writer.Operation(JavascriptOperationTypes.Call))
                            {
                                using (writer.Operation(JavascriptOperationTypes.IndexerProperty))
                                {
                                    context.Visitor.Visit(methodCall.Arguments[0]);
                                    writer.Write(".slice");
                                }

                                writer.Write('(');
                                writer.Write(')');
                            }
                        }

                        return;
                    }
                    }
                }
            }
        }
コード例 #7
0
        public override void ConvertToJavascript(JavascriptConversionContext context)
        {
            var cte = context.Node as ConstantExpression;

            if (cte != null && cte.Type.GetTypeInfo().IsEnum)
            {
                context.PreventDefault();
                var  writer        = context.GetWriter();
                long remaining     = Convert.ToInt64(cte.Value);
                var  flagsAsString = (this.opts & EnumOptions.FlagsAsStringWithSeparator) != 0;
                var  flagsAsOrs    = (this.opts & EnumOptions.FlagsAsNumericOrs) != 0;
                var  flagsAsArray  = (this.opts & EnumOptions.FlagsAsArray) != 0;
                var  isFlags       = cte.Type.GetTypeInfo().IsDefined(typeof(FlagsAttribute), false);

                // when value is zero
                if (remaining == 0 && (!isFlags || !(flagsAsString || flagsAsOrs || flagsAsArray)))
                {
                    if (WriteSingleEnumItem(context, writer, 0, cte.Value, false))
                    {
                        return;
                    }
                }

                // reading enum composition
                var values   = Enum.GetValues(cte.Type);
                var selected = new List <int>();
                for (int itV = 0; itV < values.Length; itV++)
                {
                    var val = Convert.ToInt64(values.GetValue(values.Length - itV - 1));
                    if ((val & remaining) == val)
                    {
                        remaining &= ~val;
                        selected.Add(values.Length - itV - 1);

                        if (!isFlags)
                        {
                            break;
                        }
                    }
                }

                // selecting enum case
                if (isFlags)
                {
                    var cnt = selected.Count + (remaining != 0 ? 1 : 0);


                    PrecedenceController xpto = null;
                    string start     = "";
                    string separator = "";
                    string end       = "";

                    if (flagsAsString)
                    {
                        xpto      = writer.Operation(JavascriptOperationTypes.Literal);
                        start     = "\"";
                        separator = "|";
                        end       = "\"";
                    }
                    else if (flagsAsArray)
                    {
                        xpto      = writer.Operation(0);
                        start     = "[";
                        separator = ",";
                        end       = "]";
                    }
                    else if (flagsAsOrs && cnt > 1)
                    {
                        xpto      = writer.Operation(JavascriptOperationTypes.Or);
                        start     = "";
                        separator = "|";
                        end       = "";
                    }
                    else if (cnt > 1)
                    {
                        throw new NotSupportedException("When converting flags enums to JavaScript, a flags option must be specified.");
                    }

                    using (xpto)
                    {
                        writer.Write(start);
                        var pos0 = writer.Length;
                        for (int itIdx = 0; itIdx < selected.Count; itIdx++)
                        {
                            if (pos0 != writer.Length)
                            {
                                writer.Write(separator);
                            }

                            var index   = selected[itIdx];
                            var enumVal = values.GetValue(index);
                            var val     = Convert.ToInt64(enumVal);
                            WriteSingleEnumItem(context, writer, val, enumVal, flagsAsString);
                        }

                        if (remaining != 0)
                        {
                            if (pos0 != writer.Length)
                            {
                                writer.Write(separator);
                            }
                            WriteSingleEnumItem(context, writer, remaining, remaining, flagsAsString);
                        }
                        writer.Write(end);
                    }
                }
                else
                {
                    if (remaining != 0)
                    {
                        var enumVal = cte.Value;
                        var val     = Convert.ToInt64(cte.Value);
                        WriteSingleEnumItem(context, writer, val, enumVal, false);
                    }
                    else
                    {
                        foreach (var index in selected)
                        {
                            var enumVal = values.GetValue(index);
                            var val     = Convert.ToInt64(enumVal);
                            WriteSingleEnumItem(context, writer, val, enumVal, false);
                        }
                    }
                }
            }
        }
コード例 #8
0
        public override void ConvertToJavascript(JavascriptConversionContext context)
        {
            var methodCall = context.Node as MethodCallExpression;

            if (methodCall != null)
            {
                if (methodCall.Method.DeclaringType == typeof(string))
                {
                    switch (methodCall.Method.Name)
                    {
                    case "Concat":
                    {
                        context.PreventDefault();
                        var writer = context.GetWriter();
                        using (writer.Operation(JavascriptOperationTypes.Concat))
                        {
                            if (methodCall.Arguments.Count == 0)
                            {
                                writer.Write("''");
                            }
                            else
                            {
                                if (GetTypeOfExpression(methodCall.Arguments[0]) != typeof(string))
                                {
                                    writer.Write("''+");
                                }
                                context.WriteMany('+', methodCall.Arguments);
                            }
                        }

                        return;
                    }

                    case "Join":
                    {
                        context.PreventDefault();
                        var writer = context.GetWriter();
                        using (writer.Operation(JavascriptOperationTypes.Call))
                        {
                            using (writer.Operation(JavascriptOperationTypes.IndexerProperty))
                            {
                                var pars = methodCall.Method.GetParameters();
                                if (pars.Length == 4 && pars[1].ParameterType.IsArray && pars[2].ParameterType == typeof(int) && pars[3].ParameterType == typeof(int))
                                {
                                    throw new NotSupportedException("The `String.Join` method with start and count paramaters is not supported.");
                                }

                                if (pars.Length != 2 || !TypeHelpers.IsEnumerableType(pars[1].ParameterType))
                                {
                                    throw new NotSupportedException("This `String.Join` method is not supported.");
                                }

                                // if second parameter is an enumerable, render it directly
                                context.Visitor.Visit(methodCall.Arguments[1]);
                                writer.Write(".join");
                            }

                            writer.Write('(');

                            // separator
                            using (writer.Operation(0))
                                context.Visitor.Visit(methodCall.Arguments[0]);

                            writer.Write(')');
                        }

                        return;
                    }
                    }
                }
            }
        }
コード例 #9
0
 public static JavascriptConversionContext WriteFormat(this JavascriptConversionContext context, string format, params object[] values)
 {
     context.GetWriter().WriteFormat(format, values);
     return(context);
 }
コード例 #10
0
 /// <summary>
 /// Writes a string to the output.
 /// </summary>
 /// <param name="context">The Javascript conversion context.</param>
 /// <param name="str">String to write.</param>
 /// <returns>The Javascript conversion context itself, to allow fluent style rendering.</returns>
 public static JavascriptConversionContext Write(this JavascriptConversionContext context, string str)
 {
     context.GetWriter().Write(str);
     return(context);
 }
コード例 #11
0
 /// <summary>
 /// Encloses the following write calls in an operation context,
 /// that will automatically write precedence operators '(' and ')' if needed,
 /// depening on the operations stack.
 /// <para>
 /// For example, a sum (+)
 /// inside a multiplication (*) requires the precedence operators.
 /// </para>
 /// <para>
 /// To isolate operations, you can pass 0 to the <paramref name="op"/> parameter,
 /// making neither the current nor the inner operation need precedence operators.
 /// </para>
 /// </summary>
 /// <param name="context">Context of the conversion.</param>
 /// <param name="op">The operation that you want to render in the scope.</param>
 /// <returns>A disposable object that renders the ending ')' when needed.</returns>
 public static IDisposable Operation(
     this JavascriptConversionContext context,
     JavascriptOperationTypes op)
 {
     return(context.GetWriter().Operation(op));
 }