コード例 #1
0
ファイル: MethodBlock.cs プロジェクト: theolivenbaum/h5
        protected virtual void EmitOperatorGroup(List <OperatorDeclaration> group)
        {
            if (group.Count == 1)
            {
                if (!group[0].Body.IsNull)
                {
                    Emitter.VisitOperatorDeclaration(group[0]);
                }
            }
            else
            {
                var name       = group[0].Name;
                var methodsDef = Emitter.GetTypeDefinition().Methods.Where(m => m.Name == name);
                Emitter.MethodsGroup        = methodsDef;
                Emitter.MethodsGroupBuilder = new Dictionary <int, StringBuilder>();

                foreach (var method in group)
                {
                    if (!method.Body.IsNull)
                    {
                        Emitter.VisitOperatorDeclaration(method);
                    }
                }

                Emitter.MethodsGroup        = null;
                Emitter.MethodsGroupBuilder = null;
            }
        }
コード例 #2
0
ファイル: MethodBlock.cs プロジェクト: theolivenbaum/h5
        protected virtual void EmitMethodsGroup(List <MethodDeclaration> group)
        {
            if (group.Count == 1)
            {
                if ((!group[0].Body.IsNull || Emitter.GetScript(group[0]) != null) && (!StaticBlock || !Helpers.IsEntryPointMethod(Emitter, group[0])))
                {
                    Emitter.VisitMethodDeclaration(group[0]);
                }
            }
            else
            {
                var typeDef    = Emitter.GetTypeDefinition();
                var name       = group[0].Name;
                var methodsDef = typeDef.Methods.Where(m => m.Name == name);
                Emitter.MethodsGroup        = methodsDef;
                Emitter.MethodsGroupBuilder = new Dictionary <int, StringBuilder>();

                foreach (var method in group)
                {
                    if (!method.Body.IsNull && (!StaticBlock || !Helpers.IsEntryPointMethod(Emitter, group[0])))
                    {
                        Emitter.VisitMethodDeclaration(method);
                    }
                }

                Emitter.MethodsGroup        = null;
                Emitter.MethodsGroupBuilder = null;
            }
        }
コード例 #3
0
        private void AcceptLeftExpression(Expression left, ResolveResult rr)
        {
            if (!Emitter.InConstructor || !(rr is MemberResolveResult mrr) || !(mrr.Member is IProperty) || mrr.Member.IsStatic || mrr.Member.DeclaringTypeDefinition == null || !mrr.Member.DeclaringTypeDefinition.Equals(Emitter.TypeInfo.Type))
            {
                left.AcceptVisitor(Emitter);
            }
            else
            {
                var property = (IProperty)mrr.Member;
                var proto    = mrr.IsVirtualCall || property.IsVirtual || property.IsOverride;

                var td   = Emitter.GetTypeDefinition();
                var prop = td.Properties.FirstOrDefault(p => p.Name == mrr.Member.Name);

                if (proto && prop != null && prop.SetMethod == null)
                {
                    var name = OverloadsCollection.Create(Emitter, mrr.Member).GetOverloadName();
                    Write(JS.Types.H5.ENSURE_BASE_PROPERTY + "(this, \"" + name + "\"");

                    if (Emitter.Validator.IsExternalType(property.DeclaringTypeDefinition) && !Emitter.Validator.IsH5Class(property.DeclaringTypeDefinition))
                    {
                        Write(", \"" + H5Types.ToJsName(property.DeclaringType, Emitter, isAlias: true) + "\"");
                    }

                    Write(")");

                    WriteDot();
                    var alias = H5Types.ToJsName(mrr.Member.DeclaringType, Emitter, isAlias: true);
                    if (alias.StartsWith("\""))
                    {
                        alias = alias.Insert(1, "$");
                        name  = alias + "+\"$" + name + "\"";
                        WriteIdentifier(name, false);
                    }
                    else
                    {
                        name = "$" + alias + "$" + name;
                        WriteIdentifier(name);
                    }
                }
                else
                {
                    left.AcceptVisitor(Emitter);
                }
            }
        }
