private void HandleDecimal(ResolveResult resolveOperator, bool isLong = false)
        {
            var orr         = resolveOperator as OperatorResolveResult;
            var op          = UnaryOperatorExpression.Operator;
            var oldType     = Emitter.UnaryOperatorType;
            var oldAccessor = Emitter.IsUnaryAccessor;
            var typeCode    = isLong ? KnownTypeCode.Int64 : KnownTypeCode.Decimal;

            Emitter.UnaryOperatorType = op;

            var  argResolverResult = Emitter.Resolver.ResolveNode(UnaryOperatorExpression.Expression);
            bool nullable          = NullableType.IsNullable(argResolverResult.Type);
            bool isAccessor        = false;

            if (argResolverResult is MemberResolveResult memberArgResolverResult && memberArgResolverResult.Member is IProperty)
            {
                var isIgnore           = Emitter.Validator.IsExternalType(memberArgResolverResult.Member.DeclaringTypeDefinition);
                var inlineAttr         = Emitter.GetAttribute(memberArgResolverResult.Member.Attributes, Translator.H5_ASSEMBLY + ".TemplateAttribute");
                var ignoreAccessor     = Emitter.Validator.IsExternalType(((IProperty)memberArgResolverResult.Member).Getter);
                var isAccessorsIndexer = Emitter.Validator.IsAccessorsIndexer(memberArgResolverResult.Member);

                isAccessor = ((IProperty)memberArgResolverResult.Member).IsIndexer;

                if (inlineAttr == null && (isIgnore || ignoreAccessor) && !isAccessorsIndexer)
                {
                    isAccessor = false;
                }
            }
Exemple #2
0
        protected virtual string GetCastCode(Expression expression, AstType astType, string op, out bool isCastAttr)
        {
            isCastAttr = false;

            if (!(Emitter.Resolver.ResolveNode(astType) is TypeResolveResult resolveResult))
            {
                return(null);
            }

            var    exprResolveResult = Emitter.Resolver.ResolveNode(expression);
            string inline            = null;
            bool   isOp = op == CS.Ops.IS;

            var method = isOp ? null : GetCastMethod(exprResolveResult.Type, resolveResult.Type, out inline);

            if (method == null && !isOp && (NullableType.IsNullable(exprResolveResult.Type) || NullableType.IsNullable(resolveResult.Type)))
            {
                method = GetCastMethod(NullableType.IsNullable(exprResolveResult.Type) ? NullableType.GetUnderlyingType(exprResolveResult.Type) : exprResolveResult.Type,
                                       NullableType.IsNullable(resolveResult.Type) ? NullableType.GetUnderlyingType(resolveResult.Type) : resolveResult.Type, out inline);
            }

            if (inline != null)
            {
                InlineMethod = method;
                return(inline);
            }

            IEnumerable <IAttribute> attributes = null;
            var type = resolveResult.Type.GetDefinition();

            if (type != null)
            {
                attributes = type.Attributes;
            }
            else
            {
                if (resolveResult.Type is ParameterizedType paramType)
                {
                    attributes = paramType.GetDefinition().Attributes;
                }
            }

            if (attributes != null)
            {
                var attribute = Emitter.GetAttribute(attributes, Translator.H5_ASSEMBLY + ".CastAttribute");

                if (attribute != null)
                {
                    isCastAttr = true;
                    return(attribute.PositionalArguments[0].ConstantValue.ToString());
                }
            }

            return(null);
        }
Exemple #3
0
        protected void VisitIdentifierExpression()
        {
            IdentifierExpression identifierExpression = IdentifierExpression;
            int           pos           = Emitter.Output.Length;
            ResolveResult resolveResult = null;

            isRefArg         = Emitter.IsRefArg;
            Emitter.IsRefArg = false;

            resolveResult = Emitter.Resolver.ResolveNode(identifierExpression);

            var id = identifierExpression.Identifier;

            var isResolved   = resolveResult != null && !(resolveResult is ErrorResolveResult);
            var memberResult = resolveResult as MemberResolveResult;

            if (Emitter.Locals != null && Emitter.Locals.ContainsKey(id) && resolveResult is LocalResolveResult)
            {
                var lrr = (LocalResolveResult)resolveResult;
                if (Emitter.LocalsMap != null && Emitter.LocalsMap.ContainsKey(lrr.Variable) && !(identifierExpression.Parent is DirectionExpression))
                {
                    Write(Emitter.LocalsMap[lrr.Variable]);
                }
                else if (Emitter.LocalsNamesMap != null && Emitter.LocalsNamesMap.ContainsKey(id))
                {
                    Write(Emitter.LocalsNamesMap[id]);
                }
                else
                {
                    Write(id);
                }

                Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos);

                return;
            }

            if (resolveResult is TypeResolveResult)
            {
                Write(H5Types.ToJsName(resolveResult.Type, Emitter));

                /*if (this.Emitter.Validator.IsExternalType(resolveResult.Type.GetDefinition()) || resolveResult.Type.Kind == TypeKind.Enum)
                 * {
                 *  this.Write(H5Types.ToJsName(resolveResult.Type, this.Emitter));
                 * }
                 * else
                 * {
                 *  this.Write("H5.get(" + H5Types.ToJsName(resolveResult.Type, this.Emitter) + ")");
                 * }*/

                return;
            }

            string inlineCode = memberResult != null?Emitter.GetInline(memberResult.Member) : null;

            var isInvoke = identifierExpression.Parent is InvocationExpression && (((InvocationExpression)(identifierExpression.Parent)).Target == identifierExpression);

            if (memberResult != null && memberResult.Member is IMethod && isInvoke)
            {
                if (Emitter.Resolver.ResolveNode(identifierExpression.Parent) is CSharpInvocationResolveResult i_rr && !i_rr.IsExpandedForm)
                {
                    var tpl = Emitter.GetAttribute(memberResult.Member.Attributes, JS.NS.H5 + ".TemplateAttribute");

                    if (tpl != null && tpl.PositionalArguments.Count == 2)
                    {
                        inlineCode = tpl.PositionalArguments[1].ConstantValue.ToString();
                    }
                }
            }

            if (string.IsNullOrEmpty(inlineCode) && memberResult != null &&
                memberResult.Member is IMethod &&
                !(memberResult is InvocationResolveResult) &&
                !(
                    identifierExpression.Parent is InvocationExpression &&
                    identifierExpression.NextSibling != null &&
                    identifierExpression.NextSibling.Role is TokenRole &&
                    ((TokenRole)identifierExpression.NextSibling.Role).Token == "("
                    )
                )
            {
                if (!(identifierExpression.Parent is InvocationExpression parentInvocation) || parentInvocation.Target != identifierExpression)
                {
                    var method = (IMethod)memberResult.Member;
                    if (method.TypeArguments.Count > 0)
                    {
                        inlineCode = MemberReferenceBlock.GenerateInlineForMethodReference(method, Emitter);
                    }
                }
            }

            bool hasInline = !string.IsNullOrEmpty(inlineCode);

            inlineCode = hasInline ? Helpers.ConvertTokens(Emitter, inlineCode, memberResult.Member) : inlineCode;
            bool hasThis = hasInline && Helpers.HasThis(inlineCode);

            if (hasInline && inlineCode.StartsWith("<self>"))
            {
                hasThis    = true;
                inlineCode = inlineCode.Substring(6);
            }

            if (hasThis)
            {
                Emitter.ThisRefCounter++;
                Write("");
                var oldBuilder = Emitter.Output;
                Emitter.Output = new StringBuilder();

                if (memberResult.Member.IsStatic)
                {
                    Write(H5Types.ToJsName(memberResult.Member.DeclaringType, Emitter, ignoreLiteralName: false));

                    /*if (!this.Emitter.Validator.IsExternalType(memberResult.Member.DeclaringTypeDefinition) && memberResult.Member.DeclaringTypeDefinition.Kind != TypeKind.Enum)
                     * {
                     *  this.Write("(H5.get(" + H5Types.ToJsName(memberResult.Member.DeclaringType, this.Emitter) + "))");
                     * }
                     * else
                     * {
                     *  this.Write(H5Types.ToJsName(memberResult.Member.DeclaringType, this.Emitter));
                     * }*/
                }
                else
                {
                    WriteThis();
                }

                var oldInline = inlineCode;
                var thisArg   = Emitter.Output.ToString();
                int thisIndex = inlineCode.IndexOf("{this}");
                inlineCode     = inlineCode.Replace("{this}", thisArg);
                Emitter.Output = oldBuilder;

                int[] range = null;

                if (thisIndex > -1)
                {
                    range = new[] { thisIndex, thisIndex + thisArg.Length };
                }

                if (resolveResult is InvocationResolveResult)
                {
                    PushWriter(inlineCode, null, thisArg, range);
                }
                else
                {
                    if (memberResult.Member is IMethod)
                    {
                        ResolveResult targetrr = null;
                        if (memberResult.Member.IsStatic)
                        {
                            targetrr = new TypeResolveResult(memberResult.Member.DeclaringType);
                        }

                        new InlineArgumentsBlock(Emitter, new ArgumentsInfo(Emitter, IdentifierExpression, resolveResult), oldInline, (IMethod)memberResult.Member, targetrr).EmitFunctionReference();
                    }
                    else if (memberResult != null && memberResult.Member is IField && inlineCode.Contains("{0}"))
                    {
                        PushWriter(inlineCode, null, thisArg, range);
                    }
                    else if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inlineCode))
                    {
                        PushWriter(inlineCode, null, thisArg, range);
                    }
                    else
                    {
                        Write(inlineCode);
                    }
                }

                return;
            }

            if (hasInline)
            {
                if (!memberResult.Member.IsStatic)
                {
                    inlineCode = "this." + inlineCode;
                }

                if (resolveResult is InvocationResolveResult)
                {
                    PushWriter(inlineCode);
                }
                else
                {
                    if (memberResult.Member is IMethod)
                    {
                        ResolveResult targetrr = null;
                        if (memberResult.Member.IsStatic)
                        {
                            targetrr = new TypeResolveResult(memberResult.Member.DeclaringType);
                        }

                        new InlineArgumentsBlock(Emitter, new ArgumentsInfo(Emitter, IdentifierExpression, resolveResult), inlineCode, (IMethod)memberResult.Member, targetrr).EmitFunctionReference();
                    }
                    else if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inlineCode))
                    {
                        PushWriter(inlineCode);
                    }
                    else
                    {
                        Write(inlineCode);
                    }
                }

                return;
            }

            string appendAdditionalCode = null;

            if (memberResult != null &&
                memberResult.Member is IMethod &&
                !(memberResult is InvocationResolveResult) &&
                !(
                    identifierExpression.Parent is InvocationExpression &&
                    identifierExpression.NextSibling != null &&
                    identifierExpression.NextSibling.Role is TokenRole &&
                    ((TokenRole)identifierExpression.NextSibling.Role).Token == "("
                    )
                )
            {
                if (!(identifierExpression.Parent is InvocationExpression parentInvocation) || parentInvocation.Target != identifierExpression)
                {
                    if (!string.IsNullOrEmpty(inlineCode))
                    {
                        ResolveResult targetrr = null;
                        if (memberResult.Member.IsStatic)
                        {
                            targetrr = new TypeResolveResult(memberResult.Member.DeclaringType);
                        }

                        new InlineArgumentsBlock(Emitter,
                                                 new ArgumentsInfo(Emitter, identifierExpression, resolveResult), inlineCode,
                                                 (IMethod)memberResult.Member, targetrr).EmitFunctionReference();
                    }
                    else
                    {
                        var  resolvedMethod = (IMethod)memberResult.Member;
                        bool isStatic       = resolvedMethod != null && resolvedMethod.IsStatic;

                        if (!isStatic)
                        {
                            var isExtensionMethod = resolvedMethod.IsExtensionMethod;
                            Write(isExtensionMethod ? JS.Funcs.H5_BIND_SCOPE : JS.Funcs.H5_CACHE_BIND);
                            WriteOpenParentheses();
                            WriteThis();
                            Write(", ");
                            appendAdditionalCode = ")";
                        }
                    }
                }
            }

            if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Field && Emitter.IsMemberConst(memberResult.Member) && Emitter.IsInlineConst(memberResult.Member))
            {
                WriteScript(memberResult.ConstantValue);
                return;
            }

            if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Property && memberResult.TargetResult.Type.Kind != TypeKind.Anonymous)
            {
                bool   isStatement = false;
                string valueVar    = null;

                if (Emitter.IsUnaryAccessor)
                {
                    isStatement = identifierExpression.Parent is UnaryOperatorExpression && identifierExpression.Parent.Parent is ExpressionStatement;

                    if (NullableType.IsNullable(memberResult.Type))
                    {
                        isStatement = false;
                    }

                    if (!isStatement)
                    {
                        WriteOpenParentheses();

                        valueVar = GetTempVarName();

                        Write(valueVar);
                        Write(" = ");
                    }
                }

                WriteTarget(memberResult);

                if (!string.IsNullOrWhiteSpace(inlineCode))
                {
                    //this.Write(inlineCode);
                    if (resolveResult is InvocationResolveResult || (memberResult.Member.SymbolKind == SymbolKind.Property && Emitter.IsAssignment))
                    {
                        PushWriter(inlineCode);
                    }
                    else
                    {
                        Write(inlineCode);
                    }
                }
                else if (memberResult.Member is IProperty)
                {
                    var name = Helpers.GetPropertyRef(memberResult.Member, Emitter);

                    WriteIdentifier(name);
                }
                else if (!Emitter.IsAssignment)
                {
                    if (Emitter.IsUnaryAccessor)
                    {
                        bool isDecimal  = Helpers.IsDecimalType(memberResult.Member.ReturnType, Emitter.Resolver);
                        bool isLong     = Helpers.Is64Type(memberResult.Member.ReturnType, Emitter.Resolver);
                        bool isNullable = NullableType.IsNullable(memberResult.Member.ReturnType);
                        if (isStatement)
                        {
                            Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, true));
                            WriteOpenParentheses();

                            if (isDecimal || isLong)
                            {
                                if (isNullable)
                                {
                                    Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1);
                                    WriteOpenParentheses();
                                    if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                        Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                    {
                                        WriteScript(JS.Funcs.Math.INC);
                                    }
                                    else
                                    {
                                        WriteScript(JS.Funcs.Math.DEC);
                                    }

                                    WriteComma();

                                    WriteTarget(memberResult);

                                    Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, false));
                                    WriteOpenParentheses();
                                    WriteCloseParentheses();
                                    WriteCloseParentheses();
                                }
                                else
                                {
                                    WriteTarget(memberResult);
                                    Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, false));
                                    WriteOpenParentheses();
                                    WriteCloseParentheses();
                                    WriteDot();

                                    if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                        Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                    {
                                        Write(JS.Funcs.Math.INC);
                                    }
                                    else
                                    {
                                        Write(JS.Funcs.Math.DEC);
                                    }

                                    WriteOpenParentheses();
                                    WriteCloseParentheses();
                                }
                            }
                            else
                            {
                                WriteTarget(memberResult);

                                Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, false));
                                WriteOpenParentheses();
                                WriteCloseParentheses();

                                if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment || Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                {
                                    Write("+");
                                }
                                else
                                {
                                    Write("-");
                                }

                                Write("1");
                            }

                            WriteCloseParentheses();
                        }
                        else
                        {
                            Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, false));
                            WriteOpenParentheses();
                            WriteCloseParentheses();
                            WriteComma();

                            WriteTarget(memberResult);
                            Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, true));
                            WriteOpenParentheses();

                            if (isDecimal || isLong)
                            {
                                if (isNullable)
                                {
                                    Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1);
                                    WriteOpenParentheses();
                                    if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                        Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                    {
                                        WriteScript(JS.Funcs.Math.INC);
                                    }
                                    else
                                    {
                                        WriteScript(JS.Funcs.Math.DEC);
                                    }

                                    WriteComma();
                                    Write(valueVar);
                                    WriteCloseParentheses();
                                }
                                else
                                {
                                    Write(valueVar);

                                    WriteDot();

                                    if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                        Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                    {
                                        Write(JS.Funcs.Math.INC);
                                    }
                                    else
                                    {
                                        Write(JS.Funcs.Math.DEC);
                                    }

                                    WriteOpenParentheses();
                                    WriteCloseParentheses();
                                }
                            }
                            else
                            {
                                Write(valueVar);

                                if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment || Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                {
                                    Write("+");
                                }
                                else
                                {
                                    Write("-");
                                }

                                Write("1");
                            }

                            WriteCloseParentheses();
                            WriteComma();

                            if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                Emitter.UnaryOperatorType == UnaryOperatorType.Decrement)
                            {
                                WriteTarget(memberResult);
                                Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, false));
                                WriteOpenParentheses();
                                WriteCloseParentheses();
                            }
                            else
                            {
                                Write(valueVar);
                            }

                            WriteCloseParentheses();

                            if (valueVar != null)
                            {
                                RemoveTempVar(valueVar);
                            }
                        }
                    }
                    else
                    {
                        Write(Helpers.GetPropertyRef(memberResult.Member, Emitter));
                        WriteOpenParentheses();
                        WriteCloseParentheses();
                    }
                }
                else if (Emitter.AssignmentType != AssignmentOperatorType.Assign)
                {
                    string trg;

                    if (memberResult.Member.IsStatic)
                    {
                        trg = H5Types.ToJsName(memberResult.Member.DeclaringType, Emitter, ignoreLiteralName: false);
                    }
                    else
                    {
                        trg = "this";
                    }

                    bool isBool  = memberResult != null && NullableType.IsNullable(memberResult.Member.ReturnType) ? NullableType.GetUnderlyingType(memberResult.Member.ReturnType).IsKnownType(KnownTypeCode.Boolean) : memberResult.Member.ReturnType.IsKnownType(KnownTypeCode.Boolean);
                    bool skipGet = false;
                    bool special = Emitter.Resolver.ResolveNode(identifierExpression.Parent) is OperatorResolveResult orr && orr.IsLiftedOperator;

                    if (!special && isBool &&
                        (Emitter.AssignmentType == AssignmentOperatorType.BitwiseAnd ||
                         Emitter.AssignmentType == AssignmentOperatorType.BitwiseOr))
                    {
                        skipGet = true;
                    }

                    if (skipGet)
                    {
                        PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, Emitter, true), "({0})"));
                    }
                    else
                    {
                        PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, Emitter, true),
                                                 "(",
                                                 trg,
                                                 ".",
                                                 Helpers.GetPropertyRef(memberResult.Member, Emitter, false),
                                                 "()",
                                                 "{0})"));
                    }
                }
                else
                {
                    PushWriter(Helpers.GetPropertyRef(memberResult.Member, Emitter, true) + "({0})");
                }
            }
            else if (memberResult != null && memberResult.Member is IEvent)
            {
                if (Emitter.IsAssignment &&
                    (Emitter.AssignmentType == AssignmentOperatorType.Add ||
                     Emitter.AssignmentType == AssignmentOperatorType.Subtract))
                {
                    WriteTarget(memberResult);

                    if (!string.IsNullOrWhiteSpace(inlineCode))
                    {
                        Write(inlineCode);
                    }
                    else
                    {
                        Write(Helpers.GetAddOrRemove(Emitter.AssignmentType == AssignmentOperatorType.Add));
                        Write(
                            OverloadsCollection.Create(Emitter, memberResult.Member,
                                                       Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName());
                    }

                    WriteOpenParentheses();
                }
                else
                {
                    WriteTarget(memberResult);
                    Write(Emitter.GetEntityName(memberResult.Member));
                }
            }
            else
            {
                if (!string.IsNullOrWhiteSpace(inlineCode))
                {
                    Write(inlineCode);
                }
                else if (isResolved)
                {
                    if (resolveResult is LocalResolveResult localResolveResult)
                    {
                        Write(localResolveResult.Variable.Name);
                    }
                    else if (memberResult != null)
                    {
                        WriteTarget(memberResult);
                        string name = OverloadsCollection.Create(Emitter, memberResult.Member).GetOverloadName();
                        if (isRefArg)
                        {
                            WriteScript(name);
                        }
                        else if (memberResult.Member is IField)
                        {
                            WriteIdentifier(name);
                        }
                        else
                        {
                            Write(name);
                        }
                    }
                    else
                    {
                        Write(resolveResult.ToString());
                    }
                }
                else
                {
                    throw new EmitterException(identifierExpression, "Cannot resolve identifier: " + id);
                }
            }

            if (appendAdditionalCode != null)
            {
                Write(appendAdditionalCode);
            }

            Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos);
        }
        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;
        }