Example #1
0
        public static string Create(MethodReference mRef, Resolver resolver, ICode ast)
        {
            if (mRef.ContainsGenericParameters())
            {
                throw new ArgumentException("Cannot create JS for method with open generic parameters");
            }
            var mDef = mRef.Resolve();

            if (mDef.IsAbstract)
            {
                throw new ArgumentException("Should never need to transcode an abstract method");
            }
            var tRef = mRef.DeclaringType;
            var tDef = tRef.Resolve();

            var v = new JsMethod(resolver);

            v.Visit(ast);
            var js = v.js.ToString();

            var sb = new StringBuilder();
            // Method declaration
            var methodName = resolver.MethodNames[mRef];
            //var parameterNames = mRef.Parameters.Select(x => v.parameters.ValueOrDefault(x).NullThru(y => resolver.LocalVarNames[y])).ToArray();
            // Match parameters, but have to do by position, as method built may be a custom method replacing a BCL method,
            // so parameters are not the same.
            var parameterNames = mRef.Parameters.Select(x => v.parameters.FirstOrDefault(y => y.Key.Sequence == x.Sequence).Value.NullThru(y => resolver.LocalVarNames[y])).ToArray();

            if (!mDef.IsStatic)
            {
                var thisName = v.vars.FirstOrDefault(x => x.ExprType == Expr.NodeType.VarThis).NullThru(x => resolver.LocalVarNames[x]);
                parameterNames = parameterNames.Prepend(thisName).ToArray();
            }
            var unusedParameterNameGen = new NameGenerator();

            parameterNames = parameterNames.Select(x => x ?? ("_" + unusedParameterNameGen.GetNewName())).ToArray();
            sb.AppendFormat("// {0}", mRef.FullName);
            sb.AppendLine();
            sb.AppendFormat("var {0} = function({1}) {{", methodName, string.Join(", ", parameterNames));
            // Variable declarations
            var declVars = v.vars
                           .Select(x => new { name = resolver.LocalVarNames[x], type = x.Type })
                           .Where(x => !parameterNames.Contains(x.name))
                           .Select(x => {
                var name = x.name;
                if (x.type.IsValueType)
                {
                    name += " = " + DefaultValuer.Get(x.type, resolver.FieldNames);
                }
                return(name);
            })
                           .Distinct() // Bit of a hack, but works for now
                           .ToArray();

            if (declVars.Any())
            {
                sb.AppendLine();
                sb.Append(' ', tabSize);
                sb.AppendFormat("var {0};", string.Join(", ", declVars));
            }
            // Method body
            sb.AppendLine(js);
            // Method ending
            sb.AppendLine("};");

            var sbStr = sb.ToString();

            return(sbStr);
        }