コード例 #1
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);
        }