protected virtual void EmitInlineExpressionList(ArgumentsInfo argsInfo, string inline, bool asRef = false, bool isNull = false, bool?definition = null) { IEnumerable <NamedParamExpression> expressions = argsInfo.NamedExpressions; IEnumerable <TypeParamExpression> typeParams = argsInfo.TypeArguments; bool addClose = false; this.Write(""); if (asRef) { var withoutTypeParams = this.Method.TypeArguments.Count > 0 && this.Method.TypeArguments.All(t => t.Kind != TypeKind.TypeParameter); if (definition.HasValue) { withoutTypeParams = !definition.Value; } if (withoutTypeParams && (!this.Method.IsStatic || this.Method.IsExtensionMethod && this.TargetResolveResult is ThisResolveResult) && (this.TargetResolveResult is ThisResolveResult || this.TargetResolveResult == null) && (inline.Contains("{this}") || this.Method.IsStatic || this.Method.IsExtensionMethod && inline.Contains("{" + this.Method.Parameters.First().Name + "}"))) { this.Write(JS.Funcs.BRIDGE_BIND); this.Write("(this, "); addClose = true; } this.Write("function ("); this.EmitMethodParameters(this.Method, this.Method.Parameters, withoutTypeParams ? null : this.Method.TypeParameters, isNull); this.Write(") { return "); } bool needExpand = false; bool expandParams = false; string paramsName = null; IType paramsType = null; int paramsIndex = 0; if (argsInfo.ResolveResult != null) { var paramsParam = argsInfo.ResolveResult.Member.Parameters.FirstOrDefault(p => p.IsParams); if (paramsParam != null) { paramsIndex = argsInfo.ResolveResult.Member.Parameters.IndexOf(paramsParam); paramsName = paramsParam.Name; paramsType = paramsParam.Type; } expandParams = argsInfo.ResolveResult.Member.Attributes.Any(a => a.AttributeType.FullName == "Bridge.ExpandParamsAttribute"); } else if (argsInfo.Method != null) { var paramsParam = argsInfo.Method.Parameters.FirstOrDefault(p => p.IsParams); if (paramsParam != null) { paramsIndex = argsInfo.Method.Parameters.IndexOf(paramsParam); paramsName = paramsParam.Name; paramsType = paramsParam.Type; } expandParams = argsInfo.Method.Attributes.Any(a => a.AttributeType.FullName == "Bridge.ExpandParamsAttribute"); } if (paramsName != null) { var matches = _formatArg.Matches(inline); bool ignoreArray = false; foreach (Match m in matches) { if (m.Groups[2].Value == paramsName) { bool isRaw = m.Groups[1].Success && m.Groups[1].Value == "*"; ignoreArray = isRaw || argsInfo.ParamsExpression == null; string modifier = m.Groups[1].Success ? m.Groups[4].Value : null; if (modifier == "array") { ignoreArray = false; } break; } } if (expandParams) { ignoreArray = true; } if (argsInfo.ResolveResult is CSharpInvocationResolveResult) { needExpand = !((CSharpInvocationResolveResult)argsInfo.ResolveResult).IsExpandedForm; } if (needExpand && ignoreArray && !asRef) { IList <Expression> exprs = this.GetExpressionsByKey(expressions, paramsName); if (exprs.Count == 1 && exprs[0] != null && exprs[0].Parent != null) { var exprrr = this.Emitter.Resolver.ResolveNode(exprs[0], this.Emitter); if (exprrr.Type.Kind == TypeKind.Array) { var match = _inlineMethod.Match(inline); if (match.Success) { string target = null; var methodName = match.Groups[1].Value; if (methodName.Contains(".")) { target = methodName.LeftOfRightmostOf('.'); } string args = match.Groups[2].Value; StringBuilder sb = new StringBuilder(); sb.Append(methodName); sb.Append("."); sb.Append(JS.Funcs.APPLY); sb.Append("("); sb.Append(target ?? "null"); if (args.Contains(",")) { sb.Append(", ["); sb.Append(args.LeftOfRightmostOf(',').Trim()); sb.Append("].concat("); sb.Append(args.RightOfRightmostOf(',').Trim()); sb.Append(")"); } else { sb.Append(","); sb.Append(args); } sb.Append(")"); inline = inline.Remove(match.Index, match.Length); inline = inline.Insert(match.Index, sb.ToString()); } } } } } var r = InlineArgumentsBlock._formatArg.Matches(inline); List <Match> keyMatches = new List <Match>(); foreach (Match keyMatch in r) { keyMatches.Add(keyMatch); } var tempVars = new Dictionary <string, string>(); var tempMap = new Dictionary <string, string>(); inline = _formatArg.Replace(inline, delegate(Match m) { if (this.IgnoreRange != null && m.Index >= this.IgnoreRange[0] && m.Index <= this.IgnoreRange[1]) { return(m.Value); } int count = this.Emitter.Writers.Count; string key = m.Groups[2].Value; bool isRaw = m.Groups[1].Success && m.Groups[1].Value == "*"; bool ignoreArray = isRaw || argsInfo.ParamsExpression == null; string modifier = m.Groups[1].Success ? m.Groups[4].Value : null; bool isSimple = false; var tempKey = key + ":" + modifier ?? ""; if (tempMap.ContainsKey(tempKey)) { return(tempMap[tempKey]); } if (!string.IsNullOrWhiteSpace(modifier) && !this.allowedModifiers.Contains(modifier)) { return(m.Value); } if (modifier == "array") { ignoreArray = false; } StringBuilder oldSb = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); if (modifier == "module") { IList <Expression> exprs = this.GetExpressionsByKey(expressions, key); if (exprs.Count > 0) { var amd = new List <string>(); var cjs = new List <string>(); foreach (var expr in exprs) { var rr = this.Emitter.Resolver.ResolveNode(expr, this.Emitter) as TypeOfResolveResult; if (rr == null) { throw new EmitterException(expr, "Module.Load supports typeof expression only"); } var bridgeType = this.Emitter.BridgeTypes.Get(rr.ReferencedType, true); Module module = null; if (bridgeType.TypeInfo == null) { BridgeTypes.EnsureModule(bridgeType); module = bridgeType.Module; } else { module = bridgeType.TypeInfo.Module; } AddModuleByType(amd, cjs, module); } this.Write("{"); if (amd.Count > 0) { this.Write("amd: "); this.Write(this.Emitter.ToJavaScript(amd.ToArray())); if (cjs.Count > 0) { this.Write(", "); } } if (cjs.Count > 0) { this.Write("cjs: "); this.Write(this.Emitter.ToJavaScript(cjs.ToArray())); } if (!string.IsNullOrWhiteSpace(this.Emitter.AssemblyInfo.Loader.FunctionName)) { this.Write(", "); this.Write(this.Emitter.ToJavaScript(this.Emitter.AssemblyInfo.Loader.FunctionName)); } this.Write("}, function () { "); var idx = 0; var list = amd.Concat(cjs); foreach (var moduleName in list) { this.Write(moduleName); this.Write(" = arguments["); this.Write(idx++); this.Write("];"); } this.Write(" }"); } } else if (asRef) { if (Regex.IsMatch(key, "^\\d+$")) { var index = int.Parse(key); key = this.Method.Parameters[index].Name; } if (modifier == "type") { this.Write(JS.Funcs.BRIDGE_GET_TYPE + "("); } if (key == "this") { if (isNull) { isSimple = true; this.Write(JS.Vars.T); } else if (this.Method.IsExtensionMethod && this.TargetResolveResult is TypeResolveResult) { isSimple = true; this.WriteParamName(this.Method.Parameters.First().Name); } else if (argsInfo.Expression is MemberReferenceExpression) { var trg = ((MemberReferenceExpression)argsInfo.Expression).Target; if (trg is BaseReferenceExpression) { isSimple = true; this.Write("this"); } else { isSimple = this.IsSimpleExpression(trg); trg.AcceptVisitor(this.Emitter); } } else { this.Write("this"); } } else if (this.Method.IsExtensionMethod && key == this.Method.Parameters.First().Name) { if (this.TargetResolveResult is TypeResolveResult) { isSimple = true; this.WriteParamName(key); } else if (argsInfo.Expression is MemberReferenceExpression) { var trg = ((MemberReferenceExpression)argsInfo.Expression).Target; if (trg is BaseReferenceExpression) { isSimple = true; this.Write("this"); } else { isSimple = this.IsSimpleExpression(trg); trg.AcceptVisitor(this.Emitter); } } else { isSimple = true; this.WriteParamName(key); } } else if (paramsName == key && !ignoreArray) { isSimple = true; this.Write(JS.Types.ARRAY + "." + JS.Fields.PROTOTYPE + "." + JS.Funcs.SLICE); this.WriteCall("(" + JS.Vars.ARGUMENTS + ", " + paramsIndex + ")"); } else { isSimple = true; this.WriteParamName(key); } if (modifier == "type") { this.Write(")"); } } else if (key == "this" || key == argsInfo.ThisName || (key == "0" && argsInfo.IsExtensionMethod)) { if (modifier == "type") { AstNode node = null; if (argsInfo.ThisArgument is AstNode) { node = (AstNode)argsInfo.ThisArgument; } else { node = argsInfo.Expression; } if (node != null) { var rr = this.Emitter.Resolver.ResolveNode(node, this.Emitter); var type = rr.Type; var mrr = rr as MemberResolveResult; if (mrr != null && mrr.Member.ReturnType.Kind != TypeKind.Enum && mrr.TargetResult != null) { type = mrr.TargetResult.Type; } bool needName = this.NeedName(type); if (needName) { isSimple = true; this.Write(BridgeTypes.ToJsName(type, this.Emitter)); } else { string thisValue = argsInfo.GetThisValue(); if (thisValue != null) { if (type.Kind == TypeKind.TypeParameter && !Helpers.IsIgnoreGeneric(((ITypeParameter)type).Owner, this.Emitter)) { thisValue = thisValue + ", " + type.Name; } this.Write(JS.Funcs.BRIDGE_GET_TYPE + "(" + thisValue + ")"); } } } } else { string thisValue = argsInfo.GetThisValue(); if (thisValue != null) { isSimple = true; this.Write(thisValue); } } } else { IList <Expression> exprs = this.GetExpressionsByKey(expressions, key); if (exprs.Count > 0) { if (modifier == "type") { IType type = null; if (paramsName == key && paramsType != null) { type = paramsType; } else { var rr = this.Emitter.Resolver.ResolveNode(exprs[0], this.Emitter); type = rr.Type; } bool needName = this.NeedName(type); this.WriteGetType(needName, type, exprs[0], modifier); isSimple = true; } else if (modifier == "tmp") { var tmpVarName = this.GetTempVarName(); var nameExpr = exprs[0] as PrimitiveExpression; if (nameExpr == null) { throw new EmitterException(exprs[0], "Primitive expression is required"); } Emitter.NamedTempVariables[nameExpr.LiteralValue] = tmpVarName; Write(tmpVarName); isSimple = true; } else if (modifier == "version") { var versionTypeExp = exprs != null && exprs.Any() ? exprs[0] : null; var versionType = 0; if (versionTypeExp != null) { var versionTypePrimitiveExp = versionTypeExp as PrimitiveExpression; if (versionTypePrimitiveExp != null && versionTypePrimitiveExp.Value is int) { versionType = (int)versionTypePrimitiveExp.Value; } else { var rr = this.Emitter.Resolver.ResolveNode(versionTypeExp, this.Emitter); if (rr != null && rr.ConstantValue != null && rr.ConstantValue is int) { versionType = (int)rr.ConstantValue; } } } string version; if (versionType == 0) { version = this.Emitter.Translator.GetVersionContext().Assembly.Version; } else { version = this.Emitter.Translator.GetVersionContext().Compiler.Version; } Write("\"", version, "\""); isSimple = true; } else if (modifier == "gettmp") { var nameExpr = exprs[0] as PrimitiveExpression; if (nameExpr == null) { throw new EmitterException(exprs[0], "Primitive expression is required"); } if (!Emitter.NamedTempVariables.ContainsKey(nameExpr.LiteralValue)) { throw new EmitterException(exprs[0], "Primitive expression is required"); } var tmpVarName = Emitter.NamedTempVariables[nameExpr.LiteralValue]; Write(tmpVarName); isSimple = true; } else if (modifier == "body") { var lambdaExpr = exprs[0] as LambdaExpression; if (lambdaExpr == null) { throw new EmitterException(exprs[0], "Lambda expression is required"); } var writer = this.SaveWriter(); this.NewWriter(); lambdaExpr.Body.AcceptVisitor(this.Emitter); var s = this.Emitter.Output.ToString(); this.RestoreWriter(writer); this.Write(this.WriteIndentToString(s)); } else if (exprs.Count > 1 || paramsName == key) { if (needExpand) { ignoreArray = true; } if (!ignoreArray) { this.Write("["); } if (exprs.Count == 1 && exprs[0] == null) { isSimple = true; this.Write("null"); } else { new ExpressionListBlock(this.Emitter, exprs, null, null, 0).Emit(); } if (!ignoreArray) { this.Write("]"); } } else { string s; if (exprs[0] != null) { var writer = this.SaveWriter(); this.NewWriter(); var directExpr = exprs[0] as DirectionExpression; if (directExpr != null) { var rr = this.Emitter.Resolver.ResolveNode(exprs[0], this.Emitter) as ByReferenceResolveResult; if (rr != null && !(rr.ElementResult is LocalResolveResult)) { this.Write(JS.Funcs.BRIDGE_REF + "("); this.Emitter.IsRefArg = true; exprs[0].AcceptVisitor(this.Emitter); this.Emitter.IsRefArg = false; if (this.Emitter.Writers.Count != count) { this.PopWriter(); count = this.Emitter.Writers.Count; } this.Write(")"); } else { exprs[0].AcceptVisitor(this.Emitter); } } else if (modifier == "plain") { var an = exprs[0] as AnonymousTypeCreateExpression; if (an == null) { this.Write(JS.Funcs.BRIDGE_TOPLAIN); this.WriteOpenParentheses(); exprs[0].AcceptVisitor(this.Emitter); this.Write(")"); } else { new AnonymousTypeCreateBlock(this.Emitter, an, true).Emit(); } } else { isSimple = this.IsSimpleExpression(exprs[0]); exprs[0].AcceptVisitor(this.Emitter); } s = this.Emitter.Output.ToString(); this.RestoreWriter(writer); if (modifier == "raw") { s = s.Trim('"'); } } else { isSimple = true; s = "null"; } this.Write(this.WriteIndentToString(s)); } } else if (this.ArgumentsInfo.Attribute != null) { var results = this.GetResolveResultByKey(key); if (results.Count > 1 || paramsName == key) { if (needExpand) { ignoreArray = true; } if (!ignoreArray) { this.Write("["); } if (exprs.Count == 1 && results[0].IsCompileTimeConstant && results[0].ConstantValue == null) { isSimple = true; this.Write("null"); } else { bool needComma = false; foreach (ResolveResult item in results) { if (needComma) { this.WriteComma(); } needComma = true; isSimple = this.IsSimpleResolveResult(item); AttributeCreateBlock.WriteResolveResult(item, this); } } if (!ignoreArray) { this.Write("]"); } } else { string s; if (results[0] != null) { var writer = this.SaveWriter(); this.NewWriter(); isSimple = this.IsSimpleResolveResult(results[0]); AttributeCreateBlock.WriteResolveResult(results[0], this); s = this.Emitter.Output.ToString(); this.RestoreWriter(writer); if (modifier == "raw") { s = s.Trim('"'); } } else { s = "null"; } this.Write(this.WriteIndentToString(s)); } } else if (this.ArgumentsInfo.StringArguments != null) { var results = this.GetStringArgumentByKey(key); if (results.Count > 1 || paramsName == key) { if (needExpand) { ignoreArray = true; } if (!ignoreArray) { this.Write("["); } bool needComma = false; foreach (string item in results) { if (needComma) { this.WriteComma(); } needComma = true; this.Write(item); } if (!ignoreArray) { this.Write("]"); } } else { string s; if (results[0] != null) { s = results[0]; if (modifier == "raw") { s = s.Trim('"'); } } else { s = "null"; } this.Write(s); } } else if (typeParams != null) { var type = this.GetAstTypeByKey(typeParams, key); if (type != null) { if (modifier == "default" || modifier == "defaultFn") { var def = Inspector.GetDefaultFieldValue(type, this.Emitter.Resolver); this.GetDefaultValue(def, modifier); } else { type.AcceptVisitor(this.Emitter); } } else { var iType = this.GetTypeByKey(typeParams, key); if (iType != null) { if (modifier == "default" || modifier == "defaultFn") { var def = Inspector.GetDefaultFieldValue(iType.IType, iType.AstType); this.GetDefaultValue(def, modifier); } else { new CastBlock(this.Emitter, iType.IType).Emit(); } } } } } if (this.Emitter.Writers.Count != count) { this.PopWriter(); } string replacement = this.Emitter.Output.ToString(); this.Emitter.Output = oldSb; if (!isSimple && keyMatches.Count(keyMatch => { string key1 = keyMatch.Groups[2].Value; string modifier1 = keyMatch.Groups[1].Success ? keyMatch.Groups[4].Value : null; return(key == key1 && modifier1 == modifier); }) > 1) { var t = this.GetTempVarName(); tempVars.Add(t, replacement); tempMap[tempKey] = t; return(t); } return(replacement); }); if (tempVars.Count > 0) { StringBuilder sb = new StringBuilder(); sb.Append("("); foreach (var tempVar in tempVars) { sb.Append(tempVar.Key); sb.Append("="); sb.Append(tempVar.Value); sb.Append(", "); } sb.Append(inline); sb.Append(")"); inline = sb.ToString(); } this.Write(inline); if (asRef) { this.Write("; }"); if (addClose) { this.Write(")"); } } }