예제 #1
0
        protected override void DoEmit()
        {
            XmlToJsDoc.EmitComment(this, Emitter.Translator.EmitNode);
            string globalTarget = H5Types.GetGlobalTarget(TypeInfo.Type.GetDefinition(), TypeInfo.TypeDeclaration);

            if (globalTarget != null)
            {
                CheckGlobalClass();
                Emitter.NamedFunctions = new Dictionary <string, string>();
                WriteTopInitMethods();

                Write(JS.Types.H5.APPLY);
                WriteOpenParentheses();
                Write(globalTarget);
                Write(", ");
                BeginBlock();

                new MethodBlock(Emitter, TypeInfo, true).Emit();
                EmitMetadata();

                WriteNewLine();
                EndBlock();
                WriteCloseParentheses();
                WriteSemiColon();

                EmitAnonymousTypes();
                EmitNamedFunctions();

                WriteAfterInitMethods();

                WriteNewLine();
            }
            else
            {
                EmitClassHeader();

                Emitter.NamedFunctions = new Dictionary <string, string>();

                if (TypeInfo.TypeDeclaration.ClassType != ClassType.Interface)
                {
                    MethodDeclaration entryPoint = null;
                    if (TypeInfo.StaticMethods.Any(group =>
                    {
                        return(group.Value.Any(method =>
                        {
                            var result = Helpers.IsEntryPointMethod(Emitter, method);
                            if (result)
                            {
                                entryPoint = method;
                            }
                            return result;
                        }));
                    }))
                    {
                        if (!entryPoint.Body.IsNull)
                        {
                            Emitter.VisitMethodDeclaration(entryPoint);
                        }
                    }

                    EmitStaticBlock();
                    EmitInstantiableBlock();
                }

                EmitClassEnd();
            }
        }
예제 #2
0
        public IMethod GetCastMethod(IType fromType, IType toType, out string template)
        {
            string inline = null;
            var    method = fromType.GetMethods().FirstOrDefault(m =>
            {
                if (m.IsOperator && (m.Name == "op_Explicit" || m.Name == "op_Implicit") &&
                    m.Parameters.Count == 1 &&
                    m.ReturnType.ReflectionName == toType.ReflectionName &&
                    m.Parameters[0].Type.ReflectionName == fromType.ReflectionName
                    )
                {
                    string tmpInline = Emitter.GetInline(m);

                    if (!string.IsNullOrWhiteSpace(tmpInline))
                    {
                        inline = tmpInline;
                        return(true);
                    }
                }

                return(false);
            });

            if (method == null)
            {
                method = toType.GetMethods().FirstOrDefault(m =>
                {
                    if (m.IsOperator && (m.Name == "op_Explicit" || m.Name == "op_Implicit") &&
                        m.Parameters.Count == 1 &&
                        m.ReturnType.ReflectionName == toType.ReflectionName &&
                        (m.Parameters[0].Type.ReflectionName == fromType.ReflectionName)
                        )
                    {
                        string tmpInline = Emitter.GetInline(m);

                        if (!string.IsNullOrWhiteSpace(tmpInline))
                        {
                            inline = tmpInline;
                            return(true);
                        }
                    }

                    return(false);
                });
            }

            if (method == null && CastExpression != null)
            {
                var conversion = Emitter.Resolver.Resolver.GetConversion(CastExpression);

                if (conversion.IsUserDefined)
                {
                    method = conversion.Method;

                    string tmpInline = Emitter.GetInline(method);

                    if (!string.IsNullOrWhiteSpace(tmpInline))
                    {
                        inline = tmpInline;
                    }
                }
            }

            template = inline;
            return(method);
        }
예제 #3
0
        protected virtual void EmitClassHeader()
        {
            WriteTopInitMethods();

            var    typeDef = Emitter.GetTypeDefinition();
            string name    = Emitter.Validator.GetCustomTypeName(typeDef, Emitter, false);

            IsGeneric = typeDef.GenericParameters.Count > 0 && !Helpers.IsIgnoreGeneric(TypeInfo.Type, Emitter);

            if (name.IsEmpty())
            {
                name = H5Types.ToJsName(TypeInfo.Type, Emitter, asDefinition: true, nomodule: true, ignoreLiteralName: false);
            }

            if (typeDef.IsInterface && typeDef.HasGenericParameters)
            {
                Write(JS.Types.H5.DEFINE_I);
            }
            else
            {
                Write(JS.Types.H5.DEFINE);
            }

            WriteOpenParentheses();

            WriteScript(name);
            StartPosition = Emitter.Output.Length;
            Write(", ");

            if (IsGeneric)
            {
                if (TypeInfo.Module != null)
                {
                    Write(TypeInfo.Module.Name);
                    Write(", ");
                }

                WriteFunction();
                WriteOpenParentheses();

                foreach (var p in typeDef.GenericParameters)
                {
                    if (typeDef.GenericParameters.Count(gp => gp.FullName == p.FullName) > 1)
                    {
                        throw new EmitterException(TypeInfo.TypeDeclaration, $"Type parameter '{p.FullName}' has the same name as the type parameter from outer type.");
                    }
                    EnsureComma(false);
                    Write(p.Name);
                    Emitter.Comma = true;
                }
                Emitter.Comma = false;
                WriteCloseParentheses();

                Write(" { return ");
            }

            BeginBlock();

            string extend = Emitter.GetTypeHierarchy();

            if (extend.IsNotEmpty() && !TypeInfo.IsEnum)
            {
                var h5Type = Emitter.H5Types.Get(Emitter.TypeInfo);

                if (TypeInfo.InstanceMethods.Any(m => m.Value.Any(subm => Emitter.GetEntityName(subm) == JS.Fields.INHERITS)) ||
                    TypeInfo.InstanceConfig.Fields.Any(m => m.GetName(Emitter) == JS.Fields.INHERITS))
                {
                    Write(JS.Vars.D);
                }

                Write(JS.Fields.INHERITS);
                WriteColon();
                if (Helpers.IsTypeArgInSubclass(h5Type.TypeDefinition, h5Type.TypeDefinition, Emitter, false))
                {
                    WriteFunction();
                    WriteOpenCloseParentheses(true);
                    WriteOpenBrace(true);
                    WriteReturn(true);
                    Write(extend);
                    WriteSemiColon();
                    WriteCloseBrace(true);
                }
                else
                {
                    Write(extend);
                }

                Emitter.Comma = true;
            }

            WriteKind();
            EmitMetadata();
            WriteObjectLiteral();

            if (TypeInfo.Module != null)
            {
                WriteScope();
                WriteModule();
            }

            WriteVariance();
        }
예제 #4
0
        protected virtual void EmitMethods(Dictionary <string, List <MethodDeclaration> > methods, Dictionary <string, List <EntityDeclaration> > properties, Dictionary <OperatorType, List <OperatorDeclaration> > operators)
        {
            int pos        = Emitter.Output.Length;
            var writerInfo = SaveWriter();

            string globalTarget = H5Types.GetGlobalTarget(TypeInfo.Type.GetDefinition(), TypeInfo.TypeDeclaration);

            if (globalTarget == null)
            {
                EnsureComma();
                Write(JS.Fields.METHODS);
                WriteColon();
                BeginBlock();
            }

            int checkPos = 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)
                    {
                        Emitter.VisitPropertyDeclaration((PropertyDeclaration)prop);
                    }
                    else if (prop is CustomEventDeclaration)
                    {
                        Emitter.VisitCustomEventDeclaration((CustomEventDeclaration)prop);
                    }
                    else if (prop is IndexerDeclaration)
                    {
                        Emitter.VisitIndexerDeclaration((IndexerDeclaration)prop);
                    }
                }
            }

            names = new List <string>(methods.Keys);

            foreach (var name in names)
            {
                EmitMethodsGroup(methods[name]);
            }

            if (operators != null)
            {
                var ops = new List <OperatorType>(operators.Keys);

                foreach (var op in ops)
                {
                    EmitOperatorGroup(operators[op]);
                }
            }

            if (TypeInfo.ClassType == ClassType.Struct)
            {
                if (!StaticBlock)
                {
                    EmitStructMethods();
                }
                else
                {
                    string structName = H5Types.ToJsName(TypeInfo.Type, Emitter);
                    if (TypeInfo.Type.TypeArguments.Count > 0 &&
                        !Helpers.IsIgnoreGeneric(TypeInfo.Type, Emitter))
                    {
                        structName = "(" + structName + ")";
                    }

                    EnsureComma();
                    Write(JS.Funcs.GETDEFAULTVALUE + ": function () { return new " + structName + "(); }");
                    Emitter.Comma = true;
                }
            }
            else if (StaticBlock)
            {
                var ctor = TypeInfo.Type.GetConstructors().FirstOrDefault(c => c.Parameters.Count == 0 && Emitter.GetInline(c) != null);

                if (ctor != null)
                {
                    var code = Emitter.GetInline(ctor);
                    EnsureComma();
                    Write(JS.Funcs.GETDEFAULTVALUE + ": function () ");
                    BeginBlock();
                    Write("return ");
                    var argsInfo = new ArgumentsInfo(Emitter, ctor);
                    new InlineArgumentsBlock(Emitter, argsInfo, code).Emit();
                    Write(";");
                    WriteNewLine();
                    EndBlock();
                    Emitter.Comma = true;
                }
            }

            if (globalTarget == null)
            {
                if (checkPos == Emitter.Output.Length)
                {
                    Emitter.IsNewLine = writerInfo.IsNewLine;
                    Emitter.ResetLevel(writerInfo.Level);
                    Emitter.Comma         = writerInfo.Comma;
                    Emitter.Output.Length = pos;
                }
                else
                {
                    WriteNewLine();
                    EndBlock();
                }
            }
        }
