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); }