Пример #1
0
        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;
            }
        }
Пример #2
0
        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;
            }
        }
Пример #3
0
        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());
        }
Пример #5
0
        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();
        }
Пример #6
0
        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();
            }
        }
Пример #7
0
        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()));
        }
Пример #8
0
 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));
     }
 }
Пример #9
0
 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));
     }
 }
Пример #10
0
        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();
            }
        }
Пример #12
0
        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();
            }
        }
Пример #13
0
        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();
        }
Пример #14
0
        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);
        }
Пример #15
0
        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;
        }
Пример #16
0
        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(")");
            }
        }
Пример #17
0
        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);
        }
Пример #18
0
        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;
             * }
             */
        }
Пример #19
0
        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);
                }
            }
        }
Пример #20
0
        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;
            }
        }
Пример #21
0
        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(")");
            }
        }
Пример #22
0
        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();
        }
Пример #23
0
        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();
            }
        }
Пример #24
0
        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();
                }
            }
        }
Пример #25
0
        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;
        }
Пример #26
0
        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(")");
                }
            }
        }
Пример #27
0
        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);
            }
        }
Пример #28
0
        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();
                }
            }
        }
Пример #29
0
        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();
                }
            });
        }
Пример #30
0
        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);
        }