예제 #5
0
        protected virtual void EmitCastExpression(Expression expression, AstType type, string method)
        {
            var    itype = Emitter.H5Types.ToType(type);
            bool   isCastAttr;
            string castCode = 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 = Emitter.Resolver.Compilation.FindType(KnownTypeCode.String);
                }
            }

            if (expression is NullReferenceExpression || (method != CS.Ops.IS && Helpers.IsIgnoreCast(type, Emitter)) || IsExternalCast(itype))
            {
                if (expression is ParenthesizedExpression)
                {
                    expression = ((ParenthesizedExpression)expression).Expression;
                }

                expression.AcceptVisitor(Emitter);
                return;
            }

            var expressionrr = Emitter.Resolver.ResolveNode(expression);
            var typerr       = Emitter.Resolver.ResolveNode(type);

            if (expressionrr.Type.Kind == TypeKind.Enum)
            {
                var enumMode = Helpers.EnumEmitMode(expressionrr.Type);
                if (enumMode >= 3 && enumMode < 7 && Helpers.IsIntegerType(itype, Emitter.Resolver))
                {
                    throw new EmitterException(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 = Emitter.Resolver.ResolveNode(CastExpression);

                if (cast_rr is ConstantResolveResult)
                {
                    var expectedType = Emitter.Resolver.Resolver.GetExpectedType(CastExpression);
                    var value        = ((ConstantResolveResult)cast_rr).ConstantValue;

                    WriteCastValue(value, expectedType);
                    return;
                }
                else
                {
                    if (cast_rr is ConversionResolveResult conv_rr && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined)
                    {
                        var expectedType = Emitter.Resolver.Resolver.GetExpectedType(CastExpression);
                        var value        = ((ConstantResolveResult)conv_rr.Input).ConstantValue;
                        WriteCastValue(value, expectedType);
                        return;
                    }
                }
            }

            if (method == CS.Ops.IS && castToEnum)
            {
                Write(JS.Types.H5.IS);
                WriteOpenParentheses();
                expression.AcceptVisitor(Emitter);
                Write(", ");
                Write(H5Types.ToJsName(itype, Emitter));
                Write(")");
                return;
            }

            if (expressionrr.Type.Equals(itype))
            {
                if (method == CS.Ops.IS)
                {
                    Write(JS.Funcs.H5_HASVALUE);
                    WriteOpenParentheses();
                }
                expression.AcceptVisitor(Emitter);
                if (method == CS.Ops.IS)
                {
                    Write(")");
                }

                return;
            }

            bool isResultNullable = NullableType.IsNullable(typerr.Type);

            if (castCode != null)
            {
                EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method);
                return;
            }

            bool isCast = method == CS.Ops.CAST;

            if (isCast)
            {
                if (IsUserDefinedConversion(this, CastExpression.Expression) || IsUserDefinedConversion(this, CastExpression))
                {
                    expression.AcceptVisitor(Emitter);

                    return;
                }
            }

            var conversion = Emitter.Resolver.Resolver.GetConversion(expression);

            if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion))
            {
                expression.AcceptVisitor(Emitter);
                return;
            }

            bool hasValue = false;

            if (type is SimpleType simpleType && simpleType.Identifier == "dynamic")
            {
                if (method == CS.Ops.CAST || method == CS.Ops.AS)
                {
                    expression.AcceptVisitor(Emitter);
                    return;
                }
                else if (method == CS.Ops.IS)
                {
                    hasValue = true;
                    method   = "hasValue";
                }
            }

            bool unbox = Emitter.Rules.Boxing == BoxingRule.Managed && !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion;

            if (unbox)
            {
                Write("System.Nullable.getValue(");
            }

            var typeDef = itype.Kind == TypeKind.TypeParameter ? null : Emitter.GetTypeDefinition(type, true);

            if (typeDef != null && method == CS.Ops.IS && itype.Kind != TypeKind.Interface && Emitter.Validator.IsObjectLiteral(typeDef) && 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.");
            }

            Write(JS.NS.H5);
            WriteDot();
            Write(method);
            WriteOpenParentheses();

            expression.AcceptVisitor(Emitter);

            if (!hasValue)
            {
                WriteComma();
                EmitCastType(itype);
            }

            if (isResultNullable && method != CS.Ops.IS)
            {
                WriteComma();
                WriteScript(true);
            }

            WriteCloseParentheses();

            if (unbox)
            {
                Write(")");
            }
        }
예제 #6
0
        protected void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
        {
            foreach (var attrSection in methodDeclaration.Attributes)
            {
                foreach (var attr in attrSection.Attributes)
                {
                    var rr = Emitter.Resolver.ResolveNode(attr.Type);
                    if (rr.Type.FullName == "H5.ExternalAttribute")
                    {
                        return;
                    }
                    else if (rr.Type.FullName == "H5.InitAttribute")
                    {
                        InitPosition initPosition = InitPosition.After;

                        if (attr.HasArgumentList)
                        {
                            if (attr.Arguments.Any())
                            {
                                var argExpr = attr.Arguments.First();
                                var argrr   = Emitter.Resolver.ResolveNode(argExpr);
                                if (argrr.ConstantValue is int)
                                {
                                    initPosition = (InitPosition)argrr.ConstantValue;
                                }
                            }
                        }

                        if (initPosition > 0)
                        {
                            return;
                        }
                    }
                }
            }

            EnsureComma();
            ResetLocals();

            var prevMap      = BuildLocalsMap();
            var prevNamesMap = BuildLocalsNamesMap();

            AddLocals(methodDeclaration.Parameters, methodDeclaration.Body);

            var overloads = OverloadsCollection.Create(Emitter, methodDeclaration);

            XmlToJsDoc.EmitComment(this, MethodDeclaration);
            var isEntryPoint = Helpers.IsEntryPointMethod(Emitter, MethodDeclaration);
            var member_rr    = (MemberResolveResult)Emitter.Resolver.ResolveNode(MethodDeclaration);

            string name = overloads.GetOverloadName(false, null, excludeTypeOnly: OverloadsCollection.ExcludeTypeParameterForDefinition(member_rr));

            if (isEntryPoint)
            {
                Write(JS.Funcs.ENTRY_POINT_NAME);
            }
            else
            {
                Write(name);
            }

            WriteColon();

            WriteFunction();

            if (isEntryPoint)
            {
                Write(name);
                WriteSpace();
            }
            else
            {
                var nm = Helpers.GetFunctionName(Emitter.AssemblyInfo.NamedFunctions, member_rr.Member, Emitter);
                if (nm != null)
                {
                    Write(nm);
                    WriteSpace();
                }
            }

            EmitMethodParameters(methodDeclaration.Parameters, methodDeclaration.TypeParameters.Count > 0 && Helpers.IsIgnoreGeneric(methodDeclaration, Emitter) ? null : methodDeclaration.TypeParameters, methodDeclaration);

            WriteSpace();

            var script = Emitter.GetScript(methodDeclaration);

            if (script == null)
            {
                if (YieldBlock.HasYield(methodDeclaration.Body))
                {
                    new GeneratorBlock(Emitter, methodDeclaration).Emit();
                }
                else if (methodDeclaration.HasModifier(Modifiers.Async) || AsyncBlock.HasGoto(methodDeclaration.Body))
                {
                    new AsyncBlock(Emitter, methodDeclaration).Emit();
                }
                else
                {
                    methodDeclaration.Body.AcceptVisitor(Emitter);
                }
            }
            else
            {
                BeginBlock();

                WriteLines(script);

                EndBlock();
            }

            ClearLocalsMap(prevMap);
            ClearLocalsNamesMap(prevNamesMap);
            Emitter.Comma = true;
        }
