private string CompileMethodCall(IMethod m, string[] a) { string inlineCode = _emitter.GetInline(m); var argsInfo = new ArgumentsInfo(_emitter, a); var block = new InlineArgumentsBlock(_emitter, argsInfo, inlineCode, m); var oldWriter = _block.SaveWriter(); var sb = _block.NewWriter(); block.Emit(); string result = sb.ToString(); _block.RestoreWriter(oldWriter); return(result); }
private static InlineArgumentsBlock GetInlineArgumentsBlock(ModuleLoaderType moduleType) { var emitter = EmitterHelper.GetEmitter( assemblyInfo: new AssemblyInfo() { Loader = new ModuleLoader { Type = moduleType } } ); var info = new ArgumentsInfo(emitter, new string[] { }); var block = new InlineArgumentsBlock(emitter, info, null); return(block); }
protected void VisitInvocationExpression() { InvocationExpression invocationExpression = InvocationExpression; int pos = Emitter.Output.Length; if (Emitter.IsForbiddenInvocation(invocationExpression)) { throw new EmitterException(invocationExpression, "This method cannot be invoked directly"); } var oldValue = Emitter.ReplaceAwaiterByVar; var oldAsyncExpressionHandling = Emitter.AsyncExpressionHandling; if (Emitter.IsAsync && !Emitter.AsyncExpressionHandling) { WriteAwaiters(invocationExpression); Emitter.ReplaceAwaiterByVar = true; Emitter.AsyncExpressionHandling = true; } Tuple <bool, bool, string> inlineInfo = Emitter.GetInlineCode(invocationExpression); var argsInfo = new ArgumentsInfo(Emitter, invocationExpression); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; var targetResolve = Emitter.Resolver.ResolveNode(invocationExpression); var csharpInvocation = targetResolve as CSharpInvocationResolveResult; MemberReferenceExpression targetMember = invocationExpression.Target as MemberReferenceExpression; bool isObjectLiteral = csharpInvocation != null && csharpInvocation.Member.DeclaringTypeDefinition != null?Emitter.Validator.IsObjectLiteral(csharpInvocation.Member.DeclaringTypeDefinition) : false; if (inlineInfo != null) { bool isStaticMethod = inlineInfo.Item1; bool isInlineMethod = inlineInfo.Item2; string inlineScript = inlineInfo.Item3; if (isInlineMethod) { if (invocationExpression.Arguments.Count > 0) { var code = invocationExpression.Arguments.First(); if (!(code is PrimitiveExpression inlineExpression)) { throw new EmitterException(invocationExpression, "Only primitive expression can be inlined"); } string value = inlineExpression.Value.ToString().Trim(); if (value.Length > 0) { value = InlineArgumentsBlock.ReplaceInlineArgs(this, inlineExpression.Value.ToString(), invocationExpression.Arguments.Skip(1).ToArray()); Write(value); value = value.Trim(); if (value[value.Length - 1] == ';' || value.EndsWith("*/", StringComparison.InvariantCulture) || value.StartsWith("//")) { Emitter.SkipSemiColon = true; WriteNewLine(); } } else { // Empty string, emit nothing. Emitter.SkipSemiColon = true; } Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { bool isBase = invocationExpression.Target is MemberReferenceExpression targetMemberRef && targetMemberRef.Target is BaseReferenceExpression; if (!String.IsNullOrEmpty(inlineScript) && (isBase || invocationExpression.Target is IdentifierExpression)) { argsInfo.ThisArgument = "this"; bool noThis = !Helpers.HasThis(inlineScript); if (inlineScript.StartsWith("<self>")) { noThis = false; inlineScript = inlineScript.Substring(6); } if (!noThis) { Emitter.ThisRefCounter++; } if (!isStaticMethod && noThis) { WriteThis(); WriteDot(); } new InlineArgumentsBlock(Emitter, argsInfo, inlineScript).Emit(); Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } } if (targetMember != null || isObjectLiteral) { var member = targetMember != null?Emitter.Resolver.ResolveNode(targetMember.Target) : null; if (targetResolve != null) { InvocationResolveResult invocationResult; bool isExtensionMethodInvocation = false; if (csharpInvocation != null) { if (member != null && member.Type.Kind == TypeKind.Delegate && (/*csharpInvocation.Member.Name == "Invoke" || */ csharpInvocation.Member.Name == "BeginInvoke" || csharpInvocation.Member.Name == "EndInvoke") && !csharpInvocation.IsExtensionMethodInvocation) { throw new EmitterException(invocationExpression, "Delegate's 'Invoke' methods are not supported. Please use direct delegate invoke."); } if (csharpInvocation.IsExtensionMethodInvocation) { invocationResult = csharpInvocation; isExtensionMethodInvocation = true; if (invocationResult.Member is IMethod resolvedMethod && resolvedMethod.IsExtensionMethod) { string inline = Emitter.GetInline(resolvedMethod); bool isNative = IsNativeMethod(resolvedMethod); if (string.IsNullOrWhiteSpace(inline) && isNative) { invocationResult = null; } } } else { invocationResult = null; } if (IsEmptyPartialInvoking(csharpInvocation.Member as IMethod) || IsConditionallyRemoved(invocationExpression, csharpInvocation.Member)) { Emitter.SkipSemiColon = true; Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { invocationResult = targetResolve as InvocationResolveResult; if (invocationResult != null && (IsEmptyPartialInvoking(invocationResult.Member as IMethod) || IsConditionallyRemoved(invocationExpression, invocationResult.Member))) { Emitter.SkipSemiColon = true; Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } if (invocationResult == null) { invocationResult = Emitter.Resolver.ResolveNode(invocationExpression) as InvocationResolveResult; } if (invocationResult != null) { if (invocationResult.Member is IMethod resolvedMethod && (resolvedMethod.IsExtensionMethod || isObjectLiteral)) { string inline = Emitter.GetInline(resolvedMethod); bool isNative = IsNativeMethod(resolvedMethod); if (isExtensionMethodInvocation || isObjectLiteral) { if (!string.IsNullOrWhiteSpace(inline)) { Write(""); StringBuilder savedBuilder = Emitter.Output; Emitter.Output = new StringBuilder(); WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = Emitter.Output.ToString(); Emitter.Output = savedBuilder; new InlineArgumentsBlock(Emitter, argsInfo, inline).Emit(); } else if (!isNative) { var overloads = OverloadsCollection.Create(Emitter, resolvedMethod); if (isObjectLiteral && !resolvedMethod.IsStatic && resolvedMethod.DeclaringType.Kind == TypeKind.Interface) { Write("H5.getType("); WriteThisExtension(invocationExpression.Target); Write(")."); } else { string name = H5Types.ToJsName(resolvedMethod.DeclaringType, Emitter, ignoreLiteralName: false) + "."; Write(name); } if (isObjectLiteral && !resolvedMethod.IsStatic) { Write(JS.Fields.PROTOTYPE + "." + overloads.GetOverloadName() + "." + JS.Funcs.CALL); } else { Write(overloads.GetOverloadName()); } var isIgnoreClass = resolvedMethod.DeclaringTypeDefinition != null && Emitter.Validator.IsExternalType(resolvedMethod.DeclaringTypeDefinition); int openPos = Emitter.Output.Length; WriteOpenParentheses(); Emitter.Comma = false; if (isObjectLiteral && !resolvedMethod.IsStatic) { WriteThisExtension(invocationExpression.Target); Emitter.Comma = true; } if (!isIgnoreClass && !Helpers.IsIgnoreGeneric(resolvedMethod, Emitter) && argsInfo.HasTypeArguments) { EnsureComma(false); new TypeExpressionListBlock(Emitter, argsInfo.TypeArguments).Emit(); Emitter.Comma = true; } if (!isObjectLiteral && resolvedMethod.IsStatic) { EnsureComma(false); WriteThisExtension(invocationExpression.Target); Emitter.Comma = true; } if (invocationExpression.Arguments.Count > 0) { EnsureComma(false); } new ExpressionListBlock(Emitter, argsExpressions, paramsArg, invocationExpression, openPos).Emit(); WriteCloseParentheses(); } if (!string.IsNullOrWhiteSpace(inline) || !isNative) { Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else if (isNative) { if (!string.IsNullOrWhiteSpace(inline)) { Write(""); StringBuilder savedBuilder = Emitter.Output; Emitter.Output = new StringBuilder(); WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = Emitter.Output.ToString(); Emitter.Output = savedBuilder; new InlineArgumentsBlock(Emitter, argsInfo, inline).Emit(); } else { argsExpressions.First().AcceptVisitor(Emitter); WriteDot(); string name = Emitter.GetEntityName(resolvedMethod); Write(name); int openPos = Emitter.Output.Length; WriteOpenParentheses(); new ExpressionListBlock(Emitter, argsExpressions.Skip(1), paramsArg, invocationExpression, openPos).Emit(); WriteCloseParentheses(); } Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } } } } var proto = false; if (targetMember != null && targetMember.Target is BaseReferenceExpression) { if (Emitter.Resolver.ResolveNode(targetMember) is MemberResolveResult rr) { proto = rr.IsVirtualCall; /*var method = rr.Member as IMethod; * if (method != null && method.IsVirtual) * { * proto = true; * } * else * { * var prop = rr.Member as IProperty; * * if (prop != null && prop.IsVirtual) * { * proto = true; * } * }*/ } } if (proto) { var baseType = Emitter.GetBaseMethodOwnerTypeDefinition(targetMember.MemberName, targetMember.TypeArguments.Count); bool isIgnore = Emitter.Validator.IsExternalType(baseType); bool needComma = false; var resolveResult = Emitter.Resolver.ResolveNode(targetMember); string name = null; if (Emitter.TypeInfo.GetBaseTypes(Emitter).Any()) { name = H5Types.ToJsName(Emitter.TypeInfo.GetBaseClass(Emitter), Emitter); } else { name = H5Types.ToJsName(baseType, Emitter); } string baseMethod; bool isIgnoreGeneric = false; if (resolveResult is MemberResolveResult memberResult) { baseMethod = OverloadsCollection.Create(Emitter, memberResult.Member).GetOverloadName(); isIgnoreGeneric = Helpers.IsIgnoreGeneric(memberResult.Member, Emitter); } else { baseMethod = targetMember.MemberName; baseMethod = Object.Net.Utilities.StringUtils.ToLowerCamelCase(baseMethod); } Write(name, "." + JS.Fields.PROTOTYPE + ".", baseMethod); WriteCall(); WriteOpenParentheses(); WriteThis(); Emitter.Comma = true; if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(Emitter, argsInfo.TypeArguments).Emit(); } needComma = false; foreach (var arg in argsExpressions) { if (arg == null) { continue; } EnsureComma(false); if (needComma) { WriteComma(); } needComma = true; arg.AcceptVisitor(Emitter); } Emitter.Comma = false; WriteCloseParentheses(); } else { IMethod method = null; if (Emitter.Resolver.ResolveNode(invocationExpression) is DynamicInvocationResolveResult dynamicResolveResult) { if (dynamicResolveResult.Target is MethodGroupResolveResult group && group.Methods.Count() > 1) { method = group.Methods.FirstOrDefault(m => { if (dynamicResolveResult.Arguments.Count != m.Parameters.Count) { return(false); } for (int i = 0; i < m.Parameters.Count; i++) { var argType = dynamicResolveResult.Arguments[i].Type; if (argType.Kind == TypeKind.Dynamic) { argType = Emitter.Resolver.Compilation.FindType(TypeCode.Object); } if (!m.Parameters[i].Type.Equals(argType)) { return(false); } } return(true); }); if (method == null) { throw new EmitterException(invocationExpression, Constants.Messages.Exceptions.DYNAMIC_INVOCATION_TOO_MANY_OVERLOADS); } } } else { var targetResolveResult = Emitter.Resolver.ResolveNode(invocationExpression.Target); if (targetResolveResult is MemberResolveResult invocationResolveResult) { method = invocationResolveResult.Member as IMethod; } } if (IsEmptyPartialInvoking(method) || IsConditionallyRemoved(invocationExpression, method)) { Emitter.SkipSemiColon = true; Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } bool isIgnore = method != null && method.DeclaringTypeDefinition != null && Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition); bool needExpand = false; if (method != null) { string paramsName = null; var paramsParam = method.Parameters.FirstOrDefault(p => p.IsParams); if (paramsParam != null) { paramsName = paramsParam.Name; } if (paramsName != null) { if (csharpInvocation != null && !csharpInvocation.IsExpandedForm) { needExpand = true; } } } int count = Emitter.Writers.Count; invocationExpression.Target.AcceptVisitor(Emitter); if (Emitter.Writers.Count > count) { var writer = Emitter.Writers.Pop(); if (method != null && method.IsExtensionMethod) { StringBuilder savedBuilder = Emitter.Output; Emitter.Output = new StringBuilder(); WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = Emitter.Output.ToString(); Emitter.Output = savedBuilder; } else if (writer.ThisArg != null) { argsInfo.ThisArgument = writer.ThisArg; } new InlineArgumentsBlock(Emitter, argsInfo, writer.InlineCode) { IgnoreRange = writer.IgnoreRange }.Emit(); var result = Emitter.Output.ToString(); Emitter.Output = writer.Output; Emitter.IsNewLine = writer.IsNewLine; Write(result); if (writer.Callback != null) { writer.Callback.Invoke(); } } else { if (needExpand && isIgnore) { Write("." + JS.Funcs.APPLY); } int openPos = Emitter.Output.Length; WriteOpenParentheses(); bool isIgnoreGeneric = false; if (targetResolve is InvocationResolveResult invocationResult) { isIgnoreGeneric = Helpers.IsIgnoreGeneric(invocationResult.Member, Emitter); } bool isWrapRest = false; if (needExpand && isIgnore) { StringBuilder savedBuilder = Emitter.Output; Emitter.Output = new StringBuilder(); WriteThisExtension(invocationExpression.Target); var thisArg = Emitter.Output.ToString(); Emitter.Output = savedBuilder; Write(thisArg); Emitter.Comma = true; if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(Emitter, argsInfo.TypeArguments).Emit(); } EnsureComma(false); if (argsExpressions.Length > 1) { WriteOpenBracket(); var elb = new ExpressionListBlock(Emitter, argsExpressions.Take(argsExpressions.Length - 1).ToArray(), paramsArg, invocationExpression, openPos); elb.IgnoreExpandParams = true; elb.Emit(); WriteCloseBracket(); Write(".concat("); elb = new ExpressionListBlock(Emitter, new Expression[] { argsExpressions[argsExpressions.Length - 1] }, paramsArg, invocationExpression, openPos); elb.IgnoreExpandParams = true; elb.Emit(); Write(")"); } else { new ExpressionListBlock(Emitter, argsExpressions, paramsArg, invocationExpression, -1).Emit(); } } else { if (method != null && method.Attributes.Any(a => a.AttributeType.FullName == "H5.WrapRestAttribute")) { isWrapRest = true; } Emitter.Comma = false; if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(Emitter, argsInfo.TypeArguments).Emit(); } if (invocationExpression.Arguments.Count > 0 || argsExpressions.Length > 0 && !argsExpressions.All(expr => expr == null)) { EnsureComma(false); } new ExpressionListBlock(Emitter, argsExpressions, paramsArg, invocationExpression, openPos).Emit(); } if (isWrapRest) { EnsureComma(false); Write("H5.fn.bind(this, function () "); BeginBlock(); Emitter.WrapRestCounter++; Emitter.SkipSemiColon = true; } else { Emitter.Comma = false; WriteCloseParentheses(); } } } if (targetResolve is InvocationResolveResult irr && irr.Member.MemberDefinition != null && irr.Member.MemberDefinition.ReturnType.Kind == TypeKind.TypeParameter) { Helpers.CheckValueTypeClone(Emitter.Resolver.ResolveNode(invocationExpression), invocationExpression, this, pos); } Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; }