protected virtual void EmitExpressionList(IEnumerable <AstType> types) { bool needComma = false; foreach (var type in types) { this.EnsureComma(false); this.Emitter.Translator.EmitNode = type; if (needComma) { this.WriteComma(); } needComma = true; this.Write(BridgeTypes.ToJsName(type, this.Emitter)); } if (needComma) { this.Emitter.Comma = true; } }
protected virtual void EmitExpressionList(IEnumerable <TypeParamExpression> expressions) { bool needComma = false; foreach (var expr in expressions) { if (expr.Inherited) { continue; } this.EnsureComma(false); this.Emitter.Translator.EmitNode = expr.AstType; if (needComma) { this.WriteComma(); } needComma = true; if (expr.AstType != null) { this.Write(BridgeTypes.ToJsName(expr.AstType, this.Emitter)); } else if (expr.IType != null) { this.Write(BridgeTypes.ToJsName(expr.IType, this.Emitter)); } else { throw new EmitterException(this.PreviousNode, "There is no type information"); } } if (needComma) { this.Emitter.Comma = true; } }
protected virtual void EmitCastType(AstType astType) { var resolveResult = this.Emitter.Resolver.ResolveNode(astType, this.Emitter); if (NullableType.IsNullable(resolveResult.Type)) { this.Write(BridgeTypes.ToJsName(NullableType.GetUnderlyingType(resolveResult.Type), this.Emitter)); } else if (resolveResult.Type.Kind == TypeKind.Delegate) { this.Write(JS.Types.FUNCTION); } /*else if (resolveResult.Type.Kind == TypeKind.Array) * { * this.EmitArray(resolveResult.Type); * }*/ else { astType.AcceptVisitor(this.Emitter); } }
public virtual string GetTypeHierarchy() { StringBuilder sb = new StringBuilder(); sb.Append("{ "); var list = new List <string>(); foreach (var t in this.TypeInfo.GetBaseTypes(this)) { var name = BridgeTypes.ToJsName(t, this, BridgeTypes.ToNameTypeEnum.Extend); list.Add(name); } if (list.Count > 0 && list[0] == "Object") { list.RemoveAt(0); } if (list.Count == 0) { return(""); } bool needComma = false; foreach (var item in list) { if (needComma) { sb.Append(", "); } needComma = true; sb.Append(item); } sb.Append(" }"); return(sb.ToString()); }
protected void WriteTarget(MemberResolveResult memberResult) { if (memberResult.Member.IsStatic) { this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); /*if (!this.Emitter.Validator.IsIgnoreType(memberResult.Member.DeclaringTypeDefinition) && memberResult.Member.DeclaringTypeDefinition.Kind != TypeKind.Enum) * { * this.Write("Bridge.get(" + BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter) + ")"); * } * else * { * this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); * }*/ } else { this.WriteThis(); } this.WriteDot(); }
protected virtual void EmitNamedFunctions() { if (this.Emitter.NamedFunctions.Count > 0) { this.Emitter.Comma = false; this.IntroducePrivateVar(); var name = BridgeTypes.ToJsName(this.Emitter.TypeInfo.Type, this.Emitter, true); this.WriteNewLine(); this.WriteNewLine(); this.Write(JS.Funcs.BRIDGE_NS); this.WriteOpenParentheses(); this.WriteScript(name); this.Write(", " + JS.Vars.D_ + ")"); this.WriteSemiColon(); this.WriteNewLine(); this.WriteNewLine(); this.Write(JS.Funcs.BRIDGE_APPLY + "(" + JS.Vars.D_ + "."); this.Write(name); this.Write(", "); this.BeginBlock(); foreach (KeyValuePair <string, string> namedFunction in this.Emitter.NamedFunctions) { this.EnsureComma(); this.Write(namedFunction.Key + ": " + namedFunction.Value); this.Emitter.Comma = true; } this.WriteNewLine(); this.EndBlock(); this.WriteCloseParentheses(); this.WriteSemiColon(); } }
private string GetTypeHierarchy() { StringBuilder sb = new StringBuilder(); var list = new List <string>(); foreach (var t in this.TypeInfo.TypeDeclaration.BaseTypes) { var name = BridgeTypes.ToJsName(t, this.Emitter); list.Add(name); } if (list.Count > 0 && list[0] == "Object") { list.RemoveAt(0); } if (list.Count == 0) { return(""); } bool needComma = false; foreach (var item in list) { if (needComma) { sb.Append(","); } needComma = true; sb.Append(item); } return(Bridge.Translator.TypeScript.EmitBlock.HandleType(sb.ToString())); }
protected virtual void EmitCastType(IType iType) { if (NullableType.IsNullable(iType)) { this.Write(BridgeTypes.ToJsName(NullableType.GetUnderlyingType(iType), this.Emitter)); } else if (iType.Kind == TypeKind.Delegate) { this.Write("Function"); } else if (iType.Kind == TypeKind.Array) { this.Write("Array"); } else if (iType.Kind == TypeKind.Anonymous) { this.Write("Object"); } else { this.Write(BridgeTypes.ToJsName(iType, this.Emitter)); } }
protected virtual void EmitCastType(IType iType) { if (NullableType.IsNullable(iType)) { this.Write(BridgeTypes.ToJsName(NullableType.GetUnderlyingType(iType), this.Emitter)); } else if (iType.Kind == TypeKind.Delegate) { this.Write(JS.Types.FUNCTION); } else if (iType.Kind == TypeKind.Array) { this.EmitArray(iType); } else if (iType.Kind == TypeKind.Anonymous) { this.Write(JS.Types.Object.NAME); } else { this.Write(BridgeTypes.ToJsName(iType, this.Emitter)); } }
protected void WriteSimpleTarget(ResolveResult resolveResult) { MemberResolveResult member = resolveResult as MemberResolveResult; if (member == null || !member.Member.IsStatic) { this.MemberReferenceExpression.Target.AcceptVisitor(this.Emitter); return; } var imethod = member.Member as IMethod; var imember = member.Member; if ((imethod != null && imethod.IsExtensionMethod) || imember == null) { this.MemberReferenceExpression.Target.AcceptVisitor(this.Emitter); return; } var target = BridgeTypes.ToJsName(member.Member.DeclaringType, this.Emitter); this.NoTarget = string.IsNullOrWhiteSpace(target); this.Write(target); }
protected override void EmitConversionExpression() { var proto = false; if (this.BaseReferenceExpression.Parent != null) { var rr = this.Emitter.Resolver.ResolveNode(this.BaseReferenceExpression.Parent, this.Emitter) as MemberResolveResult; if (rr != null) { 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 = this.Emitter.GetBaseTypeDefinition(); this.Write(BridgeTypes.ToJsName(baseType, this.Emitter), ".prototype"); } else { this.WriteThis(); } }
protected void WriteTarget(MemberResolveResult memberResult) { bool noTarget = false; if (memberResult.Member.IsStatic) { var target = BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter); noTarget = string.IsNullOrWhiteSpace(target); this.Write(target); } else { this.WriteThis(); } if (this.isRefArg) { this.WriteComma(); } else if (!noTarget) { this.WriteDot(); } }
protected virtual void EmitMethodParameters(IEnumerable <ParameterDeclaration> declarations, AstNode context) { this.WriteOpenParentheses(); bool needComma = false; foreach (var p in declarations) { var name = this.Emitter.GetEntityName(p); if (needComma) { this.WriteComma(); } needComma = true; this.Write(name); this.WriteColon(); name = BridgeTypes.ToJsName(p.Type, this.Emitter); name = EmitBlock.HandleType(name); this.Write(name); } this.WriteCloseParentheses(); }
internal static string GetTypeName(IType type, IEmitter emitter, bool isGenericSpecialization, bool asDefinition = false) { var typeParam = type as ITypeParameter; if (typeParam != null && (typeParam.OwnerType == SymbolKind.Method || Helpers.IsIgnoreGeneric(typeParam.Owner, emitter))) { return(JS.Types.System.Object.NAME); } var itypeDef = type.GetDefinition(); if (itypeDef != null && itypeDef.Attributes.Any(a => a.AttributeType.FullName == "Bridge.NonScriptableAttribute")) { return(JS.Types.System.Object.NAME); } var name = BridgeTypes.ToJsName(type, emitter, asDefinition, skipMethodTypeParam: true); if (emitter.NamespacesCache != null && name.StartsWith(type.Namespace + ".")) { int key; if (emitter.NamespacesCache.ContainsKey(type.Namespace)) { key = emitter.NamespacesCache[type.Namespace]; } else { key = emitter.NamespacesCache.Count; emitter.NamespacesCache.Add(type.Namespace, key); } name = string.Concat("$n[", key, "]", name.Substring(type.Namespace.Length)); } return(name); }
protected void VisitInvocationExpression() { InvocationExpression invocationExpression = this.InvocationExpression; int pos = this.Emitter.Output.Length; if (this.Emitter.IsForbiddenInvocation(invocationExpression)) { throw new EmitterException(invocationExpression, "This method cannot be invoked directly"); } var oldValue = this.Emitter.ReplaceAwaiterByVar; var oldAsyncExpressionHandling = this.Emitter.AsyncExpressionHandling; if (this.Emitter.IsAsync && !this.Emitter.AsyncExpressionHandling) { this.WriteAwaiters(invocationExpression); this.Emitter.ReplaceAwaiterByVar = true; this.Emitter.AsyncExpressionHandling = true; } Tuple <bool, bool, string> inlineInfo = this.Emitter.GetInlineCode(invocationExpression); var argsInfo = new ArgumentsInfo(this.Emitter, invocationExpression); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; var targetResolve = this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter); var csharpInvocation = targetResolve as CSharpInvocationResolveResult; MemberReferenceExpression targetMember = invocationExpression.Target as MemberReferenceExpression; bool isObjectLiteral = csharpInvocation != null && csharpInvocation.Member.DeclaringTypeDefinition != null?this.Emitter.Validator.IsObjectLiteral(csharpInvocation.Member.DeclaringTypeDefinition) : false; var interceptor = this.Emitter.Plugins.OnInvocation(this, this.InvocationExpression, targetResolve as InvocationResolveResult); if (interceptor.Cancel) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } if (!string.IsNullOrEmpty(interceptor.Replacement)) { this.Write(interceptor.Replacement); this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } 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(); var inlineExpression = code as PrimitiveExpression; if (inlineExpression == null) { 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()); this.Write(value); value = value.Trim(); if (value[value.Length - 1] == ';' || value.EndsWith("*/", StringComparison.InvariantCulture) || value.StartsWith("//")) { this.Emitter.EnableSemicolon = false; this.WriteNewLine(); } } else { // Empty string, emit nothing. this.Emitter.EnableSemicolon = false; } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { MemberReferenceExpression targetMemberRef = invocationExpression.Target as MemberReferenceExpression; bool isBase = targetMemberRef != null && targetMemberRef.Target is BaseReferenceExpression; if (!String.IsNullOrEmpty(inlineScript) && (isBase || invocationExpression.Target is IdentifierExpression)) { argsInfo.ThisArgument = "this"; bool noThis = !inlineScript.Contains("{this}"); if (inlineScript.StartsWith("<self>")) { noThis = false; inlineScript = inlineScript.Substring(6); } if (!isStaticMethod && noThis) { this.WriteThis(); this.WriteDot(); } new InlineArgumentsBlock(this.Emitter, argsInfo, inlineScript).Emit(); this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } } if (targetMember != null || isObjectLiteral) { var member = targetMember != null?this.Emitter.Resolver.ResolveNode(targetMember.Target, this.Emitter) : 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; var resolvedMethod = invocationResult.Member as IMethod; if (resolvedMethod != null && resolvedMethod.IsExtensionMethod) { string inline = this.Emitter.GetInline(resolvedMethod); bool isNative = this.IsNativeMethod(resolvedMethod); if (string.IsNullOrWhiteSpace(inline) && isNative) { invocationResult = null; } } } else { invocationResult = null; } if (this.IsEmptyPartialInvoking(csharpInvocation.Member as IMethod) || IsConditionallyRemoved(invocationExpression, csharpInvocation.Member)) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { invocationResult = targetResolve as InvocationResolveResult; if (invocationResult != null && (this.IsEmptyPartialInvoking(invocationResult.Member as IMethod) || IsConditionallyRemoved(invocationExpression, invocationResult.Member))) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } if (invocationResult == null) { invocationResult = this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter) as InvocationResolveResult; } if (invocationResult != null) { var resolvedMethod = invocationResult.Member as IMethod; if (resolvedMethod != null && (resolvedMethod.IsExtensionMethod || isObjectLiteral)) { string inline = this.Emitter.GetInline(resolvedMethod); bool isNative = this.IsNativeMethod(resolvedMethod); if (isExtensionMethodInvocation || isObjectLiteral) { if (!string.IsNullOrWhiteSpace(inline)) { this.Write(""); StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; new InlineArgumentsBlock(this.Emitter, argsInfo, inline).Emit(); } else if (!isNative) { var overloads = OverloadsCollection.Create(this.Emitter, resolvedMethod); string name = BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter) + "."; if (isObjectLiteral && !resolvedMethod.IsStatic) { name += JS.Fields.PROTOTYPE + "." + overloads.GetOverloadName() + "."; name += JS.Funcs.CALL; } else { name += overloads.GetOverloadName(); } var isIgnoreClass = resolvedMethod.DeclaringTypeDefinition != null && this.Emitter.Validator.IsIgnoreType(resolvedMethod.DeclaringTypeDefinition); this.Write(name); int openPos = this.Emitter.Output.Length; this.WriteOpenParentheses(); this.Emitter.Comma = false; if (!isIgnoreClass && !Helpers.IsIgnoreGeneric(resolvedMethod, this.Emitter) && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); } this.EnsureComma(false); if (!isObjectLiteral || !resolvedMethod.IsStatic) { this.WriteThisExtension(invocationExpression.Target); if (invocationExpression.Arguments.Count > 0) { this.WriteComma(); } } new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, invocationExpression, openPos).Emit(); this.WriteCloseParentheses(); } if (!string.IsNullOrWhiteSpace(inline) || !isNative) { this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else if (isNative) { if (!string.IsNullOrWhiteSpace(inline)) { this.Write(""); StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; new InlineArgumentsBlock(this.Emitter, argsInfo, inline).Emit(); } else { argsExpressions.First().AcceptVisitor(this.Emitter); this.WriteDot(); string name = this.Emitter.GetEntityName(resolvedMethod); this.Write(name); int openPos = this.Emitter.Output.Length; this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions.Skip(1), paramsArg, invocationExpression, openPos).Emit(); this.WriteCloseParentheses(); } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } } } } var proto = false; if (targetMember != null && targetMember.Target is BaseReferenceExpression) { var rr = this.Emitter.Resolver.ResolveNode(targetMember, this.Emitter) as MemberResolveResult; if (rr != null) { 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 = this.Emitter.GetBaseMethodOwnerTypeDefinition(targetMember.MemberName, targetMember.TypeArguments.Count); bool isIgnore = this.Emitter.Validator.IsIgnoreType(baseType); if (isIgnore) { //throw (System.Exception)this.Emitter.CreateException(targetMember.Target, "Cannot call base method, because parent class code is ignored"); } bool needComma = false; var resolveResult = this.Emitter.Resolver.ResolveNode(targetMember, this.Emitter); string name = null; if (this.Emitter.TypeInfo.GetBaseTypes(this.Emitter).Any()) { name = BridgeTypes.ToJsName(this.Emitter.TypeInfo.GetBaseClass(this.Emitter), this.Emitter); } else { name = BridgeTypes.ToJsName(baseType, this.Emitter); } string baseMethod; bool isIgnoreGeneric = false; if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; baseMethod = OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName(); isIgnoreGeneric = Helpers.IsIgnoreGeneric(invocationResult.Member, this.Emitter); } else if (resolveResult is MemberResolveResult) { MemberResolveResult memberResult = (MemberResolveResult)resolveResult; baseMethod = OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName(); isIgnoreGeneric = Helpers.IsIgnoreGeneric(memberResult.Member, this.Emitter); } else { baseMethod = targetMember.MemberName; baseMethod = this.Emitter.AssemblyInfo.PreserveMemberCase ? baseMethod : Object.Net.Utilities.StringUtils.ToLowerCamelCase(baseMethod); } this.Write(name, "." + JS.Fields.PROTOTYPE + ".", baseMethod); this.WriteCall(); this.WriteOpenParentheses(); this.WriteThis(); this.Emitter.Comma = true; if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); } needComma = false; foreach (var arg in argsExpressions) { if (arg == null) { continue; } this.EnsureComma(false); if (needComma) { this.WriteComma(); } needComma = true; arg.AcceptVisitor(this.Emitter); } this.Emitter.Comma = false; this.WriteCloseParentheses(); } else { var dynamicResolveResult = this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter) as DynamicInvocationResolveResult; if (dynamicResolveResult != null) { var group = dynamicResolveResult.Target as MethodGroupResolveResult; if (group != null && group.Methods.Count() > 1) { throw new EmitterException(invocationExpression, "Cannot compile this dynamic invocation because there are two or more method overloads with the same parameter count. To work around this limitation, assign the dynamic value to a non-dynamic variable before use or call a method with different parameter count"); } } var targetResolveResult = this.Emitter.Resolver.ResolveNode(invocationExpression.Target, this.Emitter); var invocationResolveResult = targetResolveResult as MemberResolveResult; IMethod method = null; if (invocationResolveResult != null) { method = invocationResolveResult.Member as IMethod; } if (this.IsEmptyPartialInvoking(method) || IsConditionallyRemoved(invocationExpression, method)) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } bool isIgnore = method != null && method.DeclaringTypeDefinition != null && this.Emitter.Validator.IsIgnoreType(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 = this.Emitter.Writers.Count; invocationExpression.Target.AcceptVisitor(this.Emitter); if (this.Emitter.Writers.Count > count) { var writer = this.Emitter.Writers.Pop(); if (method != null && method.IsExtensionMethod) { StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; } else if (writer.ThisArg != null) { argsInfo.ThisArgument = writer.ThisArg; } new InlineArgumentsBlock(this.Emitter, argsInfo, writer.InlineCode) { IgnoreRange = writer.IgnoreRange }.Emit(); var result = this.Emitter.Output.ToString(); this.Emitter.Output = writer.Output; this.Emitter.IsNewLine = writer.IsNewLine; this.Write(result); if (writer.Callback != null) { writer.Callback.Invoke(); } } else { if (needExpand && isIgnore) { this.Write("." + JS.Funcs.APPLY); } int openPos = this.Emitter.Output.Length; this.WriteOpenParentheses(); bool isIgnoreGeneric = false; var invocationResult = targetResolve as InvocationResolveResult; if (invocationResult != null) { isIgnoreGeneric = Helpers.IsIgnoreGeneric(invocationResult.Member, this.Emitter); } if (needExpand && isIgnore) { StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); var thisArg = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; this.Write(thisArg); this.Emitter.Comma = true; if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); } this.EnsureComma(false); if (argsExpressions.Length > 1) { this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions.Take(argsExpressions.Length - 1).ToArray(), paramsArg, invocationExpression, openPos).Emit(); this.WriteCloseBracket(); this.Write(".concat("); new ExpressionListBlock(this.Emitter, new Expression[] { argsExpressions[argsExpressions.Length - 1] }, paramsArg, invocationExpression, openPos).Emit(); this.Write(")"); } else { new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, invocationExpression, -1).Emit(); } } else { this.Emitter.Comma = false; if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); } if (invocationExpression.Arguments.Count > 0) { this.EnsureComma(false); } new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, invocationExpression, openPos).Emit(); } this.WriteCloseParentheses(); } } Helpers.CheckValueTypeClone(this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter), invocationExpression, this, pos); this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var itype = this.Emitter.BridgeTypes.ToType(type); bool isCastAttr; string castCode = this.GetCastCode(expression, type, out isCastAttr); if (itype != null && castCode == null && method != CS.Ops.CAST && itype.GetDefinition() != null && this.Emitter.Validator.IsObjectLiteral(itype.GetDefinition())) { throw new EmitterException(expression, "The type " + itype.FullName + " cannot be used in cast operation because there is no way to check its type"); } var enumType = itype; if (NullableType.IsNullable(enumType)) { enumType = NullableType.GetUnderlyingType(enumType); } var castToEnum = enumType.Kind == TypeKind.Enum; if (castToEnum) { itype = enumType.GetDefinition().EnumUnderlyingType; var enumMode = this.Emitter.Validator.EnumEmitMode(enumType); if (enumMode >= 3 && enumMode < 7) { itype = this.Emitter.Resolver.Compilation.FindType(KnownTypeCode.String); } } if (expression is NullReferenceExpression || (method != CS.Ops.IS && Helpers.IsIgnoreCast(type, this.Emitter))) { if (expression is ParenthesizedExpression) { expression = ((ParenthesizedExpression)expression).Expression; } expression.AcceptVisitor(this.Emitter); return; } if (method == CS.Ops.CAST) { var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter); if (cast_rr is ConstantResolveResult) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)cast_rr).ConstantValue; this.WriteCastValue(value, expectedType); return; } else { var conv_rr = cast_rr as ConversionResolveResult; if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)conv_rr.Input).ConstantValue; this.WriteCastValue(value, expectedType); return; } } } if (method == CS.Ops.IS && castToEnum) { this.Write("Bridge.is("); expression.AcceptVisitor(this.Emitter); this.Write(", "); this.Write(BridgeTypes.ToJsName(itype, this.Emitter)); this.Write(")"); return; } var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); var typerr = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (expressionrr.Type.Equals(itype)) { if (method == CS.Ops.IS) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); } expression.AcceptVisitor(this.Emitter); if (method == CS.Ops.IS) { this.Write(")"); } return; } bool isResultNullable = NullableType.IsNullable(typerr.Type); if (castCode != null) { this.EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method); return; } bool isCast = method == CS.Ops.CAST; if (isCast) { if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression)) { expression.AcceptVisitor(this.Emitter); return; } } var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion)) { expression.AcceptVisitor(this.Emitter); return; } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == CS.Ops.CAST || method == CS.Ops.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == CS.Ops.IS) { hasValue = true; method = "hasValue"; } } bool unbox = !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion; if (unbox) { this.Write("System.Nullable.getValue("); } this.Write(JS.NS.BRIDGE); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); if (!hasValue) { this.WriteComma(); this.EmitCastType(itype); } if (isResultNullable && method != CS.Ops.IS) { this.WriteComma(); this.WriteScript(true); } this.WriteCloseParentheses(); if (unbox) { this.Write(")"); } }
protected virtual void EmitLambda(IEnumerable <ParameterDeclaration> parameters, AstNode body, AstNode context) { var analyzer = new CaptureAnalyzer(this.Emitter.Resolver.Resolver); analyzer.Analyze(this.Body, this.Parameters.Select(p => p.Name)); var oldLevel = this.Emitter.Level; if (analyzer.UsedVariables.Count == 0) { this.Emitter.Level = 1; } AsyncBlock asyncBlock = null; this.PushLocals(); if (this.IsAsync) { if (context is LambdaExpression) { asyncBlock = new AsyncBlock(this.Emitter, (LambdaExpression)context); } else { asyncBlock = new AsyncBlock(this.Emitter, (AnonymousMethodExpression)context); } asyncBlock.InitAsyncBlock(); } var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(parameters, body); bool block = body is BlockStatement; this.Write(""); var savedPos = this.Emitter.Output.Length; var savedThisCount = this.Emitter.ThisRefCounter; this.WriteFunction(); this.EmitMethodParameters(parameters, null, context); this.WriteSpace(); int pos = 0; if (!block && !this.IsAsync) { this.BeginBlock(); pos = this.Emitter.Output.Length; } bool isSimpleLambda = body.Parent is LambdaExpression && !block && !this.IsAsync; if (isSimpleLambda) { this.ConvertParamsToReferences(parameters); var rr = this.Emitter.Resolver.ResolveNode(this.Context, this.Emitter) as LambdaResolveResult; if (rr == null || rr.ReturnType.Kind != TypeKind.Void) { this.WriteReturn(true); } } if (this.IsAsync) { asyncBlock.Emit(true); } else { body.AcceptVisitor(this.Emitter); } if (isSimpleLambda) { this.WriteSemiColon(); } if (!block && !this.IsAsync) { this.WriteNewLine(); this.EndBlock(); } if (!block && !this.IsAsync) { this.EmitTempVars(pos); } if (analyzer.UsedVariables.Count == 0) { var name = "f" + (this.Emitter.NamedFunctions.Count + 1); var code = this.Emitter.Output.ToString().Substring(savedPos); var pair = this.Emitter.NamedFunctions.FirstOrDefault(p => p.Value == code); if (pair.Key != null && pair.Value != null) { name = pair.Key; } else { this.Emitter.NamedFunctions.Add(name, code); } this.Emitter.Output.Remove(savedPos, this.Emitter.Output.Length - savedPos); this.Emitter.Output.Insert(savedPos, "$_." + BridgeTypes.ToJsName(this.Emitter.TypeInfo.Type, this.Emitter, true) + "." + name); this.Emitter.Level = oldLevel; } if (this.Emitter.ThisRefCounter > savedThisCount) { this.Emitter.Output.Insert(savedPos, Bridge.Translator.Emitter.ROOT + "." + Bridge.Translator.Emitter.DELEGATE_BIND + "(this, "); this.WriteCloseParentheses(); } this.PopLocals(); this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); }
protected void VisitArrayCreateExpression() { ArrayCreateExpression arrayCreateExpression = this.ArrayCreateExpression; var rr = this.Emitter.Resolver.ResolveNode(arrayCreateExpression, this.Emitter) as ArrayCreateResolveResult; var at = (ArrayType)rr.Type; var rank = arrayCreateExpression.Arguments.Count; if (arrayCreateExpression.Initializer.IsNull && rank == 1) { string typedArrayName = null; if (this.Emitter.AssemblyInfo.UseTypedArrays && (typedArrayName = Helpers.GetTypedArrayName(at.ElementType)) != null) { this.Write("new ", typedArrayName, "("); arrayCreateExpression.Arguments.First().AcceptVisitor(this.Emitter); this.Write(")"); } else { string typeName = BridgeTypes.ToJsName(at, this.Emitter); this.Write(typeName); this.WriteOpenParentheses(); arrayCreateExpression.Arguments.First().AcceptVisitor(this.Emitter); this.WriteCloseParentheses(); /* * this.Write("Bridge.Array.init("); * arrayCreateExpression.Arguments.First().AcceptVisitor(this.Emitter); * this.WriteComma(); * * var def = Inspector.GetDefaultFieldValue(at.ElementType); * if (def == at.ElementType) * { * this.WriteFunction(); * this.WriteOpenCloseParentheses(); * this.BeginBlock(); * this.WriteReturn(true); * this.Write(Inspector.GetStructDefaultValue(at.ElementType, this.Emitter)); * this.WriteSemiColon(); * this.WriteNewLine(); * this.EndBlock(); * } * else * { * this.WriteScript(def); * } * * this.Write(")");*/ } return; } /* * if (at.Dimensions > 1) * { * this.Write("Bridge.Array.create("); * var defaultInitializer = new PrimitiveExpression(Inspector.GetDefaultFieldValue(at.ElementType), "?"); * * if (defaultInitializer.Value is IType) * { * this.Write(Inspector.GetStructDefaultValue((IType)defaultInitializer.Value, this.Emitter)); * } * else * { * defaultInitializer.AcceptVisitor(this.Emitter); * } * * this.WriteComma(); * }*/ if (rr.InitializerElements != null && rr.InitializerElements.Count > 0) { if (at.Dimensions > 1) { string typeName = BridgeTypes.ToJsName(((ArrayType)rr.Type).ElementType, this.Emitter); this.Write("System.MultiArray"); this.WriteOpenParentheses(); this.Write(typeName); this.WriteCloseParentheses(); this.WriteOpenParentheses(); this.Emitter.Comma = true; this.WriteOpenBrace(); for (int i = 0; i < rr.SizeArguments.Count; i++) { var a = rr.SizeArguments[i]; if (a.IsCompileTimeConstant) { this.Write(a.ConstantValue); } else if (arrayCreateExpression.Arguments.Count > i) { var arg = arrayCreateExpression.Arguments.ElementAt(i); if (arg != null) { arg.AcceptVisitor(this.Emitter); } } if (i != rr.SizeArguments.Count - 1) { this.EnsureComma(false); } this.Emitter.Comma = true; } this.WriteCloseBrace(); this.Emitter.Comma = false; this.WriteComma(); var elements = arrayCreateExpression.Initializer.Elements; new ExpressionListBlock(this.Emitter, elements, null).Emit(); this.WriteCloseParentheses(); } else { string typeName = BridgeTypes.ToJsName(((ArrayType)rr.Type).ElementType, this.Emitter); this.Write("System.Array"); this.WriteOpenParentheses(); this.Write(typeName); this.WriteCloseParentheses(); this.WriteOpenParentheses(); this.Write(rr.InitializerElements.Count); this.WriteComma(); var elements = arrayCreateExpression.Initializer.Elements; new ExpressionListBlock(this.Emitter, elements, null).Emit(); this.WriteCloseParentheses(); } } else if (at.Dimensions > 1) { this.Write("null"); } else { this.Write("[]"); } /* * if (at.Dimensions > 1) * { * this.Emitter.Comma = true; * * for (int i = 0; i < rr.SizeArguments.Count; i++) * { * var a = rr.SizeArguments[i]; * this.EnsureComma(false); * * if (a.IsCompileTimeConstant) * { * this.Write(a.ConstantValue); * } * else if (arrayCreateExpression.Arguments.Count > i) * { * var arg = arrayCreateExpression.Arguments.ElementAt(i); * * if (arg != null) * { * arg.AcceptVisitor(this.Emitter); * } * } * this.Emitter.Comma = true; * } * * this.Write(")"); * this.Emitter.Comma = false; * } */ }
protected void VisitIdentifierExpression() { IdentifierExpression identifierExpression = this.IdentifierExpression; ResolveResult resolveResult = null; ResolveResult expressionResolveResult = null; /*if (identifierExpression.Parent is InvocationExpression && (((InvocationExpression)(identifierExpression.Parent)).Target == identifierExpression)) * { * resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression.Parent, this.Emitter); * expressionResolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter); * } * else * { * resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter); * }*/ resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter); var id = identifierExpression.Identifier; var isResolved = resolveResult != null && !(resolveResult is ErrorResolveResult); var memberResult = resolveResult as MemberResolveResult; if (this.Emitter.Locals != null && this.Emitter.Locals.ContainsKey(id)) { if (this.Emitter.LocalsMap != null && this.Emitter.LocalsMap.ContainsKey(id) && !(identifierExpression.Parent is DirectionExpression)) { this.Write(this.Emitter.LocalsMap[id]); } else if (this.Emitter.LocalsNamesMap != null && this.Emitter.LocalsNamesMap.ContainsKey(id)) { this.Write(this.Emitter.LocalsNamesMap[id]); } else { this.Write(id); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this); return; } IMemberDefinition member = this.ResolveFieldOrMethod(id, identifierExpression.TypeArguments.Count); if (member == null && memberResult != null) { var iMethod = memberResult.Member as IMethod; if (iMethod != null) { member = this.ResolveFieldOrMethod(id, iMethod.TypeParameters.Count); } } if (member != null) { MethodDefinition method = member as MethodDefinition; FieldDefinition field = member as FieldDefinition; bool isStatic = method != null && method.IsStatic || field != null && field.IsStatic; string appendAdditionalCode = null; if (method != null) { string inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { return; } if (memberResult != null && memberResult.Member is IMethod && !(memberResult is InvocationResolveResult) && !( identifierExpression.Parent is InvocationExpression && identifierExpression.NextSibling != null && identifierExpression.NextSibling.Role is TokenRole && ((TokenRole)identifierExpression.NextSibling.Role).Token == "(" ) ) { var resolvedMethod = (IMethod)memberResult.Member; if (!isStatic) { var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Write(Bridge.Translator.Emitter.ROOT + "." + (isExtensionMethod ? Bridge.Translator.Emitter.DELEGATE_BIND_SCOPE : Bridge.Translator.Emitter.DELEGATE_BIND) + "("); this.WriteThis(); this.Write(", "); appendAdditionalCode = ")"; } } } bool isConst = false; bool isInlineConst = false; if (memberResult != null) { isConst = this.Emitter.IsMemberConst(memberResult.Member); if (isConst) { isInlineConst = this.Emitter.IsInlineConst(memberResult.Member); } } if (!(resolveResult is TypeResolveResult) && !isInlineConst) { if (isStatic) { if (memberResult != null) { this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); } else { this.Write(BridgeTypes.ToJsName(member.DeclaringType, this.Emitter)); } } else { this.WriteThis(); } this.WriteDot(); } if (method != null) { if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; CSharpInvocationResolveResult cInvocationResult = (CSharpInvocationResolveResult)resolveResult; var expresssionMember = expressionResolveResult as MemberResolveResult; if (expresssionMember != null && cInvocationResult != null && cInvocationResult.IsDelegateInvocation && invocationResult.Member != expresssionMember.Member) { this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName()); } else { this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName()); } } else if (resolveResult is MemberResolveResult) { MemberResolveResult memberResolveResult = (MemberResolveResult)resolveResult; this.Write(OverloadsCollection.Create(this.Emitter, memberResolveResult.Member).GetOverloadName()); } else { this.Write(this.Emitter.GetDefinitionName(method)); } if (appendAdditionalCode != null) { this.Write(appendAdditionalCode); } } else if (memberResult != null) { if (isInlineConst) { this.WriteScript(memberResult.ConstantValue); } else if (memberResult != null && memberResult.Member is DefaultResolvedEvent && this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove"); this.Write(OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName()); this.WriteOpenParentheses(); } else { if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; CSharpInvocationResolveResult cInvocationResult = (CSharpInvocationResolveResult)resolveResult; var expresssionMember = expressionResolveResult as MemberResolveResult; if (expresssionMember != null && cInvocationResult != null && cInvocationResult.IsDelegateInvocation && invocationResult.Member != expresssionMember.Member) { this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName()); } else { this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName()); } } else { this.Write(OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName()); } } } else if (resolveResult is TypeResolveResult) { this.Write(BridgeTypes.ToJsName(((TypeResolveResult)resolveResult).Type, this.Emitter)); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this); return; } if (resolveResult is TypeResolveResult) { this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); return; } string inlineCode = memberResult != null?this.Emitter.GetInline(memberResult.Member) : null; bool hasInline = !string.IsNullOrEmpty(inlineCode); bool hasThis = hasInline && inlineCode.Contains("{this}"); if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); if (memberResult.Member.IsStatic) { this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); } else { this.WriteThis(); } inlineCode = inlineCode.Replace("{this}", this.Emitter.Output.ToString()); this.Emitter.Output = oldBuilder; if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } return; } if (hasInline && memberResult.Member.IsStatic) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } } else if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Property && memberResult.TargetResult.Type.Kind != TypeKind.Anonymous) { bool isStatement = false; string valueVar = null; if (this.Emitter.IsUnaryAccessor) { isStatement = identifierExpression.Parent is UnaryOperatorExpression && identifierExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(memberResult.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } } this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else if (Helpers.IsFieldProperty(memberResult.Member, this.Emitter)) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); } else if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isDecimal = Helpers.IsDecimalType(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isNullable = NullableType.IsNullable(memberResult.Member.ReturnType); if (isStatement) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); } else { this.Write(valueVar); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.Write(valueVar); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); this.WriteComma(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement) { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { string trg; if (memberResult.Member.IsStatic) { trg = BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter); } else { trg = "this"; } this.PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true), "(", trg, ".", Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false), "()", "{0})")); } else { this.PushWriter(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true) + "({0})"); } } else if (memberResult != null && memberResult.Member is DefaultResolvedEvent && this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else { this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove"); this.Write(OverloadsCollection.Create(this.Emitter, memberResult.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); } this.WriteOpenParentheses(); } else { if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else if (isResolved) { if (resolveResult is TypeResolveResult) { var typeResolveResult = (TypeResolveResult)resolveResult; this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); if (typeResolveResult.Type.TypeParameterCount > 0) { this.WriteOpenParentheses(); new TypeExpressionListBlock(this.Emitter, this.IdentifierExpression.TypeArguments).Emit(); this.WriteCloseParentheses(); } } else if (resolveResult is LocalResolveResult) { var localResolveResult = (LocalResolveResult)resolveResult; this.Write(localResolveResult.Variable.Name); } else if (memberResult != null) { this.WriteTarget(memberResult); this.Write(this.Emitter.GetEntityName(memberResult.Member)); } else { this.Write(resolveResult.ToString()); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this); } else { throw new EmitterException(identifierExpression, "Cannot resolve identifier: " + id); } } }
protected virtual void VisitVariableDeclarationStatement() { bool needVar = true; bool needComma = false; bool addSemicolon = !this.Emitter.IsAsync; var oldSemiColon = this.Emitter.EnableSemicolon; var asyncExpressionHandling = this.Emitter.AsyncExpressionHandling; foreach (var variable in this.VariableDeclarationStatement.Variables) { this.WriteSourceMapName(variable.Name); var varName = this.AddLocal(variable.Name, variable, this.VariableDeclarationStatement.Type); if (variable.Initializer != null && !variable.Initializer.IsNull && variable.Initializer.ToString().Contains(JS.Vars.FIX_ARGUMENT_NAME)) { continue; } if (needVar) { this.WriteVar(); needVar = false; } bool isReferenceLocal = false; var lrr = this.Emitter.Resolver.ResolveNode(variable, this.Emitter) as LocalResolveResult; if (this.Emitter.LocalsMap != null && lrr != null && this.Emitter.LocalsMap.ContainsKey(lrr.Variable)) { isReferenceLocal = this.Emitter.LocalsMap[lrr.Variable].EndsWith(".v"); } this.WriteAwaiters(variable.Initializer); var hasInitializer = !variable.Initializer.IsNull; if (variable.Initializer.IsNull && !this.VariableDeclarationStatement.Type.IsVar()) { var typeDef = this.Emitter.GetTypeDefinition(this.VariableDeclarationStatement.Type, true); if (typeDef != null && typeDef.IsValueType && !this.Emitter.Validator.IsExternalType(typeDef)) { hasInitializer = true; } } if (!this.Emitter.IsAsync || hasInitializer || isReferenceLocal) { if (needComma) { if (this.Emitter.IsAsync) { this.WriteSemiColon(); } else { this.WriteComma(); } } needComma = true; this.Write(varName); } if (hasInitializer) { addSemicolon = true; this.Write(" = "); if (isReferenceLocal) { this.Write("{ v : "); } var oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; if (!variable.Initializer.IsNull) { variable.Initializer.AcceptVisitor(this.Emitter); } else { var typerr = this.Emitter.Resolver.ResolveNode(this.VariableDeclarationStatement.Type, this.Emitter).Type; var isGeneric = typerr.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(typerr, this.Emitter); this.Write(string.Concat("new ", isGeneric ? "(" : "", BridgeTypes.ToJsName(this.VariableDeclarationStatement.Type, this.Emitter), isGeneric ? ")" : "", "()")); } this.Emitter.ReplaceAwaiterByVar = oldValue; if (isReferenceLocal) { this.Write(" }"); } } else if (isReferenceLocal) { addSemicolon = true; this.Write(" = { }"); } } this.Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (this.Emitter.EnableSemicolon && !needVar && addSemicolon) { this.WriteSemiColon(true); } if (oldSemiColon) { this.Emitter.EnableSemicolon = true; } }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var itype = this.Emitter.BridgeTypes.ToType(type); bool isCastAttr; string castCode = this.GetCastCode(expression, type, method, out isCastAttr); var enumType = itype; if (NullableType.IsNullable(enumType)) { enumType = NullableType.GetUnderlyingType(enumType); } var castToEnum = enumType.Kind == TypeKind.Enum; if (castToEnum) { itype = enumType.GetDefinition().EnumUnderlyingType; var enumMode = Helpers.EnumEmitMode(enumType); if (enumMode >= 3 && enumMode < 7) { itype = this.Emitter.Resolver.Compilation.FindType(KnownTypeCode.String); } } if (expression is NullReferenceExpression || (method != CS.Ops.IS && Helpers.IsIgnoreCast(type, this.Emitter)) || this.IsExternalCast(itype)) { if (expression is ParenthesizedExpression) { expression = ((ParenthesizedExpression)expression).Expression; } expression.AcceptVisitor(this.Emitter); return; } var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); var typerr = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (expressionrr.Type.Kind == TypeKind.Enum) { var enumMode = Helpers.EnumEmitMode(expressionrr.Type); if (enumMode >= 3 && enumMode < 7 && Helpers.IsIntegerType(itype, this.Emitter.Resolver)) { throw new EmitterException(this.CastExpression, "Enum underlying type is string and cannot be casted to number"); } } if (method == CS.Ops.CAST && expressionrr.Type.Kind != TypeKind.Enum) { var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter); if (cast_rr is ConstantResolveResult) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)cast_rr).ConstantValue; this.WriteCastValue(value, expectedType); return; } else { var conv_rr = cast_rr as ConversionResolveResult; if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)conv_rr.Input).ConstantValue; this.WriteCastValue(value, expectedType); return; } } } if (method == CS.Ops.IS && castToEnum) { this.Write(JS.Types.Bridge.IS); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); this.Write(", "); this.Write(BridgeTypes.ToJsName(itype, this.Emitter)); this.Write(")"); return; } if (expressionrr.Type.Equals(itype)) { if (method == CS.Ops.IS) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); } expression.AcceptVisitor(this.Emitter); if (method == CS.Ops.IS) { this.Write(")"); } return; } bool isResultNullable = NullableType.IsNullable(typerr.Type); if (castCode != null) { this.EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method); return; } bool isCast = method == CS.Ops.CAST; if (isCast) { if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression)) { expression.AcceptVisitor(this.Emitter); return; } } var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion)) { expression.AcceptVisitor(this.Emitter); return; } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == CS.Ops.CAST || method == CS.Ops.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == CS.Ops.IS) { hasValue = true; method = "hasValue"; } } bool unbox = this.Emitter.Rules.Boxing == BoxingRule.Managed && !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion; if (unbox) { this.Write("System.Nullable.getValue("); } var typeDef = itype.Kind == TypeKind.TypeParameter ? null : this.Emitter.GetTypeDefinition(type, true); if (typeDef != null && method == CS.Ops.IS && itype.Kind != TypeKind.Interface && this.Emitter.Validator.IsObjectLiteral(typeDef) && this.Emitter.Validator.GetObjectCreateMode(typeDef) == 0) { throw new EmitterException(type, $"ObjectLiteral type ({itype.FullName}) with Plain mode cannot be used in 'is' operator. Please define cast logic in Cast attribute or use Constructor mode."); } this.Write(JS.NS.BRIDGE); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); if (!hasValue) { this.WriteComma(); this.EmitCastType(itype); } if (isResultNullable && method != CS.Ops.IS) { this.WriteComma(); this.WriteScript(true); } this.WriteCloseParentheses(); if (unbox) { this.Write(")"); } }
protected void EmitGeneratorBlock() { this.BeginBlock(); var args = this.Parameters; if (!IsEnumeratorReturn) { this.WriteReturn(true); this.Write("new "); if (this.ReturnType.IsParameterized) { this.Write("(Bridge.GeneratorEnumerable$1(" + BridgeTypes.ToJsName(this.ReturnType.TypeArguments[0], this.Emitter) + "))"); } else { this.Write("Bridge.GeneratorEnumerable"); } this.WriteOpenParentheses(); this.Write(JS.Funcs.BRIDGE_BIND + "(this, "); this.WriteFunction(); if (args.Count > 0) { this.WriteOpenParentheses(); for (int i = 0; i < args.Count; i++) { this.Write(args[i]); if (i < args.Count - 1) { this.Write(", "); } } this.WriteCloseParentheses(); } else { this.WriteOpenCloseParentheses(true); } this.WriteSpace(); this.BeginBlock(); } this.WriteVar(true); this.Write(JS.Vars.ASYNC_STEP + " = 0"); this.Emitter.Comma = true; this.Indent(); // This is required to add async variables into Emitter.AsyncVariables and emit them prior to body IWriterInfo writerInfo = this.SaveWriter(); StringBuilder body = this.NewWriter(); Emitter.ResetLevel(writerInfo.Level - 1); this.EmitGeneratorBody(); this.RestoreWriter(writerInfo); foreach (var localVar in this.Emitter.AsyncVariables) { this.EnsureComma(true); this.Write(localVar); this.Emitter.Comma = true; } this.Emitter.Comma = false; this.WriteSemiColon(); this.Outdent(); this.WriteNewLine(); this.WriteNewLine(); this.WriteVar(true); this.Write(JS.Vars.ENUMERATOR + " = new "); if (this.ReturnType.IsParameterized) { this.Write("(" + JS.Types.Bridge.Generator.NAME_GENERIC + "(" + BridgeTypes.ToJsName(this.ReturnType.TypeArguments[0], this.Emitter) + "))"); } else { this.Write(JS.Types.Bridge.Generator.NAME); } this.WriteOpenParentheses(); this.Write(JS.Funcs.BRIDGE_BIND + "(this, "); this.WriteFunction(); this.WriteOpenCloseParentheses(true); this.Write(body); this.WriteCloseParentheses(); this.EmitFinallyHandler(); this.WriteCloseParentheses(); this.WriteSemiColon(); this.WriteNewLine(); this.WriteReturn(true); this.Write(JS.Vars.ENUMERATOR); this.WriteSemiColon(); this.WriteNewLine(); if (!IsEnumeratorReturn) { this.EndBlock(); if (args.Count > 0) { this.Write(", arguments"); } this.WriteCloseParentheses(); this.WriteCloseParentheses(); this.WriteSemiColon(); this.WriteNewLine(); } this.EndBlock(); }
protected virtual void EmitBaseConstructor(ConstructorDeclaration ctor, string ctorName, bool isObjectLiteral) { var initializer = ctor.Initializer != null && !ctor.Initializer.IsNull ? ctor.Initializer : new ConstructorInitializer() { ConstructorInitializerType = ConstructorInitializerType.Base }; bool appendScope = false; if (initializer.ConstructorInitializerType == ConstructorInitializerType.Base) { var baseType = this.Emitter.GetBaseTypeDefinition(); var baseName = JS.Funcs.CONSTRUCTOR; if (ctor.Initializer != null && !ctor.Initializer.IsNull) { var member = ((InvocationResolveResult)this.Emitter.Resolver.ResolveNode(ctor.Initializer, this.Emitter)).Member; var overloads = OverloadsCollection.Create(this.Emitter, member); if (overloads.HasOverloads) { baseName = overloads.GetOverloadName(); } } string name = null; if (this.TypeInfo.GetBaseTypes(this.Emitter).Any()) { name = BridgeTypes.ToJsName(this.TypeInfo.GetBaseClass(this.Emitter), this.Emitter); } else { name = BridgeTypes.ToJsName(baseType, this.Emitter); } this.Write(name, "."); this.Write(baseName); if (!isObjectLiteral) { this.WriteCall(); appendScope = true; } } else { // this.WriteThis(); string name = BridgeTypes.ToJsName(this.TypeInfo.Type, this.Emitter); this.Write(name); this.WriteDot(); var baseName = JS.Funcs.CONSTRUCTOR; var member = ((InvocationResolveResult)this.Emitter.Resolver.ResolveNode(ctor.Initializer, this.Emitter)).Member; var overloads = OverloadsCollection.Create(this.Emitter, member); if (overloads.HasOverloads) { baseName = overloads.GetOverloadName(); } this.Write(baseName); if (!isObjectLiteral) { this.WriteCall(); appendScope = true; } } int openPos = this.Emitter.Output.Length; this.WriteOpenParentheses(); if (appendScope) { this.WriteThis(); if (initializer.Arguments.Count > 0) { this.WriteComma(); } } if (initializer.Arguments.Count > 0) { var argsInfo = new ArgumentsInfo(this.Emitter, ctor.Initializer); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, ctor.Initializer, openPos).Emit(); } this.WriteCloseParentheses(); this.WriteSemiColon(); if (!isObjectLiteral) { this.WriteNewLine(); } }
private void EmitExternalBaseCtor(ConstructorDeclaration ctor, ref bool requireNewLine) { if (ctor.Initializer != null && !ctor.Initializer.IsNull) { var member = ((InvocationResolveResult)this.Emitter.Resolver.ResolveNode(ctor.Initializer, this.Emitter)).Member; var inlineCode = this.Emitter.GetInline(member); if (!string.IsNullOrEmpty(inlineCode)) { if (requireNewLine) { this.WriteNewLine(); requireNewLine = false; } this.Write(JS.Types.Bridge.APPLY); this.WriteOpenParentheses(); this.Write("this, "); var argsInfo = new ArgumentsInfo(this.Emitter, ctor.Initializer); new InlineArgumentsBlock(this.Emitter, argsInfo, inlineCode).Emit(); this.WriteCloseParentheses(); this.WriteSemiColon(); this.WriteNewLine(); } else { if (requireNewLine) { this.WriteNewLine(); requireNewLine = false; } var baseType = this.Emitter.GetBaseTypeDefinition(); string name = null; if (this.TypeInfo.GetBaseTypes(this.Emitter).Any()) { name = BridgeTypes.ToJsName(this.TypeInfo.GetBaseClass(this.Emitter), this.Emitter); } else { name = BridgeTypes.ToJsName(baseType, this.Emitter); } this.Write(name); this.WriteCall(); int openPos = this.Emitter.Output.Length; this.WriteOpenParentheses(); this.Write("this"); if (ctor.Initializer.Arguments.Count > 0) { this.Write(", "); var argsInfo = new ArgumentsInfo(this.Emitter, ctor.Initializer); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, ctor.Initializer, openPos).Emit(); } this.WriteCloseParentheses(); this.WriteSemiColon(); this.WriteNewLine(); } } }
protected virtual void EmitStructMethods() { var typeDef = this.Emitter.GetTypeDefinition(); string structName = BridgeTypes.ToJsName(this.TypeInfo.Type, this.Emitter); bool immutable = this.Emitter.Validator.IsImmutableType(typeDef); if (!immutable) { var mutableFields = this.TypeInfo.Type.GetFields(f => !f.IsConst, GetMemberOptions.IgnoreInheritedMembers); var autoProps = typeDef.Properties.Where(Helpers.IsAutoProperty); var autoEvents = this.TypeInfo.Type.GetEvents(null, GetMemberOptions.IgnoreInheritedMembers); immutable = !mutableFields.Any() && !autoProps.Any() && !autoEvents.Any(); } var fields = this.TypeInfo.InstanceConfig.Fields; var props = this.TypeInfo.InstanceConfig.Properties.Where(ent => { var p = ent.Entity as PropertyDeclaration; return(p != null && p.Getter != null && p.Getter.Body.IsNull && p.Setter != null && p.Setter.Body.IsNull); }); var list = fields.ToList(); list.AddRange(props); if (list.Count == 0) { this.EnsureComma(); this.Write(JS.Funcs.CLONE + ": function (to) { return this; }"); this.Emitter.Comma = true; return; } if (!this.TypeInfo.InstanceMethods.ContainsKey(CS.Methods.GETHASHCODE)) { this.EnsureComma(); this.Write(JS.Funcs.GETHASHCODE + ": function () "); this.BeginBlock(); this.Write("var h = " + JS.Funcs.BRIDGE_ADDHASH + "(["); var nameHashValue = new HashHelper().GetDeterministicHash(this.TypeInfo.Name); this.Write(nameHashValue); foreach (var field in list) { string fieldName = field.GetName(this.Emitter); this.Write(", this." + fieldName); } this.Write("]);"); this.WriteNewLine(); this.Write("return h;"); this.WriteNewLine(); this.EndBlock(); this.Emitter.Comma = true; } if (!this.TypeInfo.InstanceMethods.ContainsKey(CS.Methods.EQUALS)) { this.EnsureComma(); this.Write(JS.Funcs.EQUALS + ": function (o) "); this.BeginBlock(); this.Write("if (!" + JS.Types.Bridge.IS + "(o, "); this.Write(structName); this.Write(")) "); this.BeginBlock(); this.Write("return false;"); this.WriteNewLine(); this.EndBlock(); this.WriteNewLine(); this.Write("return "); bool and = false; foreach (var field in list) { string fieldName = field.GetName(this.Emitter); if (and) { this.Write(" && "); } and = true; this.Write(JS.Funcs.BRIDGE_EQUALS + "(this."); this.Write(fieldName); this.Write(", o."); this.Write(fieldName); this.Write(")"); } this.Write(";"); this.WriteNewLine(); this.EndBlock(); this.Emitter.Comma = true; } this.EnsureComma(); if (immutable) { this.Write(JS.Funcs.CLONE + ": function (to) { return this; }"); } else { this.Write(JS.Funcs.CLONE + ": function (to) "); this.BeginBlock(); this.Write("var s = to || new "); if (this.TypeInfo.Type.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(this.TypeInfo.Type, this.Emitter)) { structName = "(" + structName + ")"; } this.Write(structName); this.Write("();"); foreach (var field in list) { this.WriteNewLine(); string fieldName = field.GetName(this.Emitter); this.Write("s."); this.Write(fieldName); this.Write(" = "); int insertPosition = this.Emitter.Output.Length; this.Write("this."); this.Write(fieldName); var rr = this.Emitter.Resolver.ResolveNode(field.Entity, this.Emitter) as MemberResolveResult; if (rr == null && field.VarInitializer != null) { rr = Emitter.Resolver.ResolveNode(field.VarInitializer, Emitter) as MemberResolveResult; } if (rr != null) { Helpers.CheckValueTypeClone(rr, null, this, insertPosition); } this.Write(";"); } this.WriteNewLine(); this.Write("return s;"); this.WriteNewLine(); this.EndBlock(); } this.Emitter.Comma = true; }
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(")"); } } }
protected void VisitMemberReferenceExpression() { MemberReferenceExpression memberReferenceExpression = this.MemberReferenceExpression; int pos = this.Emitter.Output.Length; bool isRefArg = this.Emitter.IsRefArg; this.Emitter.IsRefArg = false; ResolveResult resolveResult = null; ResolveResult expressionResolveResult = null; string targetVar = null; string valueVar = null; bool isStatement = false; bool isConstTarget = false; var targetrr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Target, this.Emitter); if (targetrr is ConstantResolveResult) { isConstTarget = true; } var memberTargetrr = targetrr as MemberResolveResult; if (memberTargetrr != null && memberTargetrr.Type.Kind == TypeKind.Enum && memberTargetrr.Member is DefaultResolvedField && Helpers.EnumEmitMode(memberTargetrr.Type) == 2) { isConstTarget = true; } if (memberReferenceExpression.Target is ParenthesizedExpression || (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.Int64)) || (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.UInt64)) || (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.Decimal))) { isConstTarget = false; } var isInvoke = memberReferenceExpression.Parent is InvocationExpression && (((InvocationExpression)(memberReferenceExpression.Parent)).Target == memberReferenceExpression); if (isInvoke) { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); expressionResolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); if (expressionResolveResult is InvocationResolveResult) { resolveResult = expressionResolveResult; } else if (expressionResolveResult is MemberResolveResult) { if (((MemberResolveResult)expressionResolveResult).Member is IProperty) { resolveResult = expressionResolveResult; } } } else { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); } bool oldIsAssignment = this.Emitter.IsAssignment; bool oldUnary = this.Emitter.IsUnaryAccessor; if (resolveResult == null) { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.WriteDot(); string name = memberReferenceExpression.MemberName; this.Write(name.ToLowerCamelCase()); return; } bool isDynamic = false; if (resolveResult is DynamicInvocationResolveResult) { var dynamicResolveResult = (DynamicInvocationResolveResult)resolveResult; var group = dynamicResolveResult.Target as MethodGroupResolveResult; if (group != null && group.Methods.Count() > 1) { var 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 = this.Emitter.Resolver.Compilation.FindType(TypeCode.Object); } if (!m.Parameters[i].Type.Equals(argType)) { return(false); } } return(true); }) ?? group.Methods.Last(); isDynamic = true; resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method); resolveResult = new InvocationResolveResult(resolveResult, method, dynamicResolveResult.Arguments); } } if (resolveResult is MethodGroupResolveResult) { var oldResult = (MethodGroupResolveResult)resolveResult; resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); if (resolveResult is DynamicInvocationResolveResult) { var method = oldResult.Methods.Last(); resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method); } } MemberResolveResult member = resolveResult as MemberResolveResult; var globalTarget = member != null?this.Emitter.IsGlobalTarget(member.Member) : null; if (member != null && member.Member.Attributes.Any(a => a.AttributeType.FullName == "Bridge.NonScriptableAttribute")) { throw new EmitterException(this.MemberReferenceExpression, "Member " + member.ToString() + " is marked as not usable from script"); } if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod) { var interceptor = this.Emitter.Plugins.OnReference(this, this.MemberReferenceExpression, member); if (interceptor.Cancel) { return; } if (!string.IsNullOrEmpty(interceptor.Replacement)) { this.Write(interceptor.Replacement); return; } } if (globalTarget != null && globalTarget.Item1) { var target = globalTarget.Item2; if (!string.IsNullOrWhiteSpace(target)) { bool assign = false; var memberExpression = member.Member is IMethod ? memberReferenceExpression.Parent.Parent : memberReferenceExpression.Parent; var targetExpression = member.Member is IMethod ? memberReferenceExpression.Parent : memberReferenceExpression; var assignment = memberExpression as AssignmentExpression; if (assignment != null && assignment.Right == targetExpression) { assign = true; } else { var varInit = memberExpression as VariableInitializer; if (varInit != null && varInit.Initializer == targetExpression) { assign = true; } else if (memberExpression is InvocationExpression) { var targetInvocation = (InvocationExpression)memberExpression; if (targetInvocation.Arguments.Any(a => a == targetExpression)) { assign = true; } } } if (assign) { if (resolveResult is InvocationResolveResult) { this.PushWriter(target); } else { this.Write(target); } return; } } if (resolveResult is InvocationResolveResult) { this.PushWriter(""); } return; } Tuple <bool, bool, string> inlineInfo = member != null ? (isDynamic ? ((Emitter)this.Emitter).GetInlineCodeFromMember(member.Member, null) : this.Emitter.GetInlineCode(memberReferenceExpression)) : null; //string inline = member != null ? this.Emitter.GetInline(member.Member) : null; string inline = inlineInfo != null ? inlineInfo.Item3 : null; if (string.IsNullOrEmpty(inline) && member != null && member.Member is IMethod && !(member is InvocationResolveResult) && !( memberReferenceExpression.Parent is InvocationExpression && memberReferenceExpression.NextSibling != null && memberReferenceExpression.NextSibling.Role is TokenRole && ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "(" ) ) { var method = (IMethod)member.Member; if (method.TypeArguments.Count > 0) { inline = MemberReferenceBlock.GenerateInlineForMethodReference(method, this.Emitter); } } if (member != null && member.Member is IMethod && isInvoke) { var i_rr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter) as CSharpInvocationResolveResult; if (i_rr != null && !i_rr.IsExpandedForm) { var tpl = this.Emitter.GetAttribute(member.Member.Attributes, JS.NS.BRIDGE + ".TemplateAttribute"); if (tpl != null && tpl.PositionalArguments.Count == 2) { inline = tpl.PositionalArguments[1].ConstantValue.ToString(); } } } bool hasInline = !string.IsNullOrEmpty(inline); bool hasThis = hasInline && Helpers.HasThis(inline); inline = hasInline ? Helpers.ConvertTokens(this.Emitter, inline, member.Member) : inline; bool isInterfaceMember = false; if (hasInline && inline.StartsWith("<self>")) { hasThis = true; inline = inline.Substring(6); } bool nativeImplementation = true; bool isInterface = inline == null && member != null && member.Member.DeclaringTypeDefinition != null && member.Member.DeclaringTypeDefinition.Kind == TypeKind.Interface; var hasTypeParemeter = isInterface && Helpers.IsTypeParameterType(member.Member.DeclaringType); if (isInterface) { var itypeDef = member.Member.DeclaringTypeDefinition; var variance = MetadataUtils.IsJsGeneric(itypeDef, this.Emitter) && itypeDef.TypeParameters != null && itypeDef.TypeParameters.Any(typeParameter => typeParameter.Variance != VarianceModifier.Invariant); if (variance) { isInterfaceMember = true; } else { var ei = this.Emitter.Validator.IsExternalInterface(itypeDef); if (ei != null) { nativeImplementation = ei.IsNativeImplementation; } else { nativeImplementation = member.Member.DeclaringTypeDefinition.ParentAssembly.AssemblyName == CS.NS.ROOT || !this.Emitter.Validator.IsExternalType(member.Member.DeclaringTypeDefinition); } if (ei != null && ei.IsSimpleImplementation) { nativeImplementation = false; isInterfaceMember = false; } else if (ei != null || hasTypeParemeter) { if (hasTypeParemeter || !nativeImplementation) { isInterfaceMember = true; } } } } string interfaceTempVar = null; if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; var oldInline = inline; string thisArg = null; bool isSimple = true; if (this.MemberReferenceExpression.Target is BaseReferenceExpression) { thisArg = "this"; } else { this.Emitter.Output = new StringBuilder(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } this.WriteSimpleTarget(resolveResult); if (isConstTarget) { this.Write(")"); } thisArg = this.Emitter.Output.ToString(); if (Regex.Matches(inline, @"\{(\*?)this\}").Count > 1) { var mrr = resolveResult as MemberResolveResult; bool isField = mrr != null && mrr.Member is IField && (mrr.TargetResult is ThisResolveResult || mrr.TargetResult is LocalResolveResult || mrr.TargetResult is MemberResolveResult && ((MemberResolveResult)mrr.TargetResult).Member is IField); isSimple = (mrr != null && (mrr.TargetResult is ThisResolveResult || mrr.TargetResult is ConstantResolveResult || mrr.TargetResult is LocalResolveResult)) || isField; } } int thisIndex; inline = member != null?Helpers.ConvertTokens(this.Emitter, inline, member.Member) : inline; if (!isSimple) { StringBuilder sb = new StringBuilder(); sb.Append("("); var tempVar = this.GetTempVarName(); inline = inline.Replace("{this}", tempVar); thisIndex = tempVar.Length + 2; sb.Append(tempVar); sb.Append(" = "); sb.Append(thisArg); sb.Append(", "); sb.Append(inline); sb.Append(")"); inline = sb.ToString(); } else { thisIndex = inline.IndexOf("{this}", StringComparison.Ordinal); inline = inline.Replace("{this}", thisArg); } if (member != null && member.Member is IProperty) { this.Emitter.Output = new StringBuilder(); inline = inline.Replace("{0}", "[[0]]"); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); inline = this.Emitter.Output.ToString(); inline = inline.Replace("[[0]]", "{0}"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.Emitter.Output = oldBuilder; int[] range = null; if (thisIndex > -1) { range = new[] { thisIndex, thisIndex + thisArg.Length }; } if (resolveResult is InvocationResolveResult) { this.PushWriter(inline, null, thisArg, range); } else { if (member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), oldInline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else if (member != null && member.Member is IField && inline.Contains("{0}")) { this.PushWriter(inline, null, thisArg, range); } else if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inline)) { this.PushWriter(inline, null, thisArg, range); } else { this.Write(inline); } } return; } if (member != null && member.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(member.Member) && this.Emitter.IsInlineConst(member.Member)) { var parentExpression = memberReferenceExpression.Parent as MemberReferenceExpression; bool wrap = false; if (parentExpression != null) { var ii = this.Emitter.GetInlineCode(parentExpression); if (string.IsNullOrEmpty(ii.Item3)) { wrap = true; this.WriteOpenParentheses(); } } this.WriteScript(Bridge.Translator.Emitter.ConvertConstant(member.ConstantValue, memberReferenceExpression, this.Emitter)); if (wrap) { this.WriteCloseParentheses(); } } else if (hasInline && member.Member.IsStatic) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inline); } else { if (member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); } } } else { if (member != null && member.IsCompileTimeConstant && member.Member.DeclaringType.Kind == TypeKind.Enum) { var typeDef = member.Member.DeclaringType as ITypeDefinition; if (typeDef != null) { var enumMode = Helpers.EnumEmitMode(typeDef); if ((this.Emitter.Validator.IsExternalType(typeDef) && enumMode == -1) || enumMode == 2) { this.WriteScript(member.ConstantValue); return; } if (enumMode >= 3 && enumMode < 7) { string enumStringName = this.Emitter.GetEntityName(member.Member); this.WriteScript(enumStringName); return; } } } if (resolveResult is TypeResolveResult) { TypeResolveResult typeResolveResult = (TypeResolveResult)resolveResult; this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); return; } else if (member != null && member.Member is IMethod && !(member is InvocationResolveResult) && !( memberReferenceExpression.Parent is InvocationExpression && memberReferenceExpression.NextSibling != null && memberReferenceExpression.NextSibling.Role is TokenRole && ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "(" ) ) { if (!string.IsNullOrEmpty(inline)) { if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inline); } else { this.Write(inline); } } else { var resolvedMethod = (IMethod)member.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (!isStatic) { this.Write(isExtensionMethod ? JS.Funcs.BRIDGE_BIND_SCOPE : JS.Funcs.BRIDGE_CACHE_BIND); this.WriteOpenParentheses(); if (memberReferenceExpression.Target is BaseReferenceExpression) { this.WriteThis(); } else { interfaceTempVar = this.WriteTarget(resolveResult, isInterfaceMember, memberTargetrr, targetrr, false); } this.Write(", "); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (isExtensionMethod) { this.Write(BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter)); } else { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } if (interfaceTempVar != null) { this.Write(interfaceTempVar); } else { this.WriteSimpleTarget(resolveResult); } if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; } if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar, member, false); } else { this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation)); } if (!isStatic) { this.Write(")"); } } return; } else { bool isProperty = false; if (member != null && member.Member.SymbolKind == SymbolKind.Property && (member.Member.DeclaringTypeDefinition == null || !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition))) { isProperty = true; bool writeTargetVar = false; if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { writeTargetVar = true; } else if (this.Emitter.IsUnaryAccessor) { writeTargetVar = true; isStatement = memberReferenceExpression.Parent is UnaryOperatorExpression && memberReferenceExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(member.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); } } if (writeTargetVar) { bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (!(targetrr is ThisResolveResult || targetrr is TypeResolveResult || targetrr is LocalResolveResult || isField)) { targetVar = this.GetTempVarName(); this.Write(targetVar); this.Write(" = "); } } } if (isProperty && this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null) { valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } if (targetVar == null && isInterfaceMember) { interfaceTempVar = this.WriteTarget(resolveResult, isInterfaceMember, memberTargetrr, targetrr, true); } else { this.WriteSimpleTarget(resolveResult); } if (member != null && targetrr != null && targetrr.Type.Kind == TypeKind.Delegate && (member.Member.Name == "Invoke")) { var method = member.Member as IMethod; if (!(method != null && method.IsExtensionMethod)) { return; } } if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (targetVar != null) { if (this.Emitter.IsUnaryAccessor && !isStatement) { this.WriteComma(false); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.Write(targetVar); } else { this.WriteSemiColon(); this.WriteNewLine(); this.Write(targetVar); } } } var targetResolveResult = targetrr as MemberResolveResult; if (targetResolveResult == null || this.Emitter.IsGlobalTarget(targetResolveResult.Member) == null) { if (isRefArg) { this.WriteComma(); } else if (!isInterfaceMember && !this.NoTarget) { this.WriteDot(); } } if (member == null) { if (targetrr != null && targetrr.Type.Kind == TypeKind.Dynamic) { this.Write(memberReferenceExpression.MemberName); } else { this.Write(memberReferenceExpression.MemberName.ToLowerCamelCase()); } } else if (!string.IsNullOrEmpty(inline)) { if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inline); } else { this.Write(inline); } } else if (member.Member.SymbolKind == SymbolKind.Property && (member.Member.DeclaringTypeDefinition == null || (!this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition) || member.Member.IsStatic))) { if (member.Member is IProperty && targetrr != null && targetrr.Type.GetDefinition() != null && this.Emitter.Validator.IsObjectLiteral(targetrr.Type.GetDefinition()) && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)) { this.Write(this.Emitter.GetLiteralEntityName(member.Member)); } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { var name = OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation); var property = (IProperty)member.Member; var proto = member.IsVirtualCall || property.IsVirtual || property.IsOverride; if (this.MemberReferenceExpression.Target is BaseReferenceExpression && !property.IsIndexer && proto) { var alias = BridgeTypes.ToJsName(member.Member.DeclaringType, this.Emitter, isAlias: true); if (alias.StartsWith("\"")) { alias = alias.Insert(1, "$"); name = alias + "+\"$" + name + "\""; this.WriteIdentifier(name, false); } else { name = "$" + alias + "$" + name; this.WriteIdentifier(name); } } else { this.WriteIdentifier(name); } } } } else if (member.Member.SymbolKind == SymbolKind.Field) { bool isConst = this.Emitter.IsMemberConst(member.Member); if (isConst && this.Emitter.IsInlineConst(member.Member)) { this.WriteScript(Bridge.Translator.Emitter.ConvertConstant(member.ConstantValue, memberReferenceExpression, this.Emitter)); } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { var fieldName = OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation); if (isRefArg) { this.WriteScript(fieldName); } else { this.WriteIdentifier(fieldName); } } } } else if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; CSharpInvocationResolveResult cInvocationResult = resolveResult as CSharpInvocationResolveResult; var expresssionMember = expressionResolveResult as MemberResolveResult; if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else if (expresssionMember != null && cInvocationResult != null && cInvocationResult.IsDelegateInvocation && invocationResult.Member != expresssionMember.Member) { this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName(!nativeImplementation)); } else { this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName(!nativeImplementation)); } } else if (member.Member is IEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract, Helpers.GetAddOrRemove(this.Emitter.AssignmentType == AssignmentOperatorType.Add)); } else { this.Write(Helpers.GetEventRef(member.Member, this.Emitter, this.Emitter.AssignmentType != AssignmentOperatorType.Add, ignoreInterface: !nativeImplementation)); } this.WriteOpenParentheses(); } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { this.Write(this.Emitter.GetEntityName(member.Member)); } } } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { this.Write(this.Emitter.GetEntityName(member.Member)); } } Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this, pos); } }
protected virtual void EmitMethods(Dictionary <string, List <MethodDeclaration> > methods, Dictionary <string, List <EntityDeclaration> > properties, Dictionary <OperatorType, List <OperatorDeclaration> > operators) { int pos = this.Emitter.Output.Length; var writerInfo = this.SaveWriter(); string globalTarget = BridgeTypes.GetGlobalTarget(this.TypeInfo.Type.GetDefinition(), this.TypeInfo.TypeDeclaration); if (globalTarget == null) { this.EnsureComma(); this.Write(JS.Fields.METHODS); this.WriteColon(); this.BeginBlock(); } int checkPos = this.Emitter.Output.Length; var names = new List <string>(properties.Keys); foreach (var name in names) { var props = properties[name]; foreach (var prop in props) { if (prop is PropertyDeclaration) { this.Emitter.VisitPropertyDeclaration((PropertyDeclaration)prop); } else if (prop is CustomEventDeclaration) { this.Emitter.VisitCustomEventDeclaration((CustomEventDeclaration)prop); } else if (prop is IndexerDeclaration) { this.Emitter.VisitIndexerDeclaration((IndexerDeclaration)prop); } } } names = new List <string>(methods.Keys); foreach (var name in names) { this.EmitMethodsGroup(methods[name]); } if (operators != null) { var ops = new List <OperatorType>(operators.Keys); foreach (var op in ops) { this.EmitOperatorGroup(operators[op]); } } if (this.TypeInfo.ClassType == ClassType.Struct) { if (!this.StaticBlock) { this.EmitStructMethods(); } else { string structName = BridgeTypes.ToJsName(this.TypeInfo.Type, this.Emitter); if (this.TypeInfo.Type.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(this.TypeInfo.Type, this.Emitter)) { structName = "(" + structName + ")"; } this.EnsureComma(); this.Write(JS.Funcs.GETDEFAULTVALUE + ": function () { return new " + structName + "(); }"); this.Emitter.Comma = true; } } else if (this.StaticBlock) { var ctor = this.TypeInfo.Type.GetConstructors().FirstOrDefault(c => c.Parameters.Count == 0 && this.Emitter.GetInline(c) != null); if (ctor != null) { var code = this.Emitter.GetInline(ctor); this.EnsureComma(); this.Write(JS.Funcs.GETDEFAULTVALUE + ": function () "); this.BeginBlock(); this.Write("return "); var argsInfo = new ArgumentsInfo(this.Emitter, ctor); new InlineArgumentsBlock(this.Emitter, argsInfo, code).Emit(); this.Write(";"); this.WriteNewLine(); this.EndBlock(); this.Emitter.Comma = true; } } if (globalTarget == null) { if (checkPos == this.Emitter.Output.Length) { this.Emitter.IsNewLine = writerInfo.IsNewLine; this.Emitter.ResetLevel(writerInfo.Level); this.Emitter.Comma = writerInfo.Comma; this.Emitter.Output.Length = pos; } else { this.WriteNewLine(); this.EndBlock(); } } }
public virtual void ConvertParamsToReferences(IEnumerable <ParameterDeclaration> declarations) { if (declarations.Any()) { var p = declarations.First().Parent; if (p != null) { var rr = this.Emitter.Resolver.ResolveNode(p, this.Emitter) as MemberResolveResult; if (rr != null) { var method = rr.Member as DefaultResolvedMethod; if (method != null) { var expandParams = method.Attributes.Any(a => a.AttributeType.FullName == "Bridge.ExpandParamsAttribute"); foreach (var prm in method.Parameters) { if (prm.IsOptional) { var name = prm.Name; if (Helpers.IsReservedWord(this.Emitter, name)) { name = Helpers.ChangeReservedWord(name); } this.Write(string.Format("if ({0} === void 0) {{ {0} = ", name)); if (prm.ConstantValue == null && prm.Type.Kind == TypeKind.Struct && !prm.Type.IsKnownType(KnownTypeCode.NullableOfT)) { this.Write(Inspector.GetStructDefaultValue(prm.Type, this.Emitter)); } else if (prm.ConstantValue == null && prm.Type.Kind == TypeKind.TypeParameter) { this.Write(JS.Funcs.BRIDGE_GETDEFAULTVALUE + "(" + BridgeTypes.ToJsName(prm.Type, this.Emitter) + ")"); } else { this.WriteScript(prm.ConstantValue); } this.Write("; }"); this.WriteNewLine(); } else if (prm.IsParams) { var name = prm.Name; if (Helpers.IsReservedWord(this.Emitter, name)) { name = Helpers.ChangeReservedWord(name); } if (expandParams) { this.Write(string.Format("{0} = " + JS.Types.ARRAY + "." + JS.Fields.PROTOTYPE + "." + JS.Funcs.SLICE + "." + JS.Funcs.CALL + "(" + JS.Vars.ARGUMENTS + ", {1});", name, method.Parameters.IndexOf(prm) + method.TypeParameters.Count)); } else { this.Write(string.Format("if ({0} === void 0) {{ {0} = []; }}", name)); } this.WriteNewLine(); } } } } } } declarations.ToList().ForEach(item => { var lrr = item.Parent != null ? (LocalResolveResult)this.Emitter.Resolver.ResolveNode(item, this.Emitter) : null; var isReferenceLocal = lrr != null && this.Emitter.LocalsMap.ContainsKey(lrr.Variable) && this.Emitter.LocalsMap[lrr.Variable].EndsWith(".v"); if (item.Parent == null && item.Name == "value") { var p = this.Emitter.LocalsMap.FirstOrDefault(pair => pair.Key.Name == "value"); if (p.Value != null && p.Value.EndsWith(".v")) { isReferenceLocal = true; } } if (isReferenceLocal && !(item.ParameterModifier == ParameterModifier.Out || item.ParameterModifier == ParameterModifier.Ref)) { this.Write(string.Format("{0} = {{v:{0}}};", this.Emitter.LocalsNamesMap[item.Name])); this.WriteNewLine(); } }); }
protected override void DoEmit() { this.Emitter.Tag = "JS"; this.Emitter.Writers = new Stack <IWriter>(); this.Emitter.Outputs = new EmitterOutputs(); var metas = new Dictionary <IType, JObject>(); this.Emitter.Translator.Plugins.BeforeTypesEmit(this.Emitter, this.Emitter.Types); this.Emitter.ReflectableTypes = this.GetReflectableTypes(); var reflectedTypes = this.Emitter.ReflectableTypes; var tmpBuffer = new StringBuilder(); StringBuilder currentOutput = null; this.Emitter.NamedBoxedFunctions = new Dictionary <IType, Dictionary <string, string> >(); this.Emitter.HasModules = this.Emitter.Types.Any(t => t.Module != null); foreach (var type in this.Emitter.Types) { this.Emitter.Translator.Plugins.BeforeTypeEmit(this.Emitter, type); this.Emitter.Translator.EmitNode = type.TypeDeclaration; var typeDef = type.Type.GetDefinition(); this.Emitter.Rules = Rules.Get(this.Emitter, typeDef); bool isNative; if (typeDef.Kind == TypeKind.Interface && this.Emitter.Validator.IsExternalInterface(typeDef, out isNative)) { this.Emitter.Translator.Plugins.AfterTypeEmit(this.Emitter, type); continue; } if (type.IsObjectLiteral) { var mode = this.Emitter.Validator.GetObjectCreateMode(this.Emitter.GetTypeDefinition(type.Type)); var ignore = mode == 0 && !type.Type.GetMethods(null, GetMemberOptions.IgnoreInheritedMembers).Any(m => !m.IsConstructor && !m.IsAccessor); if (this.Emitter.Validator.IsExternalType(typeDef) || ignore) { this.Emitter.Translator.Plugins.AfterTypeEmit(this.Emitter, type); continue; } } this.Emitter.InitEmitter(); ITypeInfo typeInfo; if (this.Emitter.TypeInfoDefinitions.ContainsKey(type.Key)) { typeInfo = this.Emitter.TypeInfoDefinitions[type.Key]; type.Module = typeInfo.Module; type.FileName = typeInfo.FileName; type.Dependencies = typeInfo.Dependencies; typeInfo = type; } else { typeInfo = type; } this.Emitter.SourceFileName = type.TypeDeclaration.GetParent <SyntaxTree>().FileName; this.Emitter.SourceFileNameIndex = this.Emitter.SourceFiles.IndexOf(this.Emitter.SourceFileName); this.Emitter.Output = this.GetOutputForType(typeInfo, null); this.Emitter.TypeInfo = type; type.JsName = BridgeTypes.ToJsName(type.Type, this.Emitter, true, removeScope: false); if (this.Emitter.Output.Length > 0) { this.WriteNewLine(); } tmpBuffer.Length = 0; currentOutput = this.Emitter.Output; this.Emitter.Output = tmpBuffer; if (this.Emitter.TypeInfo.Module != null) { this.Indent(); } var name = BridgeTypes.ToJsName(type.Type, this.Emitter, true, true, true); if (type.Type.DeclaringType != null && JS.Reserved.StaticNames.Any(n => String.Equals(name, n, StringComparison.InvariantCulture))) { throw new EmitterException(type.TypeDeclaration, "Nested class cannot have such name: " + name + ". Please rename it."); } new ClassBlock(this.Emitter, this.Emitter.TypeInfo).Emit(); this.Emitter.Translator.Plugins.AfterTypeEmit(this.Emitter, type); currentOutput.Append(tmpBuffer.ToString()); this.Emitter.Output = currentOutput; } this.Emitter.DisableDependencyTracking = true; this.EmitNamedBoxedFunctions(); this.Emitter.NamespacesCache = new Dictionary <string, int>(); if (!this.Emitter.HasModules && this.Emitter.AssemblyInfo.Reflection.Target != MetadataTarget.Type) { foreach (var type in this.Emitter.Types) { var typeDef = type.Type.GetDefinition(); bool isGlobal = false; if (typeDef != null) { isGlobal = typeDef.Attributes.Any(a => a.AttributeType.FullName == "Bridge.GlobalMethodsAttribute" || a.AttributeType.FullName == "Bridge.MixinAttribute"); } if (typeDef.FullName != "System.Object") { var name = BridgeTypes.ToJsName(typeDef, this.Emitter); if (name == "Object") { continue; } } var isObjectLiteral = this.Emitter.Validator.IsObjectLiteral(typeDef); var isPlainMode = isObjectLiteral && this.Emitter.Validator.GetObjectCreateMode(this.Emitter.BridgeTypes.Get(type.Key).TypeDefinition) == 0; if (isPlainMode) { continue; } if (isGlobal || this.Emitter.TypeInfo.Module != null || reflectedTypes.Any(t => t == type.Type)) { continue; } var meta = MetadataUtils.ConstructTypeMetadata(typeDef, this.Emitter, true, type.TypeDeclaration.GetParent <SyntaxTree>()); if (meta != null) { metas.Add(type.Type, meta); } } } foreach (var reflectedType in reflectedTypes) { var typeDef = reflectedType.GetDefinition(); JObject meta = null; if (typeDef != null) { var tInfo = this.Emitter.Types.FirstOrDefault(t => t.Type == reflectedType); SyntaxTree tree = null; if (tInfo != null && tInfo.TypeDeclaration != null) { tree = tInfo.TypeDeclaration.GetParent <SyntaxTree>(); } if (tInfo != null && tInfo.Module != null || this.Emitter.HasModules || this.Emitter.AssemblyInfo.Reflection.Target == MetadataTarget.Type) { continue; } meta = MetadataUtils.ConstructTypeMetadata(reflectedType.GetDefinition(), this.Emitter, false, tree); } else { meta = MetadataUtils.ConstructITypeMetadata(reflectedType, this.Emitter); } if (meta != null) { metas.Add(reflectedType, meta); } } var lastOutput = this.Emitter.Output; var output = this.Emitter.AssemblyInfo.Reflection.Output; if (this.Emitter.AssemblyInfo.Reflection.Target == MetadataTarget.File && this.Emitter.AssemblyInfo.Module == null) { if (string.IsNullOrEmpty(output)) { if (!string.IsNullOrWhiteSpace(this.Emitter.AssemblyInfo.FileName) && this.Emitter.AssemblyInfo.FileName != AssemblyInfo.DEFAULT_FILENAME) { output = System.IO.Path.GetFileNameWithoutExtension(this.Emitter.AssemblyInfo.FileName) + ".meta.js"; } else { output = this.Emitter.Translator.ProjectProperties.AssemblyName + ".meta.js"; } } this.Emitter.Output = this.GetOutputForType(null, output, true); this.Emitter.MetaDataOutputName = this.Emitter.EmitterOutput.FileName; } var scriptableAttributes = MetadataUtils.GetScriptableAttributes(this.Emitter.Resolver.Compilation.MainAssembly.AssemblyAttributes, this.Emitter, null).ToList(); bool hasMeta = metas.Count > 0 || scriptableAttributes.Count > 0; if (hasMeta) { this.WriteNewLine(); int pos = 0; if (metas.Count > 0) { this.Write("var $m = " + JS.Types.Bridge.SET_METADATA + ","); this.WriteNewLine(); this.Write(Bridge.Translator.Emitter.INDENT + "$n = "); pos = this.Emitter.Output.Length; this.Write(";"); this.WriteNewLine(); } foreach (var meta in metas) { var metaData = meta.Value; string typeArgs = ""; if (meta.Key.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(meta.Key, this.Emitter)) { StringBuilder arr_sb = new StringBuilder(); var comma = false; foreach (var typeArgument in meta.Key.TypeArguments) { if (comma) { arr_sb.Append(", "); } arr_sb.Append(typeArgument.Name); comma = true; } typeArgs = arr_sb.ToString(); } this.Write(string.Format("$m(\"{0}\", function ({2}) {{ return {1}; }}, $n);", MetadataUtils.GetTypeName(meta.Key, this.Emitter, false, true, false), metaData.ToString(Formatting.None), typeArgs)); this.WriteNewLine(); } if (pos > 0) { this.Emitter.Output.Insert(pos, this.Emitter.ToJavaScript(this.Emitter.NamespacesCache.OrderBy(key => key.Value).Select(item => item.Key).ToArray())); this.Emitter.NamespacesCache = null; } if (scriptableAttributes.Count > 0) { JArray attrArr = new JArray(); foreach (var a in scriptableAttributes) { attrArr.Add(MetadataUtils.ConstructAttribute(a, null, this.Emitter)); } this.Write(string.Format("$asm.attr= {0};", attrArr.ToString(Formatting.None))); this.WriteNewLine(); } } this.Emitter.Output = lastOutput; //this.RemovePenultimateEmptyLines(true); this.Emitter.Translator.Plugins.AfterTypesEmit(this.Emitter, this.Emitter.Types); }