예제 #7
0
        protected virtual void EmitStructMethods()
        {
            var    typeDef    = Emitter.GetTypeDefinition();
            string structName = H5Types.ToJsName(TypeInfo.Type, Emitter);

            bool immutable = Emitter.Validator.IsImmutableType(typeDef);

            if (!immutable)
            {
                var mutableFields = TypeInfo.Type.GetFields(f => !f.IsConst, GetMemberOptions.IgnoreInheritedMembers);
                var autoProps     = typeDef.Properties.Where(Helpers.IsAutoProperty);
                var autoEvents    = TypeInfo.Type.GetEvents(null, GetMemberOptions.IgnoreInheritedMembers);
                immutable = !mutableFields.Any() && !autoProps.Any() && !autoEvents.Any();
            }

            var fields = TypeInfo.InstanceConfig.Fields;
            var props  = TypeInfo.InstanceConfig.Properties.Where(ent =>
            {
                return(ent.Entity is PropertyDeclaration p && 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)
            {
                EnsureComma();
                Write(JS.Funcs.CLONE + ": function (to) { return this; }");
                Emitter.Comma = true;
                return;
            }

            if (!TypeInfo.InstanceMethods.ContainsKey(CS.Methods.GETHASHCODE))
            {
                EnsureComma();
                Write(JS.Funcs.GETHASHCODE + ": function () ");
                BeginBlock();
                Write("var h = " + JS.Funcs.H5_ADDHASH + "([");

                var nameHashValue = new HashHelper().GetDeterministicHash(TypeInfo.Name);
                Write(nameHashValue);

                foreach (var field in list)
                {
                    string fieldName = field.GetName(Emitter);
                    Write(", this." + fieldName);
                }

                Write("]);");

                WriteNewLine();
                Write("return h;");
                WriteNewLine();
                EndBlock();
                Emitter.Comma = true;
            }

            if (!TypeInfo.InstanceMethods.ContainsKey(CS.Methods.EQUALS))
            {
                EnsureComma();
                Write(JS.Funcs.EQUALS + ": function (o) ");
                BeginBlock();
                Write("if (!" + JS.Types.H5.IS + "(o, ");
                Write(structName);
                Write(")) ");
                BeginBlock();
                Write("return false;");
                WriteNewLine();
                EndBlock();
                WriteNewLine();
                Write("return ");

                bool and = false;

                foreach (var field in list)
                {
                    string fieldName = field.GetName(Emitter);

                    if (and)
                    {
                        Write(" && ");
                    }

                    and = true;

                    Write(JS.Funcs.H5_EQUALS + "(this.");
                    Write(fieldName);
                    Write(", o.");
                    Write(fieldName);
                    Write(")");
                }

                Write(";");
                WriteNewLine();
                EndBlock();
                Emitter.Comma = true;
            }

            EnsureComma();

            if (immutable)
            {
                Write(JS.Funcs.CLONE + ": function (to) { return this; }");
            }
            else
            {
                Write(JS.Funcs.CLONE + ": function (to) ");
                BeginBlock();
                Write("var s = to || new ");
                if (TypeInfo.Type.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(TypeInfo.Type, Emitter))
                {
                    structName = "(" + structName + ")";
                }
                Write(structName);
                Write("();");

                foreach (var field in list)
                {
                    WriteNewLine();
                    string fieldName = field.GetName(Emitter);

                    Write("s.");
                    Write(fieldName);
                    Write(" = ");

                    int insertPosition = Emitter.Output.Length;
                    Write("this.");
                    Write(fieldName);

                    var rr = Emitter.Resolver.ResolveNode(field.Entity) as MemberResolveResult;

                    if (rr == null && field.VarInitializer != null)
                    {
                        rr = Emitter.Resolver.ResolveNode(field.VarInitializer) as MemberResolveResult;
                    }

                    if (rr != null)
                    {
                        Helpers.CheckValueTypeClone(rr, null, this, insertPosition);
                    }

                    Write(";");
                }

                WriteNewLine();
                Write("return s;");
                WriteNewLine();
                EndBlock();
            }

            Emitter.Comma = true;
        }
예제 #8
0
        protected void VisitForeachStatement(bool?replaceAwaiterByVar = null)
        {
            ForeachStatement foreachStatement = ForeachStatement;
            var jumpStatements = Emitter.JumpStatements;

            Emitter.JumpStatements = null;

            if (foreachStatement.EmbeddedStatement is EmptyStatement)
            {
                return;
            }

            WriteSourceMapName(foreachStatement.VariableName);
            var iteratorVar  = GetTempVarName();
            var iteratorName = AddLocal(iteratorVar, null, AstType.Null);

            var rr     = (ForEachResolveResult)Emitter.Resolver.ResolveNode(foreachStatement);
            var get_rr = rr.GetEnumeratorCall as InvocationResolveResult;
            var in_rr  = Emitter.Resolver.ResolveNode(foreachStatement.InExpression);
            var inline = get_rr != null?Emitter.GetInline(get_rr.Member) : null;

            var checkEnum = in_rr.Type.Kind != TypeKind.Array && !in_rr.Type.IsKnownType(KnownTypeCode.String) &&
                            !in_rr.Type.IsKnownType(KnownTypeCode.Array);
            var isGenericEnumerable = rr.CollectionType.IsParameterized &&
                                      rr.CollectionType.FullName == "System.Collections.Generic.IEnumerable";
            var emitInline = checkEnum && !isGenericEnumerable && inline != null;

            Write(iteratorName, " = ");

            if (!emitInline)
            {
                Write(JS.Funcs.H5_GET_ENUMERATOR);
                WriteOpenParentheses();
                foreachStatement.InExpression.AcceptVisitor(Emitter);
            }

            if (checkEnum)
            {
                if (isGenericEnumerable)
                {
                    WriteComma(false);
                    Write(H5Types.ToJsName(((ParameterizedType)rr.CollectionType).TypeArguments[0], Emitter));
                }
                else if (get_rr != null)
                {
                    if (inline != null)
                    {
                        var argsInfo = new ArgumentsInfo(Emitter, foreachStatement.InExpression, get_rr);
                        new InlineArgumentsBlock(Emitter, argsInfo, inline).Emit();
                    }
                    else
                    {
                        var name = OverloadsCollection.Create(Emitter, get_rr.Member).GetOverloadName();

                        if (name != "GetEnumerator" && name != "System$Collections$IEnumerable$GetEnumerator")
                        {
                            WriteComma(false);
                            WriteScript(name);
                        }
                    }
                }
            }

            if (!emitInline)
            {
                WriteCloseParentheses();
            }
            WriteSemiColon();
            WriteNewLine();

            WriteTry();
            BeginBlock();
            WriteWhile();
            WriteOpenParentheses();
            Write(iteratorName);
            WriteDot();
            Write(JS.Funcs.MOVE_NEXT);
            WriteOpenCloseParentheses();
            WriteCloseParentheses();
            WriteSpace();
            BeginBlock();

            PushLocals();
            Action ac = () =>
            {
                bool isReferenceLocal = false;

                if (Emitter.LocalsMap != null && Emitter.LocalsMap.ContainsKey(rr.ElementVariable))
                {
                    isReferenceLocal = Emitter.LocalsMap[rr.ElementVariable].EndsWith(".v");
                }

                var varName = AddLocal(foreachStatement.VariableName, foreachStatement.VariableNameToken, foreachStatement.VariableType);

                WriteVar();
                Write(varName + " = ");

                if (isReferenceLocal)
                {
                    Write("{ v : ");
                }

                string castCode = GetCastCode(rr.ElementType, rr.ElementVariable.Type);

                if (castCode != null)
                {
                    EmitInlineCast(iteratorName + "." + JS.Funcs.GET_CURRENT, castCode);
                }
                else if (CastMethod != null)
                {
                    Write(H5Types.ToJsName(CastMethod.DeclaringType, Emitter));
                    WriteDot();
                    Write(OverloadsCollection.Create(Emitter, CastMethod).GetOverloadName());
                    WriteOpenParentheses();
                    int pos = Emitter.Output.Length;
                    Write(iteratorName + "." + JS.Funcs.GET_CURRENT);
                    Helpers.CheckValueTypeClone(rr, ForeachStatement.InExpression, this, pos);
                    WriteCloseParentheses();
                }
                else
                {
                    var needCast = !rr.ElementType.Equals(rr.ElementVariable.Type);
                    if (needCast)
                    {
                        Write(JS.Funcs.H5_CAST);
                        WriteOpenParentheses();
                    }
                    int pos = Emitter.Output.Length;
                    Write(iteratorName);

                    WriteDot();
                    Write(JS.Funcs.GET_CURRENT);

                    Helpers.CheckValueTypeClone(rr, ForeachStatement.InExpression, this, pos);

                    if (needCast)
                    {
                        Write(", ", H5Types.ToJsName(rr.ElementVariable.Type, Emitter), ")");
                    }
                }

                if (isReferenceLocal)
                {
                    Write(" }");
                }

                WriteSemiColon();
                WriteNewLine();
            };

            Emitter.BeforeBlock = ac;


            if (replaceAwaiterByVar.HasValue)
            {
                Emitter.ReplaceAwaiterByVar = replaceAwaiterByVar.Value;
            }

            if (foreachStatement.EmbeddedStatement is BlockStatement block)
            {
                Emitter.NoBraceBlock = block;
            }

            foreachStatement.EmbeddedStatement.AcceptVisitor(Emitter);

            PopLocals();

            if (!Emitter.IsNewLine)
            {
                WriteNewLine();
            }

            EndBlock();
            WriteNewLine();

            EndBlock();
            WriteSpace();
            WriteFinally();
            BeginBlock();
            Write($"if ({JS.Types.H5.IS}({iteratorName}, {JS.Types.System.IDisposable.NAME})) ");
            BeginBlock();
            Write($"{iteratorName}.{JS.Types.System.IDisposable.INTERFACE_DISPOSE}();");
            WriteNewLine();
            EndBlock();
            WriteNewLine();
            EndBlock();
            WriteNewLine();
            Emitter.JumpStatements = jumpStatements;
        }
예제 #9
0
        protected void VisitAsyncForeachStatement()
        {
            ForeachStatement foreachStatement = ForeachStatement;

            if (foreachStatement.EmbeddedStatement is EmptyStatement)
            {
                return;
            }

            var oldValue       = Emitter.ReplaceAwaiterByVar;
            var jumpStatements = Emitter.JumpStatements;

            Emitter.JumpStatements = new List <IJumpInfo>();
            WriteAwaiters(foreachStatement.InExpression);

            bool containsAwaits = false;
            var  awaiters       = GetAwaiters(foreachStatement.EmbeddedStatement);

            if (awaiters != null && awaiters.Length > 0)
            {
                containsAwaits = true;
            }

            Emitter.ReplaceAwaiterByVar = true;

            if (!containsAwaits)
            {
                VisitForeachStatement(oldValue);
                return;
            }

            var iteratorName = AddLocal(GetTempVarName(), null, AstType.Null);

            var for_rr = (ForEachResolveResult)Emitter.Resolver.ResolveNode(foreachStatement);
            var get_rr = for_rr.GetEnumeratorCall as InvocationResolveResult;
            var in_rr  = Emitter.Resolver.ResolveNode(foreachStatement.InExpression);
            var inline = get_rr != null?Emitter.GetInline(get_rr.Member) : null;

            var checkEnum = in_rr.Type.Kind != TypeKind.Array && !in_rr.Type.IsKnownType(KnownTypeCode.String) &&
                            !in_rr.Type.IsKnownType(KnownTypeCode.Array);
            var isGenericEnumerable = for_rr.CollectionType.IsParameterized &&
                                      for_rr.CollectionType.FullName == "System.Collections.Generic.IEnumerable";
            var emitInline = checkEnum && !isGenericEnumerable && inline != null;

            Write(iteratorName, " = ");

            if (!emitInline)
            {
                Write(JS.Funcs.H5_GET_ENUMERATOR);
                WriteOpenParentheses();
                foreachStatement.InExpression.AcceptVisitor(Emitter);
            }

            if (checkEnum)
            {
                if (for_rr.CollectionType.IsParameterized &&
                    for_rr.CollectionType.FullName == "System.Collections.Generic.IEnumerable")
                {
                    WriteComma(false);
                    Write(H5Types.ToJsName(((ParameterizedType)for_rr.CollectionType).TypeArguments[0], Emitter));
                }
                else if (get_rr != null)
                {
                    if (inline != null)
                    {
                        var argsInfo = new ArgumentsInfo(Emitter, foreachStatement.InExpression, get_rr);
                        new InlineArgumentsBlock(Emitter, argsInfo, inline).Emit();
                    }
                    else
                    {
                        var name = OverloadsCollection.Create(Emitter, get_rr.Member).GetOverloadName();

                        if (name != "GetEnumerator" && name != "System$Collections$IEnumerable$GetEnumerator")
                        {
                            WriteComma(false);
                            WriteScript(name);
                        }
                    }
                }
            }

            Emitter.ReplaceAwaiterByVar = oldValue;
            if (!emitInline)
            {
                WriteCloseParentheses();
            }
            WriteSemiColon();
            WriteNewLine();
            Write(JS.Vars.ASYNC_STEP + " = " + Emitter.AsyncBlock.Step + ";");
            WriteNewLine();
            Write("continue;");
            WriteNewLine();

            IAsyncStep conditionStep = Emitter.AsyncBlock.AddAsyncStep();

            WriteIf();
            WriteOpenParentheses();
            Write(iteratorName);
            WriteDot();
            Write(JS.Funcs.MOVE_NEXT);
            WriteOpenCloseParentheses();
            WriteCloseParentheses();
            WriteSpace();
            BeginBlock();

            PushLocals();

            var varName = AddLocal(foreachStatement.VariableName, foreachStatement.VariableNameToken, foreachStatement.VariableType);

            WriteVar();
            Write(varName + " = ");

            var rr = Emitter.Resolver.ResolveNode(foreachStatement) as ForEachResolveResult;

            bool isReferenceLocal = false;

            if (Emitter.LocalsMap != null && Emitter.LocalsMap.ContainsKey(rr.ElementVariable))
            {
                isReferenceLocal = Emitter.LocalsMap[rr.ElementVariable].EndsWith(".v");
            }

            if (isReferenceLocal)
            {
                Write("{ v : ");
            }

            string castCode = GetCastCode(rr.ElementType, rr.ElementVariable.Type);

            if (castCode != null)
            {
                EmitInlineCast(iteratorName + "." + JS.Funcs.GET_CURRENT, castCode);
            }
            else if (CastMethod != null)
            {
                Write(H5Types.ToJsName(CastMethod.DeclaringType, Emitter));
                WriteDot();
                Write(OverloadsCollection.Create(Emitter, CastMethod).GetOverloadName());
                WriteOpenParentheses();
                var pos = Emitter.Output.Length;
                Write(iteratorName + "." + JS.Funcs.GET_CURRENT);
                Helpers.CheckValueTypeClone(rr, ForeachStatement.InExpression, this, pos);
                WriteCloseParentheses();
            }
            else
            {
                var needCast = !rr.ElementType.Equals(rr.ElementVariable.Type);
                if (needCast)
                {
                    Write(JS.Funcs.H5_CAST);
                    WriteOpenParentheses();
                }

                var pos = Emitter.Output.Length;
                Write(iteratorName);

                WriteDot();
                Write(JS.Funcs.GET_CURRENT);
                Helpers.CheckValueTypeClone(rr, ForeachStatement.InExpression, this, pos);

                if (needCast)
                {
                    Write(", ", H5Types.ToJsName(rr.ElementVariable.Type, Emitter), ")");
                }
            }

            if (isReferenceLocal)
            {
                Write(" }");
            }

            WriteSemiColon();
            WriteNewLine();

            Write(JS.Vars.ASYNC_STEP + " = " + Emitter.AsyncBlock.Step + ";");
            WriteNewLine();
            Write("continue;");


            var writer = SaveWriter();

            Emitter.AsyncBlock.AddAsyncStep();
            Emitter.IgnoreBlock = foreachStatement.EmbeddedStatement;
            var startCount = Emitter.AsyncBlock.Steps.Count;

            if (foreachStatement.EmbeddedStatement is BlockStatement block)
            {
                block.AcceptChildren(Emitter);
            }
            else
            {
                foreachStatement.EmbeddedStatement.AcceptVisitor(Emitter);
            }

            IAsyncStep loopStep = null;

            if (Emitter.AsyncBlock.Steps.Count > startCount)
            {
                loopStep            = Emitter.AsyncBlock.Steps.Last();
                loopStep.JumpToStep = conditionStep.Step;
            }

            RestoreWriter(writer);

            if (!IsJumpStatementLast(Emitter.Output.ToString()))
            {
                Write(JS.Vars.ASYNC_STEP + " = " + conditionStep.Step + ";");
                WriteNewLine();
                Write("continue;");
                WriteNewLine();
            }

            PopLocals();

            WriteNewLine();
            EndBlock();
            WriteNewLine();

            var nextStep = Emitter.AsyncBlock.AddAsyncStep();

            conditionStep.JumpToStep = nextStep.Step;

            if (Emitter.JumpStatements.Count > 0)
            {
                Emitter.JumpStatements.Sort((j1, j2) => - j1.Position.CompareTo(j2.Position));
                foreach (var jump in Emitter.JumpStatements)
                {
                    jump.Output.Insert(jump.Position, jump.Break ? nextStep.Step : conditionStep.Step);
                }
            }

            Emitter.JumpStatements = jumpStatements;
        }
예제 #10
0
        protected void VisitInvocationExpression()
        {
            InvocationExpression invocationExpression = InvocationExpression;
            int pos = Emitter.Output.Length;

            if (Emitter.IsForbiddenInvocation(invocationExpression))
            {
                throw new EmitterException(invocationExpression, "This method cannot be invoked directly");
            }

            var oldValue = Emitter.ReplaceAwaiterByVar;
            var oldAsyncExpressionHandling = Emitter.AsyncExpressionHandling;

            if (Emitter.IsAsync && !Emitter.AsyncExpressionHandling)
            {
                WriteAwaiters(invocationExpression);
                Emitter.ReplaceAwaiterByVar     = true;
                Emitter.AsyncExpressionHandling = true;
            }

            Tuple <bool, bool, string> inlineInfo = Emitter.GetInlineCode(invocationExpression);
            var argsInfo = new ArgumentsInfo(Emitter, invocationExpression);

            var argsExpressions = argsInfo.ArgumentsExpressions;
            var paramsArg       = argsInfo.ParamsExpression;

            var targetResolve    = Emitter.Resolver.ResolveNode(invocationExpression);
            var csharpInvocation = targetResolve as CSharpInvocationResolveResult;
            MemberReferenceExpression targetMember = invocationExpression.Target as MemberReferenceExpression;
            bool isObjectLiteral = csharpInvocation != null && csharpInvocation.Member.DeclaringTypeDefinition != null?Emitter.Validator.IsObjectLiteral(csharpInvocation.Member.DeclaringTypeDefinition) : false;

            if (inlineInfo != null)
            {
                bool   isStaticMethod = inlineInfo.Item1;
                bool   isInlineMethod = inlineInfo.Item2;
                string inlineScript   = inlineInfo.Item3;

                if (isInlineMethod)
                {
                    if (invocationExpression.Arguments.Count > 0)
                    {
                        var code = invocationExpression.Arguments.First();

                        if (!(code is PrimitiveExpression inlineExpression))
                        {
                            throw new EmitterException(invocationExpression, "Only primitive expression can be inlined");
                        }

                        string value = inlineExpression.Value.ToString().Trim();

                        if (value.Length > 0)
                        {
                            value = InlineArgumentsBlock.ReplaceInlineArgs(this, inlineExpression.Value.ToString(), invocationExpression.Arguments.Skip(1).ToArray());
                            Write(value);

                            value = value.Trim();
                            if (value[value.Length - 1] == ';' || value.EndsWith("*/", StringComparison.InvariantCulture) || value.StartsWith("//"))
                            {
                                Emitter.SkipSemiColon = true;
                                WriteNewLine();
                            }
                        }
                        else
                        {
                            // Empty string, emit nothing.
                            Emitter.SkipSemiColon = true;
                        }

                        Emitter.ReplaceAwaiterByVar     = oldValue;
                        Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;

                        return;
                    }
                }
                else
                {
                    bool isBase = invocationExpression.Target is MemberReferenceExpression targetMemberRef && targetMemberRef.Target is BaseReferenceExpression;

                    if (!String.IsNullOrEmpty(inlineScript) && (isBase || invocationExpression.Target is IdentifierExpression))
                    {
                        argsInfo.ThisArgument = "this";
                        bool noThis = !Helpers.HasThis(inlineScript);

                        if (inlineScript.StartsWith("<self>"))
                        {
                            noThis       = false;
                            inlineScript = inlineScript.Substring(6);
                        }

                        if (!noThis)
                        {
                            Emitter.ThisRefCounter++;
                        }

                        if (!isStaticMethod && noThis)
                        {
                            WriteThis();
                            WriteDot();
                        }

                        new InlineArgumentsBlock(Emitter, argsInfo, inlineScript).Emit();
                        Emitter.ReplaceAwaiterByVar     = oldValue;
                        Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;

                        return;
                    }
                }
            }

            if (targetMember != null || isObjectLiteral)
            {
                var member = targetMember != null?Emitter.Resolver.ResolveNode(targetMember.Target) : null;

                if (targetResolve != null)
                {
                    InvocationResolveResult invocationResult;
                    bool isExtensionMethodInvocation = false;
                    if (csharpInvocation != null)
                    {
                        if (member != null && member.Type.Kind == TypeKind.Delegate && (/*csharpInvocation.Member.Name == "Invoke" || */ csharpInvocation.Member.Name == "BeginInvoke" || csharpInvocation.Member.Name == "EndInvoke") && !csharpInvocation.IsExtensionMethodInvocation)
                        {
                            throw new EmitterException(invocationExpression, "Delegate's 'Invoke' methods are not supported. Please use direct delegate invoke.");
                        }

                        if (csharpInvocation.IsExtensionMethodInvocation)
                        {
                            invocationResult            = csharpInvocation;
                            isExtensionMethodInvocation = true;
                            if (invocationResult.Member is IMethod resolvedMethod && resolvedMethod.IsExtensionMethod)
                            {
                                string inline   = Emitter.GetInline(resolvedMethod);
                                bool   isNative = IsNativeMethod(resolvedMethod);

                                if (string.IsNullOrWhiteSpace(inline) && isNative)
                                {
                                    invocationResult = null;
                                }
                            }
                        }
                        else
                        {
                            invocationResult = null;
                        }

                        if (IsEmptyPartialInvoking(csharpInvocation.Member as IMethod) || IsConditionallyRemoved(invocationExpression, csharpInvocation.Member))
                        {
                            Emitter.SkipSemiColon           = true;
                            Emitter.ReplaceAwaiterByVar     = oldValue;
                            Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;

                            return;
                        }
                    }
                    else
                    {
                        invocationResult = targetResolve as InvocationResolveResult;

                        if (invocationResult != null && (IsEmptyPartialInvoking(invocationResult.Member as IMethod) || IsConditionallyRemoved(invocationExpression, invocationResult.Member)))
                        {
                            Emitter.SkipSemiColon           = true;
                            Emitter.ReplaceAwaiterByVar     = oldValue;
                            Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;

                            return;
                        }
                    }

                    if (invocationResult == null)
                    {
                        invocationResult = Emitter.Resolver.ResolveNode(invocationExpression) as InvocationResolveResult;
                    }

                    if (invocationResult != null)
                    {
                        if (invocationResult.Member is IMethod resolvedMethod && (resolvedMethod.IsExtensionMethod || isObjectLiteral))
                        {
                            string inline   = Emitter.GetInline(resolvedMethod);
                            bool   isNative = IsNativeMethod(resolvedMethod);

                            if (isExtensionMethodInvocation || isObjectLiteral)
                            {
                                if (!string.IsNullOrWhiteSpace(inline))
                                {
                                    Write("");
                                    StringBuilder savedBuilder = Emitter.Output;
                                    Emitter.Output = new StringBuilder();
                                    WriteThisExtension(invocationExpression.Target);
                                    argsInfo.ThisArgument = Emitter.Output.ToString();
                                    Emitter.Output        = savedBuilder;
                                    new InlineArgumentsBlock(Emitter, argsInfo, inline).Emit();
                                }
                                else if (!isNative)
                                {
                                    var overloads = OverloadsCollection.Create(Emitter, resolvedMethod);

                                    if (isObjectLiteral && !resolvedMethod.IsStatic && resolvedMethod.DeclaringType.Kind == TypeKind.Interface)
                                    {
                                        Write("H5.getType(");
                                        WriteThisExtension(invocationExpression.Target);
                                        Write(").");
                                    }
                                    else
                                    {
                                        string name = H5Types.ToJsName(resolvedMethod.DeclaringType, Emitter, ignoreLiteralName: false) + ".";
                                        Write(name);
                                    }

                                    if (isObjectLiteral && !resolvedMethod.IsStatic)
                                    {
                                        Write(JS.Fields.PROTOTYPE + "." + overloads.GetOverloadName() + "." + JS.Funcs.CALL);
                                    }
                                    else
                                    {
                                        Write(overloads.GetOverloadName());
                                    }

                                    var isIgnoreClass = resolvedMethod.DeclaringTypeDefinition != null && Emitter.Validator.IsExternalType(resolvedMethod.DeclaringTypeDefinition);
                                    int openPos       = Emitter.Output.Length;
                                    WriteOpenParentheses();

                                    Emitter.Comma = false;

                                    if (isObjectLiteral && !resolvedMethod.IsStatic)
                                    {
                                        WriteThisExtension(invocationExpression.Target);
                                        Emitter.Comma = true;
                                    }

                                    if (!isIgnoreClass && !Helpers.IsIgnoreGeneric(resolvedMethod, Emitter) && argsInfo.HasTypeArguments)
                                    {
                                        EnsureComma(false);
                                        new TypeExpressionListBlock(Emitter, argsInfo.TypeArguments).Emit();
                                        Emitter.Comma = true;
                                    }

                                    if (!isObjectLiteral && resolvedMethod.IsStatic)
                                    {
                                        EnsureComma(false);
                                        WriteThisExtension(invocationExpression.Target);
                                        Emitter.Comma = true;
                                    }

                                    if (invocationExpression.Arguments.Count > 0)
                                    {
                                        EnsureComma(false);
                                    }

                                    new ExpressionListBlock(Emitter, argsExpressions, paramsArg, invocationExpression, openPos).Emit();

                                    WriteCloseParentheses();
                                }

                                if (!string.IsNullOrWhiteSpace(inline) || !isNative)
                                {
                                    Emitter.ReplaceAwaiterByVar     = oldValue;
                                    Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;

                                    return;
                                }
                            }
                            else if (isNative)
                            {
                                if (!string.IsNullOrWhiteSpace(inline))
                                {
                                    Write("");
                                    StringBuilder savedBuilder = Emitter.Output;
                                    Emitter.Output = new StringBuilder();
                                    WriteThisExtension(invocationExpression.Target);
                                    argsInfo.ThisArgument = Emitter.Output.ToString();
                                    Emitter.Output        = savedBuilder;
                                    new InlineArgumentsBlock(Emitter, argsInfo, inline).Emit();
                                }
                                else
                                {
                                    argsExpressions.First().AcceptVisitor(Emitter);
                                    WriteDot();
                                    string name = Emitter.GetEntityName(resolvedMethod);
                                    Write(name);
                                    int openPos = Emitter.Output.Length;
                                    WriteOpenParentheses();
                                    new ExpressionListBlock(Emitter, argsExpressions.Skip(1), paramsArg, invocationExpression, openPos).Emit();
                                    WriteCloseParentheses();
                                }

                                Emitter.ReplaceAwaiterByVar     = oldValue;
                                Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;

                                return;
                            }
                        }
                    }
                }
            }

            var proto = false;

            if (targetMember != null && targetMember.Target is BaseReferenceExpression)
            {
                if (Emitter.Resolver.ResolveNode(targetMember) is MemberResolveResult rr)
                {
                    proto = rr.IsVirtualCall;

                    /*var method = rr.Member as IMethod;
                     * if (method != null && method.IsVirtual)
                     * {
                     *  proto = true;
                     * }
                     * else
                     * {
                     *  var prop = rr.Member as IProperty;
                     *
                     *  if (prop != null && prop.IsVirtual)
                     *  {
                     *      proto = true;
                     *  }
                     * }*/
                }
            }

            if (proto)
            {
                var baseType = Emitter.GetBaseMethodOwnerTypeDefinition(targetMember.MemberName, targetMember.TypeArguments.Count);

                bool isIgnore = Emitter.Validator.IsExternalType(baseType);

                bool needComma = false;

                var resolveResult = Emitter.Resolver.ResolveNode(targetMember);

                string name = null;

                if (Emitter.TypeInfo.GetBaseTypes(Emitter).Any())
                {
                    name = H5Types.ToJsName(Emitter.TypeInfo.GetBaseClass(Emitter), Emitter);
                }
                else
                {
                    name = H5Types.ToJsName(baseType, Emitter);
                }

                string baseMethod;
                bool   isIgnoreGeneric = false;
                if (resolveResult is MemberResolveResult memberResult)
                {
                    baseMethod      = OverloadsCollection.Create(Emitter, memberResult.Member).GetOverloadName();
                    isIgnoreGeneric = Helpers.IsIgnoreGeneric(memberResult.Member, Emitter);
                }
                else
                {
                    baseMethod = targetMember.MemberName;
                    baseMethod = Object.Net.Utilities.StringUtils.ToLowerCamelCase(baseMethod);
                }

                Write(name, "." + JS.Fields.PROTOTYPE + ".", baseMethod);

                WriteCall();
                WriteOpenParentheses();
                WriteThis();
                Emitter.Comma = true;
                if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments)
                {
                    new TypeExpressionListBlock(Emitter, argsInfo.TypeArguments).Emit();
                }

                needComma = false;

                foreach (var arg in argsExpressions)
                {
                    if (arg == null)
                    {
                        continue;
                    }

                    EnsureComma(false);

                    if (needComma)
                    {
                        WriteComma();
                    }

                    needComma = true;
                    arg.AcceptVisitor(Emitter);
                }
                Emitter.Comma = false;
                WriteCloseParentheses();
            }
            else
            {
                IMethod method = null;

                if (Emitter.Resolver.ResolveNode(invocationExpression) is DynamicInvocationResolveResult dynamicResolveResult)
                {
                    if (dynamicResolveResult.Target is MethodGroupResolveResult group && group.Methods.Count() > 1)
                    {
                        method = group.Methods.FirstOrDefault(m =>
                        {
                            if (dynamicResolveResult.Arguments.Count != m.Parameters.Count)
                            {
                                return(false);
                            }

                            for (int i = 0; i < m.Parameters.Count; i++)
                            {
                                var argType = dynamicResolveResult.Arguments[i].Type;

                                if (argType.Kind == TypeKind.Dynamic)
                                {
                                    argType = Emitter.Resolver.Compilation.FindType(TypeCode.Object);
                                }

                                if (!m.Parameters[i].Type.Equals(argType))
                                {
                                    return(false);
                                }
                            }

                            return(true);
                        });

                        if (method == null)
                        {
                            throw new EmitterException(invocationExpression, Constants.Messages.Exceptions.DYNAMIC_INVOCATION_TOO_MANY_OVERLOADS);
                        }
                    }
                }
                else
                {
                    var targetResolveResult = Emitter.Resolver.ResolveNode(invocationExpression.Target);

                    if (targetResolveResult is MemberResolveResult invocationResolveResult)
                    {
                        method = invocationResolveResult.Member as IMethod;
                    }
                }

                if (IsEmptyPartialInvoking(method) || IsConditionallyRemoved(invocationExpression, method))
                {
                    Emitter.SkipSemiColon           = true;
                    Emitter.ReplaceAwaiterByVar     = oldValue;
                    Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;
                    return;
                }

                bool isIgnore = method != null && method.DeclaringTypeDefinition != null && Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition);

                bool needExpand = false;
                if (method != null)
                {
                    string paramsName = null;

                    var paramsParam = method.Parameters.FirstOrDefault(p => p.IsParams);
                    if (paramsParam != null)
                    {
                        paramsName = paramsParam.Name;
                    }

                    if (paramsName != null)
                    {
                        if (csharpInvocation != null && !csharpInvocation.IsExpandedForm)
                        {
                            needExpand = true;
                        }
                    }
                }

                int count = Emitter.Writers.Count;
                invocationExpression.Target.AcceptVisitor(Emitter);

                if (Emitter.Writers.Count > count)
                {
                    var writer = Emitter.Writers.Pop();

                    if (method != null && method.IsExtensionMethod)
                    {
                        StringBuilder savedBuilder = Emitter.Output;
                        Emitter.Output = new StringBuilder();
                        WriteThisExtension(invocationExpression.Target);
                        argsInfo.ThisArgument = Emitter.Output.ToString();
                        Emitter.Output        = savedBuilder;
                    }
                    else if (writer.ThisArg != null)
                    {
                        argsInfo.ThisArgument = writer.ThisArg;
                    }

                    new InlineArgumentsBlock(Emitter, argsInfo, writer.InlineCode)
                    {
                        IgnoreRange = writer.IgnoreRange
                    }.Emit();
                    var result = Emitter.Output.ToString();
                    Emitter.Output    = writer.Output;
                    Emitter.IsNewLine = writer.IsNewLine;
                    Write(result);

                    if (writer.Callback != null)
                    {
                        writer.Callback.Invoke();
                    }
                }
                else
                {
                    if (needExpand && isIgnore)
                    {
                        Write("." + JS.Funcs.APPLY);
                    }
                    int openPos = Emitter.Output.Length;
                    WriteOpenParentheses();

                    bool isIgnoreGeneric = false;

                    if (targetResolve is InvocationResolveResult invocationResult)
                    {
                        isIgnoreGeneric = Helpers.IsIgnoreGeneric(invocationResult.Member, Emitter);
                    }

                    bool isWrapRest = false;

                    if (needExpand && isIgnore)
                    {
                        StringBuilder savedBuilder = Emitter.Output;
                        Emitter.Output = new StringBuilder();
                        WriteThisExtension(invocationExpression.Target);
                        var thisArg = Emitter.Output.ToString();
                        Emitter.Output = savedBuilder;

                        Write(thisArg);

                        Emitter.Comma = true;

                        if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments)
                        {
                            new TypeExpressionListBlock(Emitter, argsInfo.TypeArguments).Emit();
                        }

                        EnsureComma(false);

                        if (argsExpressions.Length > 1)
                        {
                            WriteOpenBracket();
                            var elb = new ExpressionListBlock(Emitter, argsExpressions.Take(argsExpressions.Length - 1).ToArray(), paramsArg, invocationExpression, openPos);
                            elb.IgnoreExpandParams = true;
                            elb.Emit();
                            WriteCloseBracket();
                            Write(".concat(");
                            elb = new ExpressionListBlock(Emitter, new Expression[] { argsExpressions[argsExpressions.Length - 1] }, paramsArg, invocationExpression, openPos);
                            elb.IgnoreExpandParams = true;
                            elb.Emit();
                            Write(")");
                        }
                        else
                        {
                            new ExpressionListBlock(Emitter, argsExpressions, paramsArg, invocationExpression, -1).Emit();
                        }
                    }
                    else
                    {
                        if (method != null && method.Attributes.Any(a => a.AttributeType.FullName == "H5.WrapRestAttribute"))
                        {
                            isWrapRest = true;
                        }

                        Emitter.Comma = false;
                        if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments)
                        {
                            new TypeExpressionListBlock(Emitter, argsInfo.TypeArguments).Emit();
                        }

                        if (invocationExpression.Arguments.Count > 0 || argsExpressions.Length > 0 && !argsExpressions.All(expr => expr == null))
                        {
                            EnsureComma(false);
                        }

                        new ExpressionListBlock(Emitter, argsExpressions, paramsArg, invocationExpression, openPos).Emit();
                    }


                    if (isWrapRest)
                    {
                        EnsureComma(false);
                        Write("H5.fn.bind(this, function () ");
                        BeginBlock();
                        Emitter.WrapRestCounter++;
                        Emitter.SkipSemiColon = true;
                    }
                    else
                    {
                        Emitter.Comma = false;
                        WriteCloseParentheses();
                    }
                }
            }

            if (targetResolve is InvocationResolveResult irr && irr.Member.MemberDefinition != null && irr.Member.MemberDefinition.ReturnType.Kind == TypeKind.TypeParameter)
            {
                Helpers.CheckValueTypeClone(Emitter.Resolver.ResolveNode(invocationExpression), invocationExpression, this, pos);
            }

            Emitter.ReplaceAwaiterByVar     = oldValue;
            Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;
        }
예제 #11
0
        public virtual void EmitPropertyMethod(PropertyDeclaration propertyDeclaration, Accessor accessor, IMethod method, bool setter, bool isObjectLiteral)
        {
            if ((!accessor.IsNull || method != null && Helpers.IsScript(method)) && Emitter.GetInline(accessor) == null)
            {
                EnsureComma();

                ResetLocals();

                var prevMap      = BuildLocalsMap();
                var prevNamesMap = BuildLocalsNamesMap();

                if (setter)
                {
                    AddLocals(new ParameterDeclaration[] { new ParameterDeclaration {
                                                               Name = "value"
                                                           } }, accessor.Body);
                }
                else
                {
                    AddLocals(new ParameterDeclaration[0], accessor.Body);
                }

                //XmlToJsDoc.EmitComment(this, this.PropertyDeclaration);

                Write(setter ? JS.Funcs.Property.SET : JS.Funcs.Property.GET);

                WriteColon();
                WriteFunction();

                var m_rr = (MemberResolveResult)Emitter.Resolver.ResolveNode(propertyDeclaration);

                WriteOpenParentheses();
                Write(setter ? "value" : "");
                WriteCloseParentheses();
                WriteSpace();

                var script = Emitter.GetScript(accessor);

                if (script == null)
                {
                    if (YieldBlock.HasYield(accessor.Body))
                    {
                        new GeneratorBlock(Emitter, accessor).Emit();
                    }
                    else
                    {
                        accessor.Body.AcceptVisitor(Emitter);
                    }
                }
                else
                {
                    BeginBlock();

                    WriteLines(script);

                    EndBlock();
                }

                ClearLocalsMap(prevMap);
                ClearLocalsNamesMap(prevNamesMap);
                Emitter.Comma = true;
            }
        }
예제 #12
0
        public void Translate(CancellationToken cancellationToken)
        {
            using (new Measure(Logger, "Translating assembly"))
            {
                var config = AssemblyInfo;

                Dictionary <string, string> discoveredAssemblyPaths = null;

                if (Rebuild)
                {
                    Logger.ZLogInformation("Rebuilding assembly on path {0}", AssemblyLocation);
                    discoveredAssemblyPaths = BuildAssembly(cancellationToken);
                }
                else if (!File.Exists(AssemblyLocation))
                {
                    Logger.ZLogInformation("Building assembly on path {0}", AssemblyLocation);
                    discoveredAssemblyPaths = BuildAssembly(cancellationToken);
                }

                var references = InspectReferences(discoveredAssemblyPaths);
                References = references;

                LogProductInfo();

                if (!string.IsNullOrWhiteSpace(config.BeforeBuild))
                {
                    try
                    {
                        using (new Measure(Logger, $"Running BeforeBuild event {config.BeforeBuild}"))
                        {
                            RunEvent(config.BeforeBuild);
                        }
                    }
                    catch (Exception exc)
                    {
                        Logger.ZLogError(exc, "Error running BeforeBuild event {0}", config.BeforeBuild);
                        throw new TranslatorException($"Error: Unable to run beforeBuild event command: {exc.Message}\nStack trace:\n{exc.StackTrace}");
                    }
                }

                BuildSyntaxTree(cancellationToken);

                var resolver = new MemberResolver(ParsedSourceFiles, Emitter.ToAssemblyReferences(references), AssemblyDefinition);
                resolver = Preconvert(resolver, config, cancellationToken);

                InspectTypes(resolver, config);

                resolver.CanFreeze = true;
                var emitter = CreateEmitter(resolver, cancellationToken);

                if (!AssemblyInfo.OverflowMode.HasValue)
                {
                    AssemblyInfo.OverflowMode = OverflowMode;
                }

                emitter.Translator   = this;
                emitter.AssemblyInfo = AssemblyInfo;
                emitter.References   = references;
                emitter.SourceFiles  = SourceFiles;
                emitter.InitialLevel = 1;

                if (AssemblyInfo.Module != null)
                {
                    AssemblyInfo.Module.Emitter = emitter;
                }

                foreach (var td in TypeInfoDefinitions)
                {
                    if (td.Value.Module != null)
                    {
                        td.Value.Module.Emitter = emitter;
                    }
                }

                SortReferences();

                AddMainOutputs(emitter.Emit());
                EmitterOutputs = emitter.Outputs;
            }
        }
예제 #13
0
        protected void VisitUnaryOperatorExpression()
        {
            var  unaryOperatorExpression = UnaryOperatorExpression;
            var  oldType              = Emitter.UnaryOperatorType;
            var  oldAccessor          = Emitter.IsUnaryAccessor;
            var  resolveOperator      = Emitter.Resolver.ResolveNode(unaryOperatorExpression);
            var  expectedType         = Emitter.Resolver.Resolver.GetExpectedType(unaryOperatorExpression);
            bool isDecimalExpected    = Helpers.IsDecimalType(expectedType, Emitter.Resolver);
            bool isDecimal            = Helpers.IsDecimalType(resolveOperator.Type, Emitter.Resolver);
            bool isLongExpected       = Helpers.Is64Type(expectedType, Emitter.Resolver);
            bool isLong               = Helpers.Is64Type(resolveOperator.Type, Emitter.Resolver);
            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
            int count = Emitter.Writers.Count;

            if (resolveOperator is ConstantResolveResult crr)
            {
                object constantValue = crr.ConstantValue;

                if (unaryOperatorExpression.Operator == UnaryOperatorType.Minus && SyntaxHelper.IsNumeric(constantValue.GetType()) && Convert.ToDouble(constantValue) == 0)
                {
                    Write("-");
                }

                WriteScript(constantValue);
                return;
            }

            if (Helpers.IsDecimalType(resolveOperator.Type, Emitter.Resolver))
            {
                isDecimal         = true;
                isDecimalExpected = true;
            }

            if (isDecimal && isDecimalExpected && unaryOperatorExpression.Operator != UnaryOperatorType.Await)
            {
                HandleDecimal(resolveOperator);
                return;
            }

            if (ResolveOperator(unaryOperatorExpression, orr))
            {
                return;
            }

            if (Helpers.Is64Type(resolveOperator.Type, Emitter.Resolver))
            {
                isLong         = true;
                isLongExpected = true;
            }

            if (isLong && isLongExpected && unaryOperatorExpression.Operator != UnaryOperatorType.Await)
            {
                HandleDecimal(resolveOperator, true);
                return;
            }

            if (ResolveOperator(unaryOperatorExpression, orr))
            {
                return;
            }

            var  op = unaryOperatorExpression.Operator;
            var  argResolverResult = Emitter.Resolver.ResolveNode(unaryOperatorExpression.Expression);
            bool nullable          = NullableType.IsNullable(argResolverResult.Type);

            if (nullable)
            {
                if (op != UnaryOperatorType.Increment &&
                    op != UnaryOperatorType.Decrement &&
                    op != UnaryOperatorType.PostIncrement &&
                    op != UnaryOperatorType.PostDecrement)
                {
                    Write(JS.Types.SYSTEM_NULLABLE + ".");
                }
            }

            bool isAccessor = false;


            if (argResolverResult is MemberResolveResult memberArgResolverResult)
            {
                if (memberArgResolverResult.Member is IProperty prop)
                {
                    var isIgnore   = memberArgResolverResult.Member.DeclaringTypeDefinition != null && Emitter.Validator.IsExternalType(memberArgResolverResult.Member.DeclaringTypeDefinition);
                    var inlineAttr = prop.Getter != null?Emitter.GetAttribute(prop.Getter.Attributes, Translator.H5_ASSEMBLY + ".TemplateAttribute") : null;

                    var ignoreAccessor     = prop.Getter != null && Emitter.Validator.IsExternalType(prop.Getter);
                    var isAccessorsIndexer = Emitter.Validator.IsAccessorsIndexer(memberArgResolverResult.Member);

                    isAccessor = prop.IsIndexer;

                    if (inlineAttr == null && (isIgnore || ignoreAccessor) && !isAccessorsIndexer)
                    {
                        isAccessor = false;
                    }
                }
            }
            else if (argResolverResult is ArrayAccessResolveResult)
            {
                isAccessor = ((ArrayAccessResolveResult)argResolverResult).Indexes.Count > 1;
            }

            Emitter.UnaryOperatorType = op;

            if ((isAccessor) &&
                (op == UnaryOperatorType.Increment ||
                 op == UnaryOperatorType.Decrement ||
                 op == UnaryOperatorType.PostIncrement ||
                 op == UnaryOperatorType.PostDecrement))
            {
                Emitter.IsUnaryAccessor = true;

                if (nullable)
                {
                    Write(JS.Funcs.H5_HASVALUE);
                    WriteOpenParentheses();
                    Emitter.IsUnaryAccessor = false;
                    unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    Write(") ? ");
                    Emitter.IsUnaryAccessor = true;
                    unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    Write(" : null)");
                }
                else
                {
                    unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                }

                Emitter.IsUnaryAccessor = oldAccessor;

                if (Emitter.Writers.Count > count)
                {
                    PopWriter();
                }
            }
            else
            {
                switch (op)
                {
                case UnaryOperatorType.BitNot:
                    if (nullable)
                    {
                        Write("bnot(");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(")");
                    }
                    else
                    {
                        Write("~");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    }
                    break;

                case UnaryOperatorType.Decrement:
                    if (nullable)
                    {
                        Write(JS.Funcs.H5_HASVALUE);
                        WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(") ? ");
                        Write("--");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(" : null)");
                    }
                    else
                    {
                        Write("--");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    }
                    break;

                case UnaryOperatorType.Increment:
                    if (nullable)
                    {
                        Write(JS.Funcs.H5_HASVALUE);
                        WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(") ? ");
                        Write("++");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(" : null)");
                    }
                    else
                    {
                        Write("++");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    }
                    break;

                case UnaryOperatorType.Minus:
                    if (nullable)
                    {
                        Write("neg(");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(")");
                    }
                    else
                    {
                        Write("-");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    }
                    break;

                case UnaryOperatorType.Not:
                    if (nullable)
                    {
                        Write("not(");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(")");
                    }
                    else
                    {
                        Write("!");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    }
                    break;

                case UnaryOperatorType.Plus:
                    if (nullable)
                    {
                        Write("pos(");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(")");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                    }

                    break;

                case UnaryOperatorType.PostDecrement:
                    if (nullable)
                    {
                        Write(JS.Funcs.H5_HASVALUE);
                        WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(") ? ");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write("--");
                        Write(" : null)");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write("--");
                    }
                    break;

                case UnaryOperatorType.PostIncrement:
                    if (nullable)
                    {
                        Write(JS.Funcs.H5_HASVALUE);
                        WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write(") ? ");
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write("++");
                        Write(" : null)");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(Emitter);
                        Write("++");
                    }
                    break;

                case UnaryOperatorType.Await:
                    if (Emitter.ReplaceAwaiterByVar)
                    {
                        var index = Array.IndexOf(Emitter.AsyncBlock.AwaitExpressions, unaryOperatorExpression.Expression) + 1;
                        Write(JS.Vars.ASYNC_TASK_RESULT + index);
                    }
                    else
                    {
                        var oldValue = Emitter.ReplaceAwaiterByVar;
                        var oldAsyncExpressionHandling = Emitter.AsyncExpressionHandling;

                        if (Emitter.IsAsync && !Emitter.AsyncExpressionHandling)
                        {
                            WriteAwaiters(unaryOperatorExpression.Expression);
                            Emitter.ReplaceAwaiterByVar     = true;
                            Emitter.AsyncExpressionHandling = true;
                        }

                        WriteAwaiter(unaryOperatorExpression.Expression);

                        Emitter.ReplaceAwaiterByVar     = oldValue;
                        Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;
                    }
                    break;

                default:
                    throw new EmitterException(unaryOperatorExpression, "Unsupported unary operator: " + unaryOperatorExpression.Operator.ToString());
                }

                if (Emitter.Writers.Count > count)
                {
                    PopWriter();
                }
            }

            Emitter.UnaryOperatorType = oldType;
        }
예제 #14
0
        protected virtual void VisitVariableDeclarationStatement()
        {
            bool needVar      = true;
            bool needComma    = false;
            bool addSemicolon = !Emitter.IsAsync;

            var oldSemiColon            = Emitter.EnableSemicolon;
            var asyncExpressionHandling = Emitter.AsyncExpressionHandling;

            foreach (var variable in VariableDeclarationStatement.Variables)
            {
                WriteSourceMapName(variable.Name);

                var varName = AddLocal(variable.Name, variable, VariableDeclarationStatement.Type);
                lastVarName = varName;

                if (variable.Initializer != null && !variable.Initializer.IsNull && variable.Initializer.ToString().Contains(JS.Vars.FIX_ARGUMENT_NAME))
                {
                    continue;
                }

                if (needVar)
                {
                    WriteVar();
                    needVar = false;
                }

                bool isReferenceLocal = false;

                if (Emitter.LocalsMap != null && Emitter.Resolver.ResolveNode(variable) is LocalResolveResult lrr && Emitter.LocalsMap.ContainsKey(lrr.Variable))
                {
                    isReferenceLocal = Emitter.LocalsMap[lrr.Variable].EndsWith(".v");
                }

                lastIsReferenceLocal = isReferenceLocal;
                var hasInitializer = !variable.Initializer.IsNull;

                if (variable.Initializer.IsNull && !VariableDeclarationStatement.Type.IsVar())
                {
                    var typeDef = Emitter.GetTypeDefinition(VariableDeclarationStatement.Type, true);

                    if (typeDef != null && typeDef.IsValueType && !Emitter.Validator.IsExternalType(typeDef))
                    {
                        hasInitializer = true;
                    }
                }

                if ((!Emitter.IsAsync || hasInitializer || isReferenceLocal) && needComma)
                {
                    if (Emitter.IsAsync)
                    {
                        WriteSemiColon(true);
                    }
                    else
                    {
                        WriteComma();
                    }
                }

                needComma = true;

                WriteAwaiters(variable.Initializer);

                if (!Emitter.IsAsync || hasInitializer || isReferenceLocal)
                {
                    Write(varName);
                }

                if (hasInitializer)
                {
                    addSemicolon = true;
                    Write(" = ");

                    if (isReferenceLocal)
                    {
                        Write("{ v : ");
                    }

                    var oldValue = Emitter.ReplaceAwaiterByVar;
                    Emitter.ReplaceAwaiterByVar = true;

                    if (!variable.Initializer.IsNull)
                    {
                        variable.Initializer.AcceptVisitor(Emitter);
                    }
                    else
                    {
                        var typerr    = Emitter.Resolver.ResolveNode(VariableDeclarationStatement.Type).Type;
                        var isGeneric = typerr.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(typerr, Emitter);
                        Write(string.Concat("new ", isGeneric ? "(" : "", H5Types.ToJsName(VariableDeclarationStatement.Type, Emitter), isGeneric ? ")" : "", "()"));
                    }
                    Emitter.ReplaceAwaiterByVar = oldValue;

                    if (isReferenceLocal)
                    {
                        Write(" }");
                    }
                }
                else if (isReferenceLocal)
                {
                    addSemicolon = true;
                    Write(" = { }");
                }
            }

            Emitter.AsyncExpressionHandling = asyncExpressionHandling;

            if (Emitter.EnableSemicolon && !needVar && addSemicolon)
            {
                WriteSemiColon(true);
            }

            if (oldSemiColon)
            {
                Emitter.EnableSemicolon = true;
            }
        }
예제 #15
0
        private void BuildDynamicArgumentsList(DynamicInvocationResolveResult drr, IList <Expression> arguments)
        {
            Expression paramsArg    = null;
            string     paramArgName = null;
            IMethod    method       = null;

            if (drr.Target is MethodGroupResolveResult group && group.Methods.Count() > 1)
            {
                method = group.Methods.FirstOrDefault(m =>
                {
                    if (drr.Arguments.Count != m.Parameters.Count)
                    {
                        return(false);
                    }

                    for (int i = 0; i < m.Parameters.Count; i++)
                    {
                        var argType = drr.Arguments[i].Type;

                        if (argType.Kind == TypeKind.Dynamic)
                        {
                            argType = Emitter.Resolver.Compilation.FindType(TypeCode.Object);
                        }

                        if (!m.Parameters[i].Type.Equals(argType))
                        {
                            return(false);
                        }
                    }

                    return(true);
                });

                if (method == null)
                {
                    throw new EmitterException(Expression, Constants.Messages.Exceptions.DYNAMIC_INVOCATION_TOO_MANY_OVERLOADS);
                }
            }

            if (method != null)
            {
                var member     = method;
                var parameters = method.Parameters;

                Expression[] result            = new Expression[parameters.Count];
                string[]     names             = new string[result.Length];
                bool         named             = false;
                int          i                 = 0;
                bool         isInterfaceMember = false;

                if (member != null)
                {
                    var inlineStr = Emitter.GetInline(member);
                    named = !string.IsNullOrEmpty(inlineStr);

                    isInterfaceMember = member.DeclaringTypeDefinition != null &&
                                        member.DeclaringTypeDefinition.Kind == TypeKind.Interface;
                }

                foreach (var arg in arguments)
                {
                    if (arg is NamedArgumentExpression namedArg)
                    {
                        var namedParam = parameters.First(p => p.Name == namedArg.Name);
                        var index      = parameters.IndexOf(namedParam);

                        result[index] = namedArg.Expression;
                        names[index]  = namedArg.Name;
                        named         = true;

                        if (paramsArg == null && (parameters.Count > i) && parameters[i].IsParams)
                        {
                            if (member.DeclaringTypeDefinition == null || !Emitter.Validator.IsExternalType(member.DeclaringTypeDefinition))
                            {
                                paramsArg = namedArg.Expression;
                            }

                            paramArgName = namedArg.Name;
                        }
                    }
                    else
                    {
                        if (paramsArg == null && (parameters.Count > i) && parameters[i].IsParams)
                        {
                            if (member.DeclaringTypeDefinition == null || !Emitter.Validator.IsExternalType(member.DeclaringTypeDefinition))
                            {
                                paramsArg = arg;
                            }

                            paramArgName = parameters[i].Name;
                        }

                        if (i >= result.Length)
                        {
                            var list = result.ToList();
                            list.AddRange(new Expression[arguments.Count - i]);

                            var strList = names.ToList();
                            strList.AddRange(new string[arguments.Count - i]);

                            result = list.ToArray();
                            names  = strList.ToArray();
                        }

                        result[i] = arg;
                        names[i]  = i < parameters.Count ? parameters[i].Name : paramArgName;
                    }

                    i++;
                }

                for (i = 0; i < result.Length; i++)
                {
                    if (result[i] == null)
                    {
                        var    p = parameters[i];
                        object t = null;
                        if (p.Type.Kind == TypeKind.Enum)
                        {
                            t = Helpers.GetEnumValue(Emitter, p.Type, p.ConstantValue);
                        }
                        else
                        {
                            t = p.ConstantValue;
                        }
                        if ((named || isInterfaceMember) && !p.IsParams)
                        {
                            if (t == null)
                            {
                                result[i] = new PrimitiveExpression(new RawValue("void 0"));
                            }
                            else
                            {
                                result[i] = new PrimitiveExpression(t);
                            }
                        }

                        names[i] = parameters[i].Name;
                    }
                }

                ArgumentsExpressions = result;
                ArgumentsNames       = names;
                ParamsExpression     = paramsArg;
                NamedExpressions     = CreateNamedExpressions(names, result);
            }
            else
            {
                ArgumentsExpressions = arguments.ToArray();
            }
        }
예제 #16
0
        protected void VisitObjectCreateExpression()
        {
            ObjectCreateExpression objectCreateExpression = ObjectCreateExpression;

            var resolveResult = Emitter.Resolver.ResolveNode(objectCreateExpression.Type) as TypeResolveResult;

            if (resolveResult != null && resolveResult.Type.Kind == TypeKind.Enum)
            {
                Write("(0)");
                return;
            }

            bool isTypeParam             = resolveResult != null && resolveResult.Type.Kind == TypeKind.TypeParameter;
            var  invocationResolveResult = Emitter.Resolver.ResolveNode(objectCreateExpression) as InvocationResolveResult;
            var  hasInitializer          = !objectCreateExpression.Initializer.IsNull && objectCreateExpression.Initializer.Elements.Count > 0;

            if (isTypeParam && invocationResolveResult != null && invocationResolveResult.Member.Parameters.Count == 0 && !hasInitializer)
            {
                Write(JS.Funcs.H5_CREATEINSTANCE);
                WriteOpenParentheses();
                Write(resolveResult.Type.Name);
                WriteCloseParentheses();

                return;
            }

            var type            = isTypeParam ? null : Emitter.GetTypeDefinition(objectCreateExpression.Type);
            var isObjectLiteral = type != null && Emitter.Validator.IsObjectLiteral(type);

            if (type != null && type.BaseType != null && type.BaseType.FullName == "System.MulticastDelegate")
            {
                bool wrap = false;
                if (objectCreateExpression.Parent is InvocationExpression parent && parent.Target == objectCreateExpression)
                {
                    wrap = true;
                }

                if (wrap)
                {
                    WriteOpenParentheses();
                }

                Write("H5.fn.$build([");
                objectCreateExpression.Arguments.First().AcceptVisitor(Emitter);
                Write("])");

                if (wrap)
                {
                    WriteCloseParentheses();
                }
                return;
            }

            var argsInfo        = new ArgumentsInfo(Emitter, objectCreateExpression);
            var argsExpressions = argsInfo.ArgumentsExpressions;
            var paramsArg       = argsInfo.ParamsExpression;

            string inlineCode = null;

            if (invocationResolveResult != null)
            {
                if (invocationResolveResult.Member.DeclaringType.Kind == TypeKind.Struct && objectCreateExpression.Arguments.Count == 0)
                {
                    var ctors   = invocationResolveResult.Member.DeclaringType.GetConstructors(c => c.Parameters.Count == 1);
                    var defCtor = ctors.FirstOrDefault(c => c.Parameters.First().Type.FullName == "System.Runtime.CompilerServices.DummyTypeUsedToAddAttributeToDefaultValueTypeConstructor");

                    if (defCtor != null)
                    {
                        inlineCode = Emitter.GetInline(defCtor);
                    }
                }

                if (inlineCode == null)
                {
                    inlineCode = Emitter.GetInline(invocationResolveResult.Member);
                }
            }

            var customCtor = isTypeParam ? "" : (Emitter.Validator.GetCustomConstructor(type) ?? "");

            AstNodeCollection <Expression> elements = null;

            if (hasInitializer)
            {
                elements = objectCreateExpression.Initializer.Elements;
            }

            var isPlainObjectCtor = Regex.Match(customCtor, @"\s*\{\s*\}\s*").Success;
            var isPlainMode       = type != null && Emitter.Validator.GetObjectCreateMode(type) == 0;

            if (inlineCode == null && isPlainObjectCtor && isPlainMode)
            {
                WriteOpenBrace();
                WriteSpace();
                var pos = Emitter.Output.Length;

                WriteObjectInitializer(objectCreateExpression.Initializer.Elements, type, invocationResolveResult, false);

                if (pos < Emitter.Output.Length)
                {
                    WriteSpace();
                }

                WriteCloseBrace();
            }
            else
            {
                string tempVar = null;
                if (hasInitializer)
                {
                    tempVar = GetTempVarName();
                    WriteOpenParentheses();
                    Write(tempVar);
                    Write(" = ");
                }

                if (inlineCode != null)
                {
                    new InlineArgumentsBlock(Emitter, argsInfo, inlineCode).Emit();
                }
                else
                {
                    var  ctorMember   = ((InvocationResolveResult)Emitter.Resolver.ResolveNode(objectCreateExpression)).Member;
                    var  expandParams = ctorMember.Attributes.Any(a => a.AttributeType.FullName == "H5.ExpandParamsAttribute");
                    bool applyCtor    = false;

                    if (expandParams)
                    {
                        var ctor_rr = Emitter.Resolver.ResolveNode(paramsArg);

                        if (ctor_rr.Type.Kind == TypeKind.Array && !(paramsArg is ArrayCreateExpression) && objectCreateExpression.Arguments.Last() == paramsArg)
                        {
                            Write(JS.Types.H5.Reflection.APPLYCONSTRUCTOR + "(");
                            applyCtor = true;
                        }
                    }

                    if (String.IsNullOrEmpty(customCtor) || (isObjectLiteral && isPlainObjectCtor))
                    {
                        if (!applyCtor && !isObjectLiteral)
                        {
                            WriteNew();
                        }

                        var typerr    = Emitter.Resolver.ResolveNode(objectCreateExpression.Type).Type;
                        var td        = typerr.GetDefinition();
                        var isGeneric = typerr.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(typerr, Emitter) || td != null && Validator.IsVirtualTypeStatic(td);

                        if (isGeneric && !applyCtor)
                        {
                            WriteOpenParentheses();
                        }

                        objectCreateExpression.Type.AcceptVisitor(Emitter);

                        if (isGeneric && !applyCtor)
                        {
                            WriteCloseParentheses();
                        }
                    }
                    else
                    {
                        Write(customCtor);
                    }

                    if (!isTypeParam && type.Methods.Count(m => m.IsConstructor && !m.IsStatic) > (type.IsValueType || isObjectLiteral ? 0 : 1))
                    {
                        var member = ((InvocationResolveResult)Emitter.Resolver.ResolveNode(objectCreateExpression)).Member;
                        if (!Emitter.Validator.IsExternalType(type) || member.Attributes.Any(a => a.AttributeType.FullName == "H5.NameAttribute"))
                        {
                            WriteDot();
                            var name = OverloadsCollection.Create(Emitter, member).GetOverloadName();
                            Write(name);
                        }
                    }

                    if (applyCtor)
                    {
                        Write(", ");
                    }
                    else
                    {
                        WriteOpenParentheses();
                    }

                    new ExpressionListBlock(Emitter, argsExpressions, paramsArg, objectCreateExpression, -1).Emit();
                    WriteCloseParentheses();
                }

                if (hasInitializer)
                {
                    if (isObjectLiteral && isPlainMode)
                    {
                        WriteObjectInitializer(objectCreateExpression.Initializer.Elements, type, invocationResolveResult, true);
                    }
                    else
                    {
                        foreach (Expression item in elements)
                        {
                            WriteInitializerExpression(item, tempVar);
                        }
                    }

                    WriteComma();
                    Write(tempVar);
                    WriteCloseParentheses();
                    RemoveTempVar(tempVar);
                }
            }

            //Helpers.CheckValueTypeClone(invocationResolveResult, this.ObjectCreateExpression, this, pos);
        }
예제 #17
0
        private void BuildArgumentsList(IList <Expression> arguments)
        {
            Expression paramsArg     = null;
            string     paramArgName  = null;
            var        resolveResult = ResolveResult;

            if (resolveResult != null)
            {
                var parameters = resolveResult.Member.Parameters;
                var isDelegate = resolveResult.Member.DeclaringType.Kind == TypeKind.Delegate;
                int shift      = 0;

                if (resolveResult.Member is IMethod resolvedMethod && resolveResult is CSharpInvocationResolveResult invocationResult &&
                    resolvedMethod.IsExtensionMethod && invocationResult.IsExtensionMethodInvocation)
                {
                    shift             = 1;
                    ThisName          = resolvedMethod.Parameters[0].Name;
                    IsExtensionMethod = true;
                }

                Expression[] result            = new Expression[parameters.Count - shift];
                string[]     names             = new string[result.Length];
                bool         named             = false;
                int          i                 = 0;
                bool         isInterfaceMember = false;

                if (resolveResult.Member != null)
                {
                    var inlineStr = Emitter.GetInline(resolveResult.Member);
                    named = !string.IsNullOrEmpty(inlineStr);

                    isInterfaceMember = resolveResult.Member.DeclaringTypeDefinition != null &&
                                        resolveResult.Member.DeclaringTypeDefinition.Kind == TypeKind.Interface;
                }

                var expandParams = resolveResult.Member.Attributes.Any(a => a.AttributeType.FullName == "H5.ExpandParamsAttribute");

                foreach (var arg in arguments)
                {
                    if (arg is NamedArgumentExpression namedArg)
                    {
                        var namedParam = parameters.First(p => p.Name == namedArg.Name);
                        var index      = parameters.IndexOf(namedParam) - shift;

                        result[index] = namedArg.Expression;
                        names[index]  = namedArg.Name;
                        named         = true;

                        if (paramsArg == null && parameters.FirstOrDefault(p => p.Name == namedArg.Name).IsParams)
                        {
                            if (resolveResult.Member.DeclaringTypeDefinition == null || !Emitter.Validator.IsExternalType(resolveResult.Member.DeclaringTypeDefinition))
                            {
                                paramsArg = namedArg.Expression;
                            }

                            paramArgName = namedArg.Name;
                        }
                    }
                    else
                    {
                        if (paramsArg == null && (parameters.Count > (i + shift)) && parameters[i + shift].IsParams)
                        {
                            if (resolveResult.Member.DeclaringTypeDefinition == null || !Emitter.Validator.IsExternalType(resolveResult.Member.DeclaringTypeDefinition) || expandParams)
                            {
                                paramsArg = arg;
                            }

                            paramArgName = parameters[i + shift].Name;
                        }

                        if (i >= result.Length)
                        {
                            var list = result.ToList();
                            list.AddRange(new Expression[arguments.Count - i]);

                            var strList = names.ToList();
                            strList.AddRange(new string[arguments.Count - i]);

                            result = list.ToArray();
                            names  = strList.ToArray();
                        }

                        result[i] = arg;
                        names[i]  = (i + shift) < parameters.Count ? parameters[i + shift].Name : paramArgName;
                    }

                    i++;
                }

                for (i = 0; i < result.Length; i++)
                {
                    if (result[i] == null)
                    {
                        var    p = parameters[i + shift];
                        object t = null;
                        if (p.Type.Kind == TypeKind.Enum)
                        {
                            t = Helpers.GetEnumValue(Emitter, p.Type, p.ConstantValue);
                        }
                        else
                        {
                            t = p.ConstantValue;
                        }
                        if ((named || isInterfaceMember || isDelegate) && !p.IsParams)
                        {
                            if (t == null)
                            {
                                result[i] = new PrimitiveExpression(new RawValue("void 0"));
                            }
                            else
                            {
                                result[i] = new PrimitiveExpression(t);
                            }
                        }

                        names[i] = parameters[i + shift].Name;
                    }
                }

                ArgumentsExpressions = result;
                ArgumentsNames       = names;
                ParamsExpression     = paramsArg;
                NamedExpressions     = CreateNamedExpressions(names, result);
            }
            else
            {
                ArgumentsExpressions = arguments.ToArray();
            }
        }
예제 #18
0
        protected virtual void EmitIndexerMethod(IndexerDeclaration indexerDeclaration, IProperty prop, Accessor accessor, IMethod propAccessor, bool setter)
        {
            var isIgnore = propAccessor != null && Emitter.Validator.IsExternalType(propAccessor);

            if (!accessor.IsNull && Emitter.GetInline(accessor) == null && !isIgnore)
            {
                EnsureComma();

                ResetLocals();

                var prevMap      = BuildLocalsMap();
                var prevNamesMap = BuildLocalsNamesMap();

                if (setter)
                {
                    AddLocals(new ParameterDeclaration[] { new ParameterDeclaration {
                                                               Name = "value"
                                                           } }, accessor.Body);
                }
                else
                {
                    AddLocals(new ParameterDeclaration[0], accessor.Body);
                }

                XmlToJsDoc.EmitComment(this, IndexerDeclaration, !setter);

                string accName = null;

                if (prop != null)
                {
                    accName = Emitter.GetEntityNameFromAttr(prop, setter);

                    if (string.IsNullOrEmpty(accName))
                    {
                        var member_rr = (MemberResolveResult)Emitter.Resolver.ResolveNode(indexerDeclaration);

                        var overloads = OverloadsCollection.Create(Emitter, indexerDeclaration, setter);
                        accName = overloads.GetOverloadName(false, Helpers.GetSetOrGet(setter), OverloadsCollection.ExcludeTypeParameterForDefinition(member_rr));
                    }
                }

                Write(accName);
                WriteColon();
                WriteFunction();
                var nm = Helpers.GetFunctionName(Emitter.AssemblyInfo.NamedFunctions, prop, Emitter, setter);
                if (nm != null)
                {
                    Write(nm);
                }
                EmitMethodParameters(indexerDeclaration.Parameters, null, indexerDeclaration, setter);

                if (setter)
                {
                    Write(", value)");
                }
                WriteSpace();

                var script = Emitter.GetScript(accessor);

                if (script == null)
                {
                    if (YieldBlock.HasYield(accessor.Body))
                    {
                        new GeneratorBlock(Emitter, accessor).Emit();
                    }
                    else
                    {
                        accessor.Body.AcceptVisitor(Emitter);
                    }
                }
                else
                {
                    BeginBlock();

                    WriteLines(script);

                    EndBlock();
                }

                ClearLocalsMap(prevMap);
                ClearLocalsNamesMap(prevNamesMap);
                Emitter.Comma = true;
            }
        }