コード例 #4
0
ファイル: ClassBlock.cs プロジェクト: theolivenbaum/h5
        protected virtual void EmitInstantiableBlock()
        {
            if (TypeInfo.IsEnum)
            {
                if (Emitter.GetTypeDefinition(TypeInfo.Type)
                    .CustomAttributes.Any(attr => attr.AttributeType.FullName == "System.FlagsAttribute"))
                {
                    EnsureComma();
                    Write(JS.Fields.FLAGS + ": true");
                    Emitter.Comma = true;
                }

                var etype    = TypeInfo.Type.GetDefinition().EnumUnderlyingType;
                var enumMode = Helpers.EnumEmitMode(TypeInfo.Type);
                var isString = enumMode >= 3 && enumMode <= 6;
                if (isString)
                {
                    etype = Emitter.Resolver.Compilation.FindType(KnownTypeCode.String);
                }
                if (!etype.IsKnownType(KnownTypeCode.Int32))
                {
                    EnsureComma();
                    Write(JS.Fields.UNDERLYINGTYPE + ": ");
                    Write(H5Types.ToJsName(etype, Emitter));

                    Emitter.Comma = true;
                }
            }

            if (HasEntryPoint)
            {
                EnsureComma();
                Write(JS.Fields.ENTRY_POINT + ": true");
                Emitter.Comma = true;
            }

            var ctorBlock = new ConstructorBlock(Emitter, TypeInfo, false);

            if (TypeInfo.HasRealInstantiable(Emitter) || TypeInfo.ClassType == ClassType.Struct)
            {
                ctorBlock.Emit();
                new MethodBlock(Emitter, TypeInfo, false).Emit();
            }
        }
コード例 #5
0
        protected override void DoEmit()
        {
            IAttribute attribute = Attribute;

            var type = Emitter.GetTypeDefinition(attribute.AttributeType);

            var argsInfo = new ArgumentsInfo(Emitter, attribute);

            string inlineCode = Emitter.GetInline(attribute.Constructor);

            var customCtor     = Emitter.Validator.GetCustomConstructor(type) ?? "";
            var hasInitializer = attribute.NamedArguments.Count > 0;

            if (inlineCode == null && Regex.Match(customCtor, @"\s*\{\s*\}\s*").Success)
            {
                WriteOpenBrace();
                WriteSpace();

                if (hasInitializer)
                {
                    WriteObjectInitializer(attribute.NamedArguments, type, attribute);
                    WriteSpace();
                }
                else if (Emitter.Validator.IsObjectLiteral(type))
                {
                    WriteObjectInitializer(null, type, attribute);
                    WriteSpace();
                }

                WriteCloseBrace();
            }
            else
            {
                if (hasInitializer)
                {
                    Write(JS.Types.H5.APPLY);
                    WriteOpenParentheses();
                }

                if (inlineCode != null)
                {
                    new InlineArgumentsBlock(Emitter, argsInfo, inlineCode, attribute.Constructor).Emit();
                }
                else
                {
                    if (String.IsNullOrEmpty(customCtor))
                    {
                        WriteNew();
                        Write(H5Types.ToJsName(attribute.AttributeType, Emitter));
                    }
                    else
                    {
                        Write(customCtor);
                    }

                    if (!Emitter.Validator.IsExternalType(type) && type.Methods.Count(m => m.IsConstructor && !m.IsStatic) > (type.IsValueType ? 0 : 1))
                    {
                        WriteDot();
                        var name = OverloadsCollection.Create(Emitter, attribute.Constructor).GetOverloadName();
                        Write(name);
                    }

                    WriteOpenParentheses();

                    WritePositionalList(attribute.PositionalArguments, attribute);
                    WriteCloseParentheses();
                }

                if (hasInitializer)
                {
                    WriteComma();

                    BeginBlock();

                    var inlineInit = WriteObjectInitializer(attribute.NamedArguments, type, attribute);

                    WriteNewLine();

                    EndBlock();

                    if (inlineInit.Count > 0)
                    {
                        Write(", function () ");
                        BeginBlock();

                        foreach (var init in inlineInit)
                        {
                            Write(init);
                            WriteNewLine();
                        }

                        EndBlock();
                    }

                    WriteSpace();
                    WriteCloseParentheses();
                }
            }
        }
コード例 #6
0
ファイル: ConstructorBlock.cs プロジェクト: theolivenbaum/h5
        protected virtual void EmitCtorForInstantiableClass()
        {
            var baseType        = Emitter.GetBaseTypeDefinition();
            var typeDef         = Emitter.GetTypeDefinition();
            var isObjectLiteral = Emitter.Validator.IsObjectLiteral(typeDef);
            var isPlainMode     = Emitter.Validator.GetObjectCreateMode(typeDef) == 0;

            var ctorWrappers = isObjectLiteral ? new string[0] : EmitInitMembers().ToArray();

            if (!TypeInfo.HasRealInstantiable(Emitter) && ctorWrappers.Length == 0 || isObjectLiteral && isPlainMode)
            {
                if (ctorHeader)
                {
                    WriteNewLine();
                    EndBlock();
                }
                return;
            }

            bool forceDefCtor = isObjectLiteral && Emitter.Validator.GetObjectCreateMode(typeDef) == 1 && TypeInfo.Ctors.Count == 0;

            if (typeDef.IsValueType || forceDefCtor || (TypeInfo.Ctors.Count == 0 && ctorWrappers.Length > 0))
            {
                TypeInfo.Ctors.Add(new ConstructorDeclaration
                {
                    Modifiers = Modifiers.Public,
                    Body      = new BlockStatement()
                });
            }

            if (!ctorHeader && TypeInfo.Ctors.Count > 0)
            {
                EnsureComma();
                ctorHeader = true;
                Write(JS.Fields.CTORS);
                WriteColon();
                BeginBlock();
            }

            Emitter.InConstructor = true;
            foreach (var ctor in TypeInfo.Ctors)
            {
                var oldRules = Emitter.Rules;

                if (ctor.Body.HasChildren)
                {
                    if (Emitter.Resolver.ResolveNode(ctor) is MemberResolveResult rr)
                    {
                        Emitter.Rules = Rules.Get(Emitter, rr.Member);
                    }
                }

                EnsureComma();
                ResetLocals();
                var prevMap      = BuildLocalsMap();
                var prevNamesMap = BuildLocalsNamesMap();
                AddLocals(ctor.Parameters, ctor.Body);

                var ctorName = JS.Funcs.CONSTRUCTOR;

                if (TypeInfo.Ctors.Count > 1 && ctor.Parameters.Count > 0)
                {
                    var overloads = OverloadsCollection.Create(Emitter, ctor);
                    ctorName = overloads.GetOverloadName();
                }

                XmlToJsDoc.EmitComment(this, ctor);
                Write(ctorName);

                WriteColon();
                WriteFunction();

                int pos = Emitter.Output.Length;
                EmitMethodParameters(ctor.Parameters, null, ctor);
                var ctorParams = Emitter.Output.ToString().Substring(pos);

                WriteSpace();
                BeginBlock();
                var len            = Emitter.Output.Length;
                var requireNewLine = false;

                var         noThisInvocation = ctor.Initializer == null || ctor.Initializer.IsNull || ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.Base;
                IWriterInfo oldWriter        = null;
                if (ctorWrappers.Length > 0 && noThisInvocation)
                {
                    oldWriter = SaveWriter();
                    NewWriter();
                }

                ConvertParamsToReferences(ctor.Parameters);

                if (len != Emitter.Output.Length)
                {
                    requireNewLine = true;
                }

                if (isObjectLiteral)
                {
                    if (requireNewLine)
                    {
                        WriteNewLine();
                    }

                    Write("var " + JS.Vars.D_THIS + " = ");

                    var isBaseObjectLiteral = baseType != null && Emitter.Validator.IsObjectLiteral(baseType);
                    if (isBaseObjectLiteral && baseType != null && (!Emitter.Validator.IsExternalType(baseType) || Emitter.Validator.IsH5Class(baseType)) ||
                        (ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.This))
                    {
                        EmitBaseConstructor(ctor, ctorName, true);
                    }
                    else if (isBaseObjectLiteral && baseType != null && ctor.Initializer != null &&
                             ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.Base)
                    {
                        EmitExternalBaseCtor(ctor, ref requireNewLine);
                    }
                    else
                    {
                        Write("{ };");
                    }

                    WriteNewLine();

                    string name = Emitter.Validator.GetCustomTypeName(typeDef, Emitter, false);
                    if (name.IsEmpty())
                    {
                        name = H5Types.ToJsName(TypeInfo.Type, Emitter);
                    }

                    Write(JS.Vars.D_THIS + "." + JS.Funcs.GET_TYPE + " = function () { return " + name + "; };");

                    WriteNewLine();
                    Write("(function ()");
                    BeginBlock();
                    requireNewLine = false;
                }

                var beginPosition = Emitter.Output.Length;

                if (noThisInvocation)
                {
                    if (requireNewLine)
                    {
                        WriteNewLine();
                    }

                    if (isObjectLiteral)
                    {
                        var fieldBlock = new FieldBlock(Emitter, TypeInfo, false, false, true);
                        fieldBlock.Emit();

                        var properties = TypeInfo.InstanceProperties;

                        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 p)
                                {
                                    if (p.Getter.Body.IsNull && p.Setter.Body.IsNull)
                                    {
                                        continue;
                                    }

                                    Write(JS.Types.Object.DEFINEPROPERTY);
                                    WriteOpenParentheses();
                                    Write("this, ");
                                    WriteScript(OverloadsCollection.Create(Emitter, p).GetOverloadName());
                                    WriteComma();
                                    Emitter.Comma = false;
                                    BeginBlock();
                                    var memberResult = Emitter.Resolver.ResolveNode(p) as MemberResolveResult;
                                    var block        = new VisitorPropertyBlock(Emitter, p);
                                    block.EmitPropertyMethod(p, p.Getter, ((IProperty)memberResult.Member).Getter, false, true);
                                    block.EmitPropertyMethod(p, p.Setter, ((IProperty)memberResult.Member).Setter, true, true);
                                    EnsureComma(true);
                                    Write(JS.Fields.ENUMERABLE + ": true");
                                    WriteNewLine();
                                    EndBlock();
                                    WriteCloseParentheses();
                                    Write(";");
                                    WriteNewLine();
                                }
                            }
                        }
                    }
                    else
                    {
                        Write("this." + JS.Funcs.INITIALIZE + "();");
                        requireNewLine = true;
                    }
                }

                if (!isObjectLiteral)
                {
                    if (baseType != null && (!Emitter.Validator.IsExternalType(baseType) || Emitter.Validator.IsH5Class(baseType)) ||
                        (ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.This))
                    {
                        if (requireNewLine)
                        {
                            WriteNewLine();
                            requireNewLine = false;
                        }
                        EmitBaseConstructor(ctor, ctorName, false);
                    }
                    else if (baseType != null && (ctor.Initializer == null || ctor.Initializer.IsNull || ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.Base))
                    {
                        EmitExternalBaseCtor(ctor, ref requireNewLine);
                    }
                }

                var script = Emitter.GetScript(ctor);
                var hasAdditionalIndent = false;

                if (script == null)
                {
                    if (ctor.Body.HasChildren)
                    {
                        if (requireNewLine)
                        {
                            WriteNewLine();
                        }

                        ctor.Body.AcceptChildren(Emitter);

                        if (!Emitter.IsAsync)
                        {
                            hasAdditionalIndent = Emitter.TempVariables.Count > 0;
                            EmitTempVars(beginPosition, true);
                        }
                    }
                    else if (requireNewLine)
                    {
                        WriteNewLine();
                    }
                }
                else
                {
                    if (requireNewLine)
                    {
                        WriteNewLine();
                    }

                    WriteLines(script);
                }

                if (oldWriter != null)
                {
                    WrapBody(oldWriter, ctorWrappers, ctorParams);
                }

                if (isObjectLiteral)
                {
                    if (requireNewLine)
                    {
                        WriteNewLine();
                    }
                    EndBlock();
                    Write(")." + JS.Funcs.CALL + "(" + JS.Vars.D_THIS + ");");
                    WriteNewLine();
                    Write("return " + JS.Vars.D_THIS + ";");
                    WriteNewLine();
                }

                if (hasAdditionalIndent)
                {
                    Indent();
                }

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

                Emitter.Rules = oldRules;
            }

            Emitter.InConstructor = false;

            if (ctorHeader)
            {
                WriteNewLine();
                EndBlock();
            }
        }
コード例 #7
0
ファイル: VariableBlock.cs プロジェクト: theolivenbaum/h5
        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);

                        bool hadCustomConstructor = false;
                        if (typerr.Kind == ICSharpCode.NRefactory.TypeSystem.TypeKind.Struct)
                        {
                            var type = Emitter.GetTypeDefinition(typerr);

                            var customCtor = (Emitter.Validator.GetCustomConstructor(type) ?? "");
                            if (!string.IsNullOrEmpty(customCtor))
                            {
                                hadCustomConstructor = true;
                                Write(string.Concat(customCtor, "()"));
                            }
                        }

                        if (!hadCustomConstructor)
                        {
                            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;
            }
        }
コード例 #8
0
ファイル: ClassBlock.cs プロジェクト: theolivenbaum/h5
        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();
        }
コード例 #9
0
ファイル: CastBlock.cs プロジェクト: theolivenbaum/h5
        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(")");
            }
        }
コード例 #10
0
ファイル: MethodBlock.cs プロジェクト: theolivenbaum/h5
        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;
        }
コード例 #11
0
ファイル: ObjectCreateBlock.cs プロジェクト: theolivenbaum/h5
        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);
        }