void CheckFormattingCall(InvocationExpression invocationExpression, CSharpInvocationResolveResult invocationResolveResult)
            {
                Expression         formatArgument;
                IList <Expression> formatArguments;
                TextLocation       formatStart;
                // Only check parameters that are of type object: String means it is neccessary, others
                // means that there is another problem (ie no matching overload of the method).
                Func <IParameter, Expression, bool> predicate = (parameter, argument) => {
                    var type = parameter.Type;
                    if (type is TypeWithElementType && parameter.IsParams)
                    {
                        type = ((TypeWithElementType)type).ElementType;
                    }
                    var typeDefinition = type.GetDefinition();
                    if (typeDefinition == null)
                    {
                        return(false);
                    }
                    return(typeDefinition.IsKnownType(KnownTypeCode.Object));
                };

                if (FormatStringHelper.TryGetFormattingParameters(invocationResolveResult, invocationExpression,
                                                                  out formatArgument, out formatStart, out formatArguments, predicate))
                {
                    foreach (var argument in formatArguments)
                    {
                        CheckExpressionInAutoCallContext(argument);
                    }
                }
            }
Exemple #2
0
 public JsNode VisitCSharpInvocationResolveResult(CSharpInvocationResolveResult res)
 {
     if (res.Member.IsConstructor())
     {
         if (res.Type is AnonymousType)
         {
             //TODO: check context class JsType.NativeJsons
             var json       = InitializersToJson(res.InitializerStatements, res.Type);
             var parentType = res.GetParentType();
             if (parentType != null && !Sk.UseNativeJsons(parentType))
             {
                 return(Js.Member("$CreateAnonymousObject").Invoke(json));
             }
             return(json);
         }
         else
         {
             return(VisitInvocationResolveResultAsCtor(res));
         }
     }
     else
     {
         return(VisitInvocationResolveResult(res));
     }
 }
        static InitializedObjectResolveResult FindInitializedObjectResolveResult(CSharpInvocationResolveResult res)
        {
            var init1 = res.InitializerStatements[0];

            while (init1 != null && !(init1 is InitializedObjectResolveResult))
            {
                if (init1 is OperatorResolveResult)
                {
                    init1 = ((OperatorResolveResult)init1).Operands[0];
                }
                else if (init1 is CSharpInvocationResolveResult)
                {
                    init1 = ((CSharpInvocationResolveResult)init1).TargetResult;
                }
                else if (init1 is MemberResolveResult)
                {
                    init1 = ((MemberResolveResult)init1).TargetResult;
                }
                else
                {
                    throw new NotImplementedException("FindInitializedObjectResolveResult");
                }
            }
            return((InitializedObjectResolveResult)init1);
        }
            IEnumerable <Expression> GetRedundantArguments(Expression[] arguments, CSharpInvocationResolveResult invocationResolveResult)
            {
                var argumentToParameterMap = invocationResolveResult.GetArgumentToParameterMap();
                var resolvedParameters     = invocationResolveResult.Member.Parameters;

                for (int i = arguments.Length - 1; i >= 0; i--)
                {
                    var parameterIndex = argumentToParameterMap[i];
                    if (parameterIndex == -1)
                    {
                        // This particular parameter is an error, but keep trying the other ones
                        continue;
                    }
                    var parameter = resolvedParameters[parameterIndex];
                    var argument  = arguments[i];
                    if (argument is PrimitiveExpression)
                    {
                        if (parameter.IsParams)
                        {
                            // before positional params arguments all optional arguments are needed, otherwise some of the
                            // param arguments will be shifted out of the params into the fixed parameters
                            break;
                        }
                        if (!parameter.IsOptional)
                        {
                            // There can be no optional parameters preceding a required one
                            break;
                        }
                        var argumentResolveResult = ctx.Resolve(argument) as ConstantResolveResult;
                        if (argumentResolveResult == null || parameter.ConstantValue != argumentResolveResult.ConstantValue)
                        {
                            // Stop here since any arguments before this one has to be there
                            // to enable the passing of this argument
                            break;
                        }
                        yield return(argument);
                    }
                    else if (argument is NamedArgumentExpression)
                    {
                        var expression = ((NamedArgumentExpression)argument).Expression as PrimitiveExpression;
                        if (expression == null)
                        {
                            continue;
                        }
                        var expressionResolveResult = ctx.Resolve(expression) as ConstantResolveResult;
                        if (expressionResolveResult == null || parameter.ConstantValue != expressionResolveResult.ConstantValue)
                        {
                            // continue, since there can still be more arguments that are redundant
                            continue;
                        }
                        yield return(argument);
                    }
                    else
                    {
                        // This is a non-constant positional argument => no more redundancies are possible
                        break;
                    }
                }
            }
Exemple #5
0
        public JNode VisitMemberResolveResult(MemberResolveResult res)
        {
            var   me = res.Member;
            JNode node2;
            bool  enumValuesAsNames;

            if (me == null) //TODO: dynamics
            {
                throw new NotImplementedException();
                //var node3 = Js.Member(node.MemberName);
                //if (node.Target != null)
                //    node3.PreviousMember = VisitExpression(node.Target);
                //return node3;
            }
            else if (IsEntityFunctionProperty(res.Member, res))//(Entity)node.entity))
            {
                var pe  = (IProperty)me;
                var xxx = new CSharpInvocationResolveResult(res.TargetResult, pe.Getter, null);
                node2 = Visit(xxx);
                return(node2);
            }
            else if (me.IsEnumMember() && JMeta.UseJsonEnums(me, out enumValuesAsNames))
            {
                var me2 = (IField)me;
                if (enumValuesAsNames)
                {
                    return(J.String(JNaming.JName(me2)));
                }
                else
                {
                    return(J.Value(me2.ConstantValue));
                }
            }
            //TODO: Support a way to override this (JsField.ConstantInlining=false)
            else if (res.IsCompileTimeConstant && !me.IsEnumMember())
            {
                return(J.Value(res.ConstantValue));
            }
            else
            {
                var node3 = JNaming.JAccess(me);
                node2 = node3;
                if (res.TargetResult != null && !me.IsStatic())
                {
                    var instanceContext = VisitExpression(res.TargetResult);
                    if (node3.Name.IsNullOrEmpty()) //support Name=""
                    {
                        node2 = instanceContext;
                    }
                    else
                    {
                        node3.PreviousMember = instanceContext;
                    }
                }
            }
            return(node2);
        }
Exemple #6
0
        AstNode ToStaticMethodInvocation(InvocationExpression invocation, MemberReferenceExpression memberReference,
                                         CSharpInvocationResolveResult invocationRR)
        {
            var newArgumentList = invocation.Arguments.Select(arg => arg.Clone()).ToList();

            newArgumentList.Insert(0, memberReference.Target.Clone());
            var newTarget = memberReference.Clone() as MemberReferenceExpression;

            newTarget.Target = new IdentifierExpression(invocationRR.Member.DeclaringType.Name);
            return(new InvocationExpression(newTarget, newArgumentList));
        }
        public static bool TryGetFormattingParameters(CSharpInvocationResolveResult invocationResolveResult, InvocationExpression invocationExpression,
                                                      out Expression formatArgument, out IList <Expression> arguments,
                                                      Func <IParameter, Expression, bool> argumentFilter)
        {
            if (argumentFilter == null)
            {
                argumentFilter = (p, e) => true;
            }

            formatArgument = null;
            arguments      = new List <Expression>();
            var argumentToParameterMap = invocationResolveResult.GetArgumentToParameterMap();
            var resolvedParameters     = invocationResolveResult.Member.Parameters;
            var allArguments           = invocationExpression.Arguments.ToArray();

            for (int i = 0; i < allArguments.Length; i++)
            {
                var parameterIndex = argumentToParameterMap[i];
                if (parameterIndex < 0 || parameterIndex >= resolvedParameters.Count)
                {
                    // No valid mapping for this argument, skip it
                    continue;
                }
                var parameter = resolvedParameters[parameterIndex];
                var argument  = allArguments[i];
                if (i == 0 && parameter.Type.IsKnownType(KnownTypeCode.String) && parameterNames.Contains(parameter.Name))
                {
                    formatArgument = argument;
                }
                else if (formatArgument != null && parameter.IsParams && !invocationResolveResult.IsExpandedForm)
                {
                    var ace = argument as ArrayCreateExpression;
                    if (ace == null || ace.Initializer.IsNull)
                    {
                        return(false);
                    }
                    foreach (var element in ace.Initializer.Elements)
                    {
                        if (argumentFilter(parameter, element))
                        {
                            arguments.Add(argument);
                        }
                    }
                }
                else if (formatArgument != null && argumentFilter(parameter, argument))
                {
                    arguments.Add(argument);
                }
            }
            return(formatArgument != null);
        }
Exemple #8
0
        public static CSharpInvocationResolveResult ToCSharpInvocationResolveResult(this InvocationResolveResult res)
        {
            if (res == null)
            {
                return(null);
            }
            if (res is CSharpInvocationResolveResult)
            {
                return((CSharpInvocationResolveResult)res);
            }
            var res2 = new CSharpInvocationResolveResult(res.TargetResult, res.Member, res.Arguments, initializerStatements: res.InitializerStatements);

            res2.Tag = res.Tag;
            return(res2);
        }
Exemple #9
0
        public override void VisitInvocationExpression(InvocationExpression invocationExpression)
        {
            base.VisitInvocationExpression(invocationExpression);
            if (!CanTransformToExtensionMethodCall(resolver, invocationExpression, out var memberRefExpr,
                                                   out var target, out var firstArgument))
            {
                return;
            }
            var method = (IMethod)invocationExpression.GetSymbol();

            if (firstArgument is DirectionExpression dirExpr)
            {
                if (!context.Settings.RefExtensionMethods || dirExpr.FieldDirection == FieldDirection.Out)
                {
                    return;
                }
                firstArgument = dirExpr.Expression;
                target        = firstArgument.GetResolveResult();
                dirExpr.Detach();
            }
            else if (firstArgument is NullReferenceExpression)
            {
                Debug.Assert(context.RequiredNamespacesSuperset.Contains(method.Parameters[0].Type.Namespace));
                firstArgument = firstArgument.ReplaceWith(expr => new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.Parameters[0].Type), expr.Detach()));
            }
            if (invocationExpression.Target is IdentifierExpression identifierExpression)
            {
                identifierExpression.Detach();
                memberRefExpr = new MemberReferenceExpression(firstArgument.Detach(), method.Name, identifierExpression.TypeArguments.Detach());
                invocationExpression.Target = memberRefExpr;
            }
            else
            {
                memberRefExpr.Target = firstArgument.Detach();
            }
            if (invocationExpression.GetResolveResult() is CSharpInvocationResolveResult irr)
            {
                // do not forget to update the CSharpInvocationResolveResult => set IsExtensionMethodInvocation == true
                invocationExpression.RemoveAnnotations <CSharpInvocationResolveResult>();
                var newResolveResult = new CSharpInvocationResolveResult(
                    irr.TargetResult, irr.Member, irr.Arguments, irr.OverloadResolutionErrors,
                    isExtensionMethodInvocation: true, irr.IsExpandedForm, irr.IsDelegateInvocation,
                    irr.GetArgumentToParameterMap(), irr.InitializerStatements);
                invocationExpression.AddAnnotation(newResolveResult);
            }
        }
Exemple #10
0
 public JNode VisitCSharpInvocationResolveResult(CSharpInvocationResolveResult res)
 {
     if (res.Member.IsConstructor())
     {
         if (res.Type is AnonymousType)
         {
             //TODO: check context class JsType.NativeJsons
             var json = InitializersToJson(res.InitializerStatements, res.Type);
             return(json);
         }
         else
         {
             return(VisitInvocationResolveResultAsCtor(res));
         }
     }
     else
     {
         return(VisitInvocationResolveResult(res));
     }
 }
Exemple #11
0
        public static List <ParameterBinding> GetArgumentsForCall2(this CSharpInvocationResolveResult res)
        {
            var args     = res.Arguments;
            var callArgs = res.GetArgumentsForCall();

            var map  = res.GetArgumentToParameterMap();
            var prms = res.Member.Parameters;
            var list = callArgs.Select(t => new ParameterBinding {
                CallResult = t
            }).ToList();
            var index = -1;

            foreach (var arg in args)
            {
                index++;
                var index2  = map == null ? index : map[index];
                var prm     = prms[index2];
                var binding = list[index2];
                binding.Parameter = prm;
                binding.ArgResult = arg;
            }
            index = 0;
            foreach (var binding in list)
            {
                var prm = prms[index];
                if (binding.Parameter == null)
                {
                    binding.Parameter = prm;
                }
                else if (binding.Parameter != prm)
                {
                    throw new NotImplementedException();
                }
                if (!prm.IsParams)
                {
                    index++;
                }
            }
            return(list);
        }
Exemple #12
0
        void TransformIntoBaseMethodCallIfNeeded(CSharpInvocationResolveResult res, JInvocationExpression node2)
        {
            var target = res.TargetResult as ThisResolveResult;

            if (target != null && target.CausesNonVirtualInvocation) //base.
            {
                //var info = res.GetInfo();
                //var node = info.Nodes.FirstOrDefault();
                var ce = target.Type;// node.FindThisEntity();
                if (ce != null && JMeta.IsExtJsType(ce.GetDefinitionOrArrayType(Compiler)))
                {
                    node2.Member = J.This().Member("callParent");
                    if (node2.Arguments.IsNotNullOrEmpty())
                    {
                        node2.Arguments = new List <JExpression> {
                            J.NewJsonArray(node2.Arguments.ToArray())
                        }
                    }
                    ;
                    //var me2 = (node2.Member as JsMemberExpression);
                    //me2.Name = "callParent";
                    return;
                }
                IMethod me2;
                var     me = res.Member;
                if (me is IProperty)
                {
                    me2 = ((IProperty)me).Getter;
                }
                else if (me is IMethod)
                {
                    me2 = (IMethod)res.Member;
                }
                else
                {
                    throw new Exception("Can't resolve method from member: " + res.Member);
                }
                ((JMemberExpression)node2.Member).PreviousMember = J.Member("super");
            }
        }
        public static bool TryGetFormattingParameters(CSharpInvocationResolveResult invocationResolveResult, InvocationExpression invocationExpression,
                                                      out Expression formatArgument, out TextLocation formatStart, out IList <Expression> arguments,
                                                      Func <IParameter, Expression, bool> argumentFilter)
        {
            if (argumentFilter == null)
            {
                argumentFilter = (p, e) => true;
            }

            formatArgument = null;
            formatStart    = default(TextLocation);
            arguments      = new List <Expression>();
            var argumentToParameterMap = invocationResolveResult.GetArgumentToParameterMap();
            var resolvedParameters     = invocationResolveResult.Member.Parameters;
            var allArguments           = invocationExpression.Arguments.ToArray();

            for (int i = 0; i < allArguments.Length; i++)
            {
                var parameterIndex = argumentToParameterMap[i];
                if (parameterIndex < 0 || parameterIndex >= resolvedParameters.Count)
                {
                    // No valid mapping for this parameter, skip it
                    continue;
                }
                var parameter = resolvedParameters[parameterIndex];
                var argument  = allArguments[i];
                if (parameter.Type.IsKnownType(KnownTypeCode.String) && parameterNames.Contains(parameter.Name))
                {
                    formatArgument = argument;
                    formatStart    = argument.StartLocation;
                }
                else if ((formatArgument != null || parameter.IsParams) && argumentFilter(parameter, argument))
                {
                    arguments.Add(argument);
                }
            }
            return(formatArgument != null);
        }
Exemple #14
0
 private JsNode VisitInvocationResolveResultAsCtor(CSharpInvocationResolveResult res)
 {
     return(new ResolveResultVisitor_Invcation {
         Compiler = Compiler, Importer = this, Project = Project
     }.VisitInvocationResolveResultAsCtor(res));
 }
Exemple #15
0
        public JsNode VisitMemberResolveResult(MemberResolveResult res)
        {
            var    me = res.Member;
            JsNode node2;
            bool   enumValuesAsNames;

            if (me == null) //TODO: dynamics
            {
                throw new NotImplementedException();
                //var node3 = Js.Member(node.MemberName);
                //if (node.Target != null)
                //    node3.PreviousMember = VisitExpression(node.Target);
                //return node3;
            }
            else if (Sk.IsEntityFunctionProperty(res.Member, res))//(Entity)node.entity))
            {
                var pe  = (IProperty)me;
                var xxx = new CSharpInvocationResolveResult(res.TargetResult, pe.Getter, null);
                var fn  = res.GetFirstNode();
                qiucw.InvokeRR2Location.Add(xxx, new qiucw.InvocationLocation {
                    FileName = fn.GetFileName(), Line = fn.StartLocation.Line
                });
                {
                    node2 = Visit(xxx);
                }
                qiucw.InvokeRR2Location.Remove(xxx);
                return(node2);
            }
            else if (me.IsEnumMember() && Sk.UseJsonEnums(me, out enumValuesAsNames))
            {
                var me2 = (IField)me;
                if (enumValuesAsNames)
                {
                    return(Js.String(SkJs.GetEntityJsName(me2)));
                }
                else
                {
                    return(Js.Value(me2.ConstantValue));
                }
            }
            //TODO: Support a way to override this (JsField.ConstantInlining=false)
            else if (res.IsCompileTimeConstant && !me.IsEnumMember())
            {
                var nodes = res.GetNodes();
                if (nodes.IsNotNullOrEmpty())
                {
                    if (nodes[0] != null)
                    {
                        bool isPrimitiveExpr = nodes[0] is PrimitiveExpression;
                        if (!isPrimitiveExpr)
                        {
                            return(Js.Value(res.ConstantValue, string.Format(" /* {0} */", nodes[0].ToString())));
                        }
                    }
                }
                return(Js.Value(res.ConstantValue));
            }
            else
            {
                var node3 = SkJs.EntityToMember(me);
                qiucw.CheckAddInvocation(res, node3.Name);
                node2 = node3;
                if (res.TargetResult != null && !me.IsStatic())
                {
                    var instanceContext = VisitExpression(res.TargetResult);
                    if (node3.Name.IsNullOrEmpty()) //support Name=""
                    {
                        node2 = instanceContext;
                    }
                    else
                    {
                        node3.PreviousMember = instanceContext;
                    }
                }
            }
            return(node2);
        }
Exemple #16
0
        private JNode VisitInvocationResolveResult(CSharpInvocationResolveResult res)
        {
            ////TODO: LET LINQ
            //var firstNode = res.GetFirstNode();
            //if (firstNode != null && firstNode is QueryLetClause)
            //{
            //    foreach (var arg in res.Arguments)
            //    {
            //        if (arg.GetInfo() == null)
            //            arg.SetInfo(new ResolveResultInfo { Nodes = { firstNode } });
            //    }
            //}
            var member = res.Member;
            var me     = member as IMethod;

            if (me == null)
            {
                var pe = member as IProperty;
                if (pe != null)
                {
                    me     = pe.Getter;
                    member = me;
                }
            }
            var att = me != null?JMeta.GetJMethodAttribute(me) : null;

            if (att != null && att.InlineCode != null)
            {
                return(J.Code(att.InlineCode));
            }
            //TODO: move defines locally
            var condAtt = me.GetMetadata <System.Diagnostics.ConditionalAttribute>();

            if (condAtt != null && Compiler != null && Compiler.Defines != null && !Compiler.Defines.Contains(condAtt.ConditionString))
            {
                return(null);
            }
            if (att != null && att.OmitCalls)
            {
                if (me.IsStatic() && !me.IsExtensionMethod)
                {
                    return(null);
                }
                if (me.IsExtensionMethod && !res.IsExtensionMethodInvocation)
                {
                    return(null);
                }
                if (res.Arguments.IsEmpty() && res.TargetResult != null)
                {
                    return(VisitExpression(res.TargetResult));
                }
                return(Visit(res.Arguments[0]));
            }
            var jsMember = JNaming.JAccess(member);

            if (res.TargetResult != null && !member.IsStatic() && member.SymbolKind != SymbolKind.Constructor) //TargetResult==null when ctor
            {
                var target = VisitExpression(res.TargetResult);
                if (jsMember.PreviousMember != null)
                {
                    throw new NotSupportedException();
                }
                jsMember.PreviousMember = target;
            }
            var bindings = res.GetArgumentsForCall2();

            if (JMeta.OmitOptionalParameters(me))
            {
                bindings.RemoveAll(t => t.ArgResult == null);
            }
            if (JMeta.IsNativeParams(me))
            {
                var binding = bindings.Where(t => t.Parameter.IsParams).FirstOrDefault();
                if (binding != null)
                {
                    if (binding.CallResult is ArrayCreateResolveResult)
                    {
                        var arrayRes = (ArrayCreateResolveResult)binding.CallResult;
                        bindings.Remove(binding);
                        if (arrayRes.InitializerElements.IsNotNullOrEmpty())
                        {
                            foreach (var init in arrayRes.InitializerElements)
                            {
                                var b = binding.Clone();
                                b.CallResult = init;
                                bindings.Add(b);
                            }
                        }
                    }
                    else
                    {
                        Log.Warn(res.GetFirstNode(), "Invalid params parameter passed to method with NativeParams=true");
                    }
                }
            }
            var        byRefs    = new List <ByReferenceResolveResult>();
            List <int> refToRefs = new List <int>();
            var        c         = 0;

            foreach (var binding in bindings)
            {
                var byRef = binding.CallResult as ByReferenceResolveResult;
                if (byRef == null)
                {
                    c++;
                    continue;
                }
                var x = byRef.ElementResult as LocalResolveResult;
                if (x != null && x.Variable != null && x.Variable.Type.Kind == TypeKind.ByReference)
                {
                    if (binding.Parameter.IsRef || binding.Parameter.IsOut)
                    {
                        refToRefs.Add(c);
                    }
                    c++;
                    continue;
                }
                byRefs.Add(byRef);
                c++;
            }
            var callArgs = bindings.Select(t => t.CallResult).ToList();
            var node2    = new JInvocationExpression
            {
                Member    = jsMember,
                Arguments = VisitExpressions(callArgs),
            };

            foreach (var i in refToRefs)
            {
                JMemberExpression jsmex = node2.Arguments[i] as JMemberExpression;
                if (jsmex != null)
                {
                    node2.Arguments[i] = jsmex.PreviousMember;//remove the .Value ref wrapper
                }
            }
            if (me != null && me.IsExtensionMethod && res.IsExtensionMethodInvocation && JMeta.ExtensionImplementedInInstance(me))
            {
                var arg = node2.Arguments[0];
                node2.Arguments.RemoveAt(0);
                if (jsMember.PreviousMember != null)
                {
                    throw new NotImplementedException();
                }
                jsMember.PreviousMember = arg;
            }

            TransformIntoBaseMethodCallIfNeeded(res, node2);
            if (att != null)
            {
                if (att.OmitParanthesis)
                {
                    node2.OmitParanthesis = true;
                }
                if (node2.Arguments == null)
                {
                    node2.Arguments = new List <JExpression>();
                }
                if (att.InsertArg2 != null)
                {
                    node2.Arguments.InsertOrAdd(2, new JCodeExpression {
                        Code = att.InsertArg2.ToString()
                    });
                }
                if (att.InsertArg1 != null)
                {
                    node2.Arguments.InsertOrAdd(1, new JCodeExpression {
                        Code = att.InsertArg1.ToString()
                    });
                }
                if (att.InsertArg0 != null)
                {
                    node2.Arguments.InsertOrAdd(0, new JCodeExpression {
                        Code = att.InsertArg0.ToString()
                    });
                }
                node2.OmitCommas      = att.OmitCommas;
                node2.ArgumentsPrefix = att.ArgumentsPrefix;
                node2.ArgumentsSuffix = att.ArgumentsSuffix;
                if (att.InstanceImplementedAsExtension)
                {
                    var ext = (JMemberExpression)node2.Member;
                    node2.Arguments.Insert(0, ext.PreviousMember);
                    ext.PreviousMember = null;
                }
            }


            //if (me != null && me is SpecializedMethod && !Sk.IgnoreGenericMethodArguments(me))
            //{
            //    List<JsExpression> genericArgs;
            //    if (me.IsConstructor)
            //    {
            //        var ce = me.DeclaringType as ParameterizedType;
            //        if (ce != null)
            //            genericArgs = ce.TypeArguments.Select(t => SkJs.EntityTypeRefToMember(t, true)).ToList();
            //        else
            //            genericArgs = new List<JsExpression>();
            //    }
            //    else
            //    {
            //        var sme = (SpecializedMethod)me;
            //        genericArgs = sme.TypeArguments.Select(t => SkJs.EntityTypeRefToMember(t, true)).ToList();
            //    }
            //    if (node2.Arguments == null)
            //        node2.Arguments = new List<JsExpression>(genericArgs);
            //    else
            //        node2.Arguments.InsertRange(0, genericArgs);
            //}
            if (att != null && att.OmitDotOperator)
            {
                if (node2.Member is JMemberExpression && node2.Arguments.Count == 1 && att.OmitParanthesis)
                {
                    var meNode = (JMemberExpression)node2.Member;
                    var node3  = new JBinaryExpression {
                        Left = meNode.PreviousMember, Operator = meNode.Name, Right = node2.Arguments[0]
                    };
                    return(node3);
                }
                else
                {
                    Log.Warn(res.GetFirstNode(), "TODO:OmitDotOperator is not supported in this syntax.");
                }
            }
            if (node2.Member is JMemberExpression)
            {
                var x = (JMemberExpression)node2.Member;
                if (x.Name.IsNullOrEmpty() && jsMember.PreviousMember != null)
                {
                    node2.Member = x.PreviousMember;
                }
            }
            if (res.Member.SymbolKind == SymbolKind.Indexer && JMeta.UseNativeIndexer((IProperty)res.Member))
            {
                var node3 = new JIndexerAccessExpression
                {
                    Member    = node2.Member,
                    Arguments = node2.Arguments,
                };

                return(node3);
            }

            if (byRefs.IsNotNullOrEmpty())
            {
                var func = J.Function();
                foreach (var byRef in byRefs)
                {
                    func.Add(J.Assign(VisitExpression(byRef), J.Json().Add("Value", VisitExpression(byRef))).Statement());
                }
                func.Add(J.Var("$res", res.Type.JAccess(), node2).Statement());
                foreach (var byRef in byRefs)
                {
                    func.Add(J.Assign(VisitExpression(byRef), VisitExpression(byRef).Member("Value")).Statement());
                }
                func.Add(J.Return(J.Member("$res")));
                var node5 = WrapFunctionAndInvoke(res, func.Block);
                return(node5);
            }


            return(node2);
        }
 public virtual TResult VisitCSharpInvocationResolveResult(CSharpInvocationResolveResult rr, TData data)
 {
     VisitChildResolveResults(rr, data);
     return(default(TResult));
 }
Exemple #18
0
        public ExpressionWithResolveResult Build(OpCode callOpCode, IMethod method, IReadOnlyList <ILInstruction> callArguments,
                                                 IType constrainedTo = null)
        {
            // Used for Call, CallVirt and NewObj
            var expectedTargetDetails = new ExpectedTargetDetails {
                CallOpCode = callOpCode
            };
            TranslatedExpression target;

            if (callOpCode == OpCode.NewObj)
            {
                target = default(TranslatedExpression);                 // no target
            }
            else
            {
                target = expressionBuilder.TranslateTarget(method, callArguments.FirstOrDefault(), callOpCode == OpCode.Call, constrainedTo);
                if (callOpCode == OpCode.CallVirt &&
                    constrainedTo == null &&
                    target.Expression is CastExpression cast &&
                    target.ResolveResult is ConversionResolveResult conversion &&
                    target.Type.IsKnownType(KnownTypeCode.Object) &&
                    conversion.Conversion.IsBoxingConversion)
                {
                    // boxing conversion on call target?
                    // let's see if we can make that implicit:
                    target = target.UnwrapChild(cast.Expression);
                    // we'll need to make sure the boxing effect is preserved
                    expectedTargetDetails.NeedsBoxingConversion = true;
                }
            }

            int firstParamIndex = (method.IsStatic || callOpCode == OpCode.NewObj) ? 0 : 1;

            // Translate arguments to the expected parameter types
            var arguments = new List <TranslatedExpression>(method.Parameters.Count);

            Debug.Assert(callArguments.Count == firstParamIndex + method.Parameters.Count);
            var  expectedParameters = method.Parameters.ToList();
            bool isExpandedForm     = false;

            for (int i = 0; i < method.Parameters.Count; i++)
            {
                var parameter = expectedParameters[i];
                var arg       = expressionBuilder.Translate(callArguments[firstParamIndex + i]);
                if (parameter.IsParams && i + 1 == method.Parameters.Count)
                {
                    // Parameter is marked params
                    // If the argument is an array creation, inline all elements into the call and add missing default values.
                    // Otherwise handle it normally.
                    if (arg.ResolveResult is ArrayCreateResolveResult acrr &&
                        acrr.SizeArguments.Count == 1 &&
                        acrr.SizeArguments[0].IsCompileTimeConstant &&
                        acrr.SizeArguments[0].ConstantValue is int length)
                    {
                        var expandedParameters = expectedParameters.Take(expectedParameters.Count - 1).ToList();
                        var expandedArguments  = new List <TranslatedExpression>(arguments);
                        if (length > 0)
                        {
                            var arrayElements = ((ArrayCreateExpression)arg.Expression).Initializer.Elements.ToArray();
                            var elementType   = ((ArrayType)acrr.Type).ElementType;
                            for (int j = 0; j < length; j++)
                            {
                                expandedParameters.Add(new DefaultParameter(elementType, parameter.Name + j));
                                if (j < arrayElements.Length)
                                {
                                    expandedArguments.Add(new TranslatedExpression(arrayElements[j]));
                                }
                                else
                                {
                                    expandedArguments.Add(expressionBuilder.GetDefaultValueExpression(elementType).WithoutILInstruction());
                                }
                            }
                        }
                        if (IsUnambiguousCall(expectedTargetDetails, method, target, Empty <IType> .Array, expandedArguments) == OverloadResolutionErrors.None)
                        {
                            isExpandedForm     = true;
                            expectedParameters = expandedParameters;
                            arguments          = expandedArguments.SelectList(a => new TranslatedExpression(a.Expression.Detach()));
                            continue;
                        }
                    }
                }

                arguments.Add(arg.ConvertTo(parameter.Type, expressionBuilder, allowImplicitConversion: true));

                if (parameter.IsOut && arguments[i].Expression is DirectionExpression dirExpr)
                {
                    dirExpr.FieldDirection = FieldDirection.Out;
                }
            }

            if (method is VarArgInstanceMethod)
            {
                int regularParameterCount = ((VarArgInstanceMethod)method).RegularParameterCount;
                var argListArg            = new UndocumentedExpression();
                argListArg.UndocumentedExpressionType = UndocumentedExpressionType.ArgList;
                int paramIndex = regularParameterCount;
                var builder    = expressionBuilder;
                argListArg.Arguments.AddRange(arguments.Skip(regularParameterCount).Select(arg => arg.ConvertTo(expectedParameters[paramIndex++].Type, builder).Expression));
                var argListRR = new ResolveResult(SpecialType.ArgList);
                arguments = arguments.Take(regularParameterCount)
                            .Concat(new[] { argListArg.WithoutILInstruction().WithRR(argListRR) }).ToList();
                method             = (IMethod)method.MemberDefinition;
                expectedParameters = method.Parameters.ToList();
            }

            var argumentResolveResults = arguments.Select(arg => arg.ResolveResult).ToList();

            ResolveResult rr = new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults, isExpandedForm: isExpandedForm);

            if (callOpCode == OpCode.NewObj)
            {
                if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType())
                {
                    var argumentExpressions            = arguments.SelectArray(arg => arg.Expression);
                    AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
                    if (CanInferAnonymousTypePropertyNamesFromArguments(argumentExpressions, expectedParameters))
                    {
                        atce.Initializers.AddRange(argumentExpressions);
                    }
                    else
                    {
                        for (int i = 0; i < argumentExpressions.Length; i++)
                        {
                            atce.Initializers.Add(
                                new NamedExpression {
                                Name       = expectedParameters[i].Name,
                                Expression = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder)
                            });
                        }
                    }
                    return(atce
                           .WithRR(rr));
                }
                else
                {
                    if (IsUnambiguousCall(expectedTargetDetails, method, target, Empty <IType> .Array, arguments) != OverloadResolutionErrors.None)
                    {
                        for (int i = 0; i < arguments.Count; i++)
                        {
                            if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType())
                            {
                                if (arguments[i].Expression is LambdaExpression lambda)
                                {
                                    ModifyReturnTypeOfLambda(lambda);
                                }
                            }
                            else
                            {
                                arguments[i] = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder);
                            }
                        }
                    }
                    return(new ObjectCreateExpression(expressionBuilder.ConvertType(method.DeclaringType), arguments.SelectArray(arg => arg.Expression))
                           .WithRR(rr));
                }
            }
            else
            {
                int allowedParamCount = (method.ReturnType.IsKnownType(KnownTypeCode.Void) ? 1 : 0);
                if (method.IsAccessor && (method.AccessorOwner.SymbolKind == SymbolKind.Indexer || expectedParameters.Count == allowedParamCount))
                {
                    return(HandleAccessorCall(expectedTargetDetails, method, target, arguments.ToList()));
                }
                else if (method.Name == "Invoke" && method.DeclaringType.Kind == TypeKind.Delegate)
                {
                    return(new InvocationExpression(target, arguments.Select(arg => arg.Expression)).WithRR(rr));
                }
                else if (IsDelegateEqualityComparison(method, arguments))
                {
                    return(HandleDelegateEqualityComparison(method, arguments)
                           .WithRR(rr));
                }
                else if (method.IsOperator && method.Name == "op_Implicit" && arguments.Count == 1)
                {
                    return(HandleImplicitConversion(method, arguments[0]));
                }
                else
                {
                    bool    requireTypeArguments = false;
                    bool    targetCasted         = false;
                    bool    argumentsCasted      = false;
                    IType[] typeArguments        = Empty <IType> .Array;

                    OverloadResolutionErrors errors;
                    while ((errors = IsUnambiguousCall(expectedTargetDetails, method, target, typeArguments, arguments)) != OverloadResolutionErrors.None)
                    {
                        switch (errors)
                        {
                        case OverloadResolutionErrors.TypeInferenceFailed:
                        case OverloadResolutionErrors.WrongNumberOfTypeArguments:
                            if (requireTypeArguments)
                            {
                                goto default;
                            }
                            requireTypeArguments = true;
                            typeArguments        = method.TypeArguments.ToArray();
                            continue;

                        default:
                            if (!argumentsCasted)
                            {
                                argumentsCasted = true;
                                for (int i = 0; i < arguments.Count; i++)
                                {
                                    if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType())
                                    {
                                        if (arguments[i].Expression is LambdaExpression lambda)
                                        {
                                            ModifyReturnTypeOfLambda(lambda);
                                        }
                                    }
                                    else
                                    {
                                        arguments[i] = arguments[i].ConvertTo(expectedParameters[i].Type, expressionBuilder);
                                    }
                                }
                            }
                            else if (!targetCasted)
                            {
                                targetCasted = true;
                                target       = target.ConvertTo(method.DeclaringType, expressionBuilder);
                            }
                            else if (!requireTypeArguments)
                            {
                                requireTypeArguments = true;
                                typeArguments        = method.TypeArguments.ToArray();
                            }
                            else
                            {
                                break;
                            }
                            continue;
                        }
                        break;
                    }

                    Expression targetExpr = target.Expression;
                    string     methodName = method.Name;
                    // HACK : convert this.Dispose() to ((IDisposable)this).Dispose(), if Dispose is an explicitly implemented interface method.
                    if (method.IsExplicitInterfaceImplementation && targetExpr is ThisReferenceExpression)
                    {
                        targetExpr = new CastExpression(expressionBuilder.ConvertType(method.ImplementedInterfaceMembers[0].DeclaringType), targetExpr);
                        methodName = method.ImplementedInterfaceMembers[0].Name;
                    }
                    var mre = new MemberReferenceExpression(targetExpr, methodName);
                    if (requireTypeArguments && (!settings.AnonymousTypes || !method.TypeArguments.Any(a => a.ContainsAnonymousType())))
                    {
                        mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
                    }
                    var argumentExpressions = arguments.Select(arg => arg.Expression);
                    return(new InvocationExpression(mre, argumentExpressions).WithRR(rr));
                }
            }
        }
Exemple #19
0
        public JsNode VisitInvocationResolveResult(CSharpInvocationResolveResult res)
        {
            Res = res;

            ProcessMember();

            if (MethodAtt != null && MethodAtt.InlineCode != null)
            {
                return(Js.CodeExpression(MethodAtt.InlineCode));
            }

            var conditional = ProcessConditional();

            if (conditional)
            {
                return(null);
            }

            bool omittedCalls;
            var  omittedCallsNode = ProcessOmitCalls(out omittedCalls);

            if (omittedCalls)
            {
                return(omittedCallsNode);
            }

            JsMember = SkJs.EntityToMember(Member);

            qiucw.CheckAddInvocation(res, JsMember.Name);

            ProcessTarget();

            ProcessPrmBindings();

            ProcessNativeParams();

            ProcessByRefs1();

            PrmBindings.ForEach(t => t.JsCallResult = VisitExpression(t.Binding.CallResult));
            Node2 = new JsInvocationExpression
            {
                Member    = JsMember,
                Arguments = PrmBindings.Select(t => t.JsCallResult).ToList(),
            };

            ProcessByRefs2();

            ProcessExtensionImplementedInInstance();

            TransformIntoBaseMethodCallIfNeeded(Res, Node2);

            ProcessArgsCustomization();

            ProcessGenericMethodArgs();

            var inlineCodeExpression = ProcessInlineCodeExpression();

            if (inlineCodeExpression != null)
            {
                return(inlineCodeExpression);
            }



            var omittedDotOperator = ProcessOmitDotOperator();

            if (omittedDotOperator != null)
            {
                return(omittedDotOperator);
            }

            ProcessRemoveEmptyPreviousMemberName();

            var indexerAccess = ProcessIndexer();

            if (indexerAccess != null)
            {
                return(indexerAccess);
            }

            ProcessByRefs3();

            return(Node2);
        }
Exemple #20
0
        private JNode VisitInvocationResolveResultAsCtor(CSharpInvocationResolveResult res)
        {
            if (res.Type.Kind == TypeKind.Delegate)
            {
                return(Visit(res.Arguments.Single()));
            }
            var me    = (IMethod)res.Member;
            var meAtt = JMeta.GetJMethodAttribute(me);
            var ce    = me.GetDeclaringTypeDefinition();
            var att   = ce == null ? null : ce.GetJsTypeAttribute();

            if (att != null && att.Mode == JsMode.Json && (meAtt == null || meAtt.Name == null))
            {
                var node2 = VisitInvocationResolveResult(res);
                var json  = InitializersToJson(res.InitializerStatements, res.Type);
                return(json);
            }
            else
            {
                var invokeExp = (JInvocationExpression)VisitInvocationResolveResult(res);
                var newExp    = new JNewObjectExpression {
                    Invocation = invokeExp
                };
                JExpression finalExp;
                if (meAtt != null && meAtt.OmitNewOperator)
                {
                    finalExp = invokeExp;
                }
                else
                {
                    finalExp = newExp;
                }

                if (meAtt != null && meAtt.JsonInitializers)
                {
                    var json = InitializersToJson(res.InitializerStatements, res.Type);
                    invokeExp.Arguments.Add(json);
                }
                else if (res.InitializerStatements.IsNotNullOrEmpty())
                {
                    //var func = J.Function();
                    var func   = J.Block();
                    var inits2 = res.InitializerStatements.Select(t => Visit(t)).ToList();
                    var init1  = res.InitializerStatements[0];

                    var target  = FindInitializedObjectResolveResult(res);// ((init1 as OperatorResolveResult).Operands[0] as MemberResolveResult).TargetResult as InitializedObjectResolveResult;
                    var varName = Initializers[target];
                    func.Add(J.Var(varName, res.Type.JAccess(), finalExp).Statement());

                    foreach (var init in inits2)
                    {
                        var exp = ((JExpression)init);
                        func.Add(exp.Statement());
                    }
                    func.Add(J.Return(J.Member(varName)));
                    finalExp = WrapFunctionAndInvoke(res, func);
                }

                return(finalExp);
            }
        }
Exemple #21
0
        protected void VisitMemberReferenceExpression()
        {
            MemberReferenceExpression memberReferenceExpression = this.MemberReferenceExpression;
            int pos = this.Emitter.Output.Length;

            ResolveResult resolveResult           = null;
            ResolveResult expressionResolveResult = null;
            string        targetVar     = null;
            string        valueVar      = null;
            bool          isStatement   = false;
            bool          isConstTarget = false;

            var targetrr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Target, this.Emitter);

            if (targetrr is ConstantResolveResult)
            {
                isConstTarget = true;
            }

            var memberTargetrr = targetrr as MemberResolveResult;

            if (memberTargetrr != null && memberTargetrr.Type.Kind == TypeKind.Enum && memberTargetrr.Member is DefaultResolvedField && this.Emitter.Validator.EnumEmitMode(memberTargetrr.Type) == 2)
            {
                isConstTarget = true;
            }

            if (memberReferenceExpression.Parent is InvocationExpression && (((InvocationExpression)(memberReferenceExpression.Parent)).Target == memberReferenceExpression))
            {
                resolveResult           = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter);
                expressionResolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter);

                if (expressionResolveResult is InvocationResolveResult)
                {
                    resolveResult = expressionResolveResult;
                }
            }
            else
            {
                resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter);
            }

            bool oldIsAssignment = this.Emitter.IsAssignment;
            bool oldUnary        = this.Emitter.IsUnaryAccessor;

            if (resolveResult == null)
            {
                this.Emitter.IsAssignment    = false;
                this.Emitter.IsUnaryAccessor = false;
                if (isConstTarget)
                {
                    this.Write("(");
                }
                memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                if (isConstTarget)
                {
                    this.Write(")");
                }
                this.Emitter.IsAssignment    = oldIsAssignment;
                this.Emitter.IsUnaryAccessor = oldUnary;
                this.WriteDot();
                string name = memberReferenceExpression.MemberName;
                this.Write(name.ToLowerCamelCase());

                return;
            }

            if (resolveResult is DynamicInvocationResolveResult)
            {
                resolveResult = ((DynamicInvocationResolveResult)resolveResult).Target;
            }

            if (resolveResult is MethodGroupResolveResult)
            {
                var oldResult = (MethodGroupResolveResult)resolveResult;
                resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter);

                if (resolveResult is DynamicInvocationResolveResult)
                {
                    var method = oldResult.Methods.Last();
                    resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method);
                }
            }

            MemberResolveResult member = resolveResult as MemberResolveResult;
            var globalTarget           = member != null?this.Emitter.IsGlobalTarget(member.Member) : null;

            if (globalTarget != null && globalTarget.Item1)
            {
                var target = globalTarget.Item2;

                if (!string.IsNullOrWhiteSpace(target))
                {
                    bool assign           = false;
                    var  memberExpression = member.Member is IMethod ? memberReferenceExpression.Parent.Parent : memberReferenceExpression.Parent;
                    var  targetExpression = member.Member is IMethod ? memberReferenceExpression.Parent : memberReferenceExpression;
                    var  assignment       = memberExpression as AssignmentExpression;
                    if (assignment != null && assignment.Right == targetExpression)
                    {
                        assign = true;
                    }
                    else
                    {
                        var varInit = memberExpression as VariableInitializer;
                        if (varInit != null && varInit.Initializer == targetExpression)
                        {
                            assign = true;
                        }
                        else if (memberExpression is InvocationExpression)
                        {
                            var targetInvocation = (InvocationExpression)memberExpression;
                            if (targetInvocation.Arguments.Any(a => a == targetExpression))
                            {
                                assign = true;
                            }
                        }
                    }

                    if (assign)
                    {
                        if (resolveResult is InvocationResolveResult)
                        {
                            this.PushWriter(target);
                        }
                        else
                        {
                            this.Write(target);
                        }

                        return;
                    }
                }

                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter("");
                }

                return;
            }

            Tuple <bool, bool, string> inlineInfo = member != null?this.Emitter.GetInlineCode(memberReferenceExpression) : null;

            //string inline = member != null ? this.Emitter.GetInline(member.Member) : null;
            string inline    = inlineInfo != null ? inlineInfo.Item3 : null;
            bool   hasInline = !string.IsNullOrEmpty(inline);
            bool   hasThis   = hasInline && inline.Contains("{this}");

            if (hasThis)
            {
                this.Write("");
                var oldBuilder = this.Emitter.Output;
                this.Emitter.Output          = new StringBuilder();
                this.Emitter.IsAssignment    = false;
                this.Emitter.IsUnaryAccessor = false;
                if (isConstTarget)
                {
                    this.Write("(");
                }
                memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                if (isConstTarget)
                {
                    this.Write(")");
                }
                this.Emitter.IsAssignment    = oldIsAssignment;
                this.Emitter.IsUnaryAccessor = oldUnary;
                inline = inline.Replace("{this}", this.Emitter.Output.ToString());
                this.Emitter.Output = oldBuilder;

                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter(inline);
                }
                else
                {
                    if (member != null && member.Member is IMethod)
                    {
                        throw new EmitterException(memberReferenceExpression, "The templated method (" + member.Member.FullName + ") cannot be used like reference");
                    }
                    else
                    {
                        this.Write(inline);
                    }
                }

                return;
            }

            if (member != null && member.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(member.Member) && this.Emitter.IsInlineConst(member.Member))
            {
                this.WriteScript(member.ConstantValue);
            }
            else if (hasInline && member.Member.IsStatic)
            {
                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter(inline);
                }
                else
                {
                    if (member != null && member.Member is IMethod)
                    {
                        var r     = new Regex(@"([$\w\.]+)\(\s*\S.*\)");
                        var match = r.Match(inline);

                        if (match.Success)
                        {
                            this.Write(match.Groups[1].Value);
                        }
                        else
                        {
                            throw new EmitterException(memberReferenceExpression, "The templated method (" + member.Member.FullName + ") cannot be used like reference");
                        }
                    }
                    else
                    {
                        new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit();
                    }
                }
            }
            else
            {
                if (member != null && member.IsCompileTimeConstant && member.Member.DeclaringType.Kind == TypeKind.Enum)
                {
                    var typeDef = member.Member.DeclaringType as DefaultResolvedTypeDefinition;

                    if (typeDef != null)
                    {
                        var enumMode = this.Emitter.Validator.EnumEmitMode(typeDef);

                        if ((this.Emitter.Validator.IsIgnoreType(typeDef) && enumMode == -1) || enumMode == 2)
                        {
                            this.WriteScript(member.ConstantValue);

                            return;
                        }

                        if (enumMode >= 3)
                        {
                            string enumStringName = member.Member.Name;
                            var    attr           = Helpers.GetInheritedAttribute(member.Member, Translator.Bridge_ASSEMBLY + ".NameAttribute");

                            if (attr != null)
                            {
                                enumStringName = this.Emitter.GetEntityName(member.Member);
                            }
                            else
                            {
                                switch (enumMode)
                                {
                                case 3:
                                    enumStringName = Object.Net.Utilities.StringUtils.ToLowerCamelCase(member.Member.Name);
                                    break;

                                case 4:
                                    break;

                                case 5:
                                    enumStringName = enumStringName.ToLowerInvariant();
                                    break;

                                case 6:
                                    enumStringName = enumStringName.ToUpperInvariant();
                                    break;
                                }
                            }

                            this.WriteScript(enumStringName);

                            return;
                        }
                    }
                }

                if (resolveResult is TypeResolveResult)
                {
                    TypeResolveResult typeResolveResult = (TypeResolveResult)resolveResult;
                    var isNative = this.Emitter.Validator.IsIgnoreType(typeResolveResult.Type.GetDefinition());
                    if (isNative)
                    {
                        this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter));
                    }
                    else
                    {
                        this.Write("Bridge.get(" + BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter) + ")");
                    }

                    return;
                }
                else if (member != null &&
                         member.Member is IMethod &&
                         !(member is InvocationResolveResult) &&
                         !(
                             memberReferenceExpression.Parent is InvocationExpression &&
                             memberReferenceExpression.NextSibling != null &&
                             memberReferenceExpression.NextSibling.Role is TokenRole &&
                             ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "("
                             )
                         )
                {
                    var  resolvedMethod = (IMethod)member.Member;
                    bool isStatic       = resolvedMethod != null && resolvedMethod.IsStatic;

                    var isExtensionMethod = resolvedMethod.IsExtensionMethod;

                    this.Emitter.IsAssignment    = false;
                    this.Emitter.IsUnaryAccessor = false;

                    if (!isStatic)
                    {
                        this.Write(Bridge.Translator.Emitter.ROOT + "." + (isExtensionMethod ? Bridge.Translator.Emitter.DELEGATE_BIND_SCOPE : Bridge.Translator.Emitter.DELEGATE_BIND) + "(");
                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                        this.Write(", ");
                    }

                    this.Emitter.IsAssignment    = oldIsAssignment;
                    this.Emitter.IsUnaryAccessor = oldUnary;

                    if (isExtensionMethod)
                    {
                        this.Write(BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter));
                    }
                    else
                    {
                        this.Emitter.IsAssignment    = false;
                        this.Emitter.IsUnaryAccessor = false;
                        if (isConstTarget)
                        {
                            this.Write("(");
                        }
                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                        if (isConstTarget)
                        {
                            this.Write(")");
                        }
                        this.Emitter.IsAssignment    = oldIsAssignment;
                        this.Emitter.IsUnaryAccessor = oldUnary;
                    }

                    this.WriteDot();

                    this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName());

                    if (!isStatic)
                    {
                        this.Write(")");
                    }

                    return;
                }
                else
                {
                    bool isProperty = false;

                    if (member != null && member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition))
                    {
                        isProperty = true;
                        bool writeTargetVar = false;

                        if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign)
                        {
                            writeTargetVar = true;
                        }
                        else if (this.Emitter.IsUnaryAccessor)
                        {
                            writeTargetVar = true;

                            isStatement = memberReferenceExpression.Parent is UnaryOperatorExpression && memberReferenceExpression.Parent.Parent is ExpressionStatement;

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

                            if (!isStatement)
                            {
                                this.WriteOpenParentheses();
                            }
                        }

                        if (writeTargetVar)
                        {
                            bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult);

                            if (!(targetrr is ThisResolveResult || targetrr is TypeResolveResult || targetrr is LocalResolveResult || isField))
                            {
                                targetVar = this.GetTempVarName();

                                this.Write(targetVar);
                                this.Write(" = ");
                            }
                        }
                    }

                    if (isProperty && this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null)
                    {
                        valueVar = this.GetTempVarName();

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

                    this.Emitter.IsAssignment    = false;
                    this.Emitter.IsUnaryAccessor = false;
                    if (isConstTarget)
                    {
                        this.Write("(");
                    }
                    memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                    if (isConstTarget)
                    {
                        this.Write(")");
                    }
                    this.Emitter.IsAssignment    = oldIsAssignment;
                    this.Emitter.IsUnaryAccessor = oldUnary;

                    if (targetVar != null)
                    {
                        if (this.Emitter.IsUnaryAccessor && !isStatement)
                        {
                            this.WriteComma(false);

                            valueVar = this.GetTempVarName();

                            this.Write(valueVar);
                            this.Write(" = ");

                            this.Write(targetVar);
                        }
                        else
                        {
                            this.WriteSemiColon();
                            this.WriteNewLine();
                            this.Write(targetVar);
                        }
                    }
                }

                var targetResolveResult = targetrr as MemberResolveResult;

                if (targetResolveResult == null || this.Emitter.IsGlobalTarget(targetResolveResult.Member) == null)
                {
                    this.WriteDot();
                }

                if (member == null)
                {
                    if (targetrr != null && targetrr.Type.Kind == TypeKind.Dynamic)
                    {
                        this.Write(memberReferenceExpression.MemberName);
                    }
                    else
                    {
                        this.Write(memberReferenceExpression.MemberName.ToLowerCamelCase());
                    }
                }
                else if (!string.IsNullOrEmpty(inline))
                {
                    if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment))
                    {
                        this.PushWriter(inline);
                    }
                    else
                    {
                        this.Write(inline);
                    }
                }
                else if (member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition))
                {
                    var proto = false;
                    if (this.MemberReferenceExpression.Target is BaseReferenceExpression && member != null)
                    {
                        var prop = member.Member as IProperty;

                        if (prop != null && (prop.IsVirtual || prop.IsOverride))
                        {
                            proto = true;
                        }
                    }

                    if (Helpers.IsFieldProperty(member.Member, this.Emitter))
                    {
                        this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter));
                    }
                    else if (!this.Emitter.IsAssignment)
                    {
                        if (this.Emitter.IsUnaryAccessor)
                        {
                            bool isNullable = NullableType.IsNullable(member.Member.ReturnType);
                            bool isDecimal  = Helpers.IsDecimalType(member.Member.ReturnType, this.Emitter.Resolver);

                            if (isStatement)
                            {
                                this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true));
                                if (proto)
                                {
                                    this.Write(".call");
                                    this.WriteOpenParentheses();
                                    this.WriteThis();
                                    this.WriteComma();
                                }
                                else
                                {
                                    this.WriteOpenParentheses();
                                }

                                if (isDecimal)
                                {
                                    if (isNullable)
                                    {
                                        this.Write("Bridge.Nullable.lift1");
                                        this.WriteOpenParentheses();
                                        if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                        {
                                            this.WriteScript("inc");
                                        }
                                        else
                                        {
                                            this.WriteScript("dec");
                                        }

                                        this.WriteComma();

                                        if (targetVar != null)
                                        {
                                            this.Write(targetVar);
                                        }
                                        else
                                        {
                                            memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                        }

                                        this.WriteDot();

                                        this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));

                                        if (proto)
                                        {
                                            this.Write(".call");
                                            this.WriteOpenParentheses();
                                            this.WriteThis();
                                            this.WriteCloseParentheses();
                                        }
                                        else
                                        {
                                            this.WriteOpenParentheses();
                                            this.WriteCloseParentheses();
                                        }

                                        this.WriteCloseParentheses();
                                    }
                                    else
                                    {
                                        if (targetVar != null)
                                        {
                                            this.Write(targetVar);
                                        }
                                        else
                                        {
                                            memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                        }

                                        this.WriteDot();

                                        this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));

                                        if (proto)
                                        {
                                            this.Write(".call");
                                            this.WriteOpenParentheses();
                                            this.WriteThis();
                                            this.WriteCloseParentheses();
                                        }
                                        else
                                        {
                                            this.WriteOpenParentheses();
                                            this.WriteCloseParentheses();
                                        }

                                        this.WriteDot();

                                        if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                        {
                                            this.Write("inc");
                                        }
                                        else
                                        {
                                            this.Write("dec");
                                        }

                                        this.WriteOpenParentheses();
                                        this.WriteCloseParentheses();

                                        this.WriteCloseParentheses();
                                    }
                                }
                                else
                                {
                                    if (targetVar != null)
                                    {
                                        this.Write(targetVar);
                                    }
                                    else
                                    {
                                        if (isConstTarget)
                                        {
                                            this.Write("(");
                                        }
                                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                        if (isConstTarget)
                                        {
                                            this.Write(")");
                                        }
                                    }

                                    this.WriteDot();

                                    this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));

                                    if (proto)
                                    {
                                        this.Write(".call");
                                        this.WriteOpenParentheses();
                                        this.WriteThis();
                                        this.WriteCloseParentheses();
                                    }
                                    else
                                    {
                                        this.WriteOpenParentheses();
                                        this.WriteCloseParentheses();
                                    }

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

                                    this.Write("1");
                                    this.WriteCloseParentheses();
                                }
                            }
                            else
                            {
                                this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));
                                if (proto)
                                {
                                    this.Write(".call");
                                    this.WriteOpenParentheses();
                                    this.WriteThis();
                                    this.WriteCloseParentheses();
                                }
                                else
                                {
                                    this.WriteOpenParentheses();
                                    this.WriteCloseParentheses();
                                }
                                this.WriteComma();

                                if (targetVar != null)
                                {
                                    this.Write(targetVar);
                                }
                                else
                                {
                                    if (isConstTarget)
                                    {
                                        this.Write("(");
                                    }
                                    memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                    if (isConstTarget)
                                    {
                                        this.Write(")");
                                    }
                                }

                                this.WriteDot();
                                this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true));

                                if (proto)
                                {
                                    this.Write(".call");
                                    this.WriteOpenParentheses();
                                    this.WriteThis();
                                    this.WriteComma();
                                }
                                else
                                {
                                    this.WriteOpenParentheses();
                                }

                                if (isDecimal)
                                {
                                    if (isNullable)
                                    {
                                        this.Write("Bridge.Nullable.lift1");
                                        this.WriteOpenParentheses();
                                        if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                        {
                                            this.WriteScript("inc");
                                        }
                                        else
                                        {
                                            this.WriteScript("dec");
                                        }
                                        this.WriteComma();
                                        this.Write(valueVar);
                                        this.WriteCloseParentheses();
                                    }
                                    else
                                    {
                                        this.Write(valueVar);
                                        this.WriteDot();
                                        if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                        {
                                            this.Write("inc");
                                        }
                                        else
                                        {
                                            this.Write("dec");
                                        }
                                        this.WriteOpenParentheses();
                                        this.WriteCloseParentheses();
                                    }
                                }
                                else
                                {
                                    this.Write(valueVar);

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

                                this.WriteCloseParentheses();
                                this.WriteComma();

                                bool isPreOp = this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                               this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement;

                                if (isPreOp)
                                {
                                    if (targetVar != null)
                                    {
                                        this.Write(targetVar);
                                    }
                                    else
                                    {
                                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                    }
                                    this.WriteDot();
                                    this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));
                                    this.WriteOpenParentheses();
                                    this.WriteCloseParentheses();
                                }
                                else
                                {
                                    this.Write(valueVar);
                                }
                                this.WriteCloseParentheses();

                                if (valueVar != null)
                                {
                                    this.RemoveTempVar(valueVar);
                                }
                            }

                            if (targetVar != null)
                            {
                                this.RemoveTempVar(targetVar);
                            }
                        }
                        else
                        {
                            this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter));
                            if (proto)
                            {
                                this.Write(".call");
                                this.WriteOpenParentheses();
                                this.WriteThis();
                                this.WriteCloseParentheses();
                            }
                            else
                            {
                                this.WriteOpenParentheses();
                                this.WriteCloseParentheses();
                            }
                        }
                    }
                    else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign)
                    {
                        if (targetVar != null)
                        {
                            this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true),
                                                          proto ? ".call(this, " : "(",
                                                          targetVar,
                                                          ".",
                                                          Helpers.GetPropertyRef(member.Member, this.Emitter, false),
                                                          proto ? ".call(this)" : "()",
                                                          "{0})"), () =>
                            {
                                this.RemoveTempVar(targetVar);
                            });
                        }
                        else
                        {
                            var oldWriter = this.SaveWriter();
                            this.NewWriter();

                            this.Emitter.IsAssignment    = false;
                            this.Emitter.IsUnaryAccessor = false;
                            memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                            this.Emitter.IsAssignment    = oldIsAssignment;
                            this.Emitter.IsUnaryAccessor = oldUnary;
                            var trg = this.Emitter.Output.ToString();

                            this.RestoreWriter(oldWriter);
                            this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true),
                                                          proto ? ".call(this, " : "(",
                                                          trg,
                                                          ".",
                                                          Helpers.GetPropertyRef(member.Member, this.Emitter, false),
                                                          proto ? ".call(this)" : "()",
                                                          "{0})"));
                        }
                    }
                    else
                    {
                        if (proto)
                        {
                            this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + ".call(this, {0})");
                        }
                        else
                        {
                            this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + "({0})");
                        }
                    }
                }
                else if (member.Member.SymbolKind == SymbolKind.Field)
                {
                    bool isConst = this.Emitter.IsMemberConst(member.Member);

                    if (isConst && this.Emitter.IsInlineConst(member.Member))
                    {
                        this.WriteScript(member.ConstantValue);
                    }
                    else
                    {
                        this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName());
                    }
                }
                else if (resolveResult is InvocationResolveResult)
                {
                    InvocationResolveResult       invocationResult  = (InvocationResolveResult)resolveResult;
                    CSharpInvocationResolveResult cInvocationResult = (CSharpInvocationResolveResult)resolveResult;
                    var expresssionMember = expressionResolveResult as MemberResolveResult;

                    if (expresssionMember != null &&
                        cInvocationResult != null &&
                        cInvocationResult.IsDelegateInvocation &&
                        invocationResult.Member != expresssionMember.Member)
                    {
                        this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName());
                    }
                    else
                    {
                        this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName());
                    }
                }
                else if (member.Member is DefaultResolvedEvent)
                {
                    if (this.Emitter.IsAssignment &&
                        (this.Emitter.AssignmentType == AssignmentOperatorType.Add ||
                         this.Emitter.AssignmentType == AssignmentOperatorType.Subtract))
                    {
                        this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove");
                        this.Write(
                            OverloadsCollection.Create(this.Emitter, member.Member,
                                                       this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName());
                        this.WriteOpenParentheses();
                    }
                    else
                    {
                        this.Write(this.Emitter.GetEntityName(member.Member, true));
                    }
                }
                else
                {
                    this.Write(this.Emitter.GetEntityName(member.Member));
                }

                Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this, pos);
            }
        }
Exemple #22
0
        public static bool TryGetFormattingParameters(CSharpInvocationResolveResult invocationResolveResult, InvocationExpression invocationExpression,
                                                      out Expression formatArgument, out IList <Expression> arguments,
                                                      Func <IParameter, Expression, bool> argumentFilter)
        {
            if (argumentFilter == null)
            {
                argumentFilter = (p, e) => true;
            }

            formatArgument = null;
            arguments      = new List <Expression>();

            // Serach for method of type: void Name(string format, params object[] args);
            if (invocationResolveResult.Member.SymbolKind == SymbolKind.Method && invocationResolveResult.Member.DeclaringType != null)
            {
                var methods = invocationResolveResult.Member.DeclaringType.GetMethods(m => m.Name == invocationResolveResult.Member.Name).ToList();
                if (!methods.Any(m => m.Parameters.Count == 2 &&
                                 m.Parameters[0].Type.IsKnownType(KnownTypeCode.String) && parameterNames.Contains(m.Parameters[0].Name) &&
                                 m.Parameters[1].IsParams))
                {
                    return(false);
                }
            }

            var argumentToParameterMap = invocationResolveResult.GetArgumentToParameterMap();
            var resolvedParameters     = invocationResolveResult.Member.Parameters;
            var allArguments           = invocationExpression.Arguments.ToArray();

            for (int i = 0; i < allArguments.Length; i++)
            {
                var parameterIndex = argumentToParameterMap[i];
                if (parameterIndex < 0 || parameterIndex >= resolvedParameters.Count)
                {
                    // No valid mapping for this argument, skip it
                    continue;
                }
                var parameter = resolvedParameters[parameterIndex];
                var argument  = allArguments[i];
                if (i == 0 && parameter.Type.IsKnownType(KnownTypeCode.String) && parameterNames.Contains(parameter.Name))
                {
                    formatArgument = argument;
                }
                else if (formatArgument != null && parameter.IsParams && !invocationResolveResult.IsExpandedForm)
                {
                    if (!(argument is ArrayCreateExpression ace) || ace.Initializer.IsNull)
                    {
                        return(false);
                    }
                    foreach (var element in ace.Initializer.Elements)
                    {
                        if (argumentFilter(parameter, element))
                        {
                            arguments.Add(argument);
                        }
                    }
                }
                else if (formatArgument != null && argumentFilter(parameter, argument))
                {
                    arguments.Add(argument);
                }
            }
            return(formatArgument != null);
        }
        public override void VisitInvocationExpression(InvocationExpression invocationExpression)
        {
            base.VisitInvocationExpression(invocationExpression);
            var method = invocationExpression.GetSymbol() as IMethod;

            if (method == null || !method.IsExtensionMethod || !invocationExpression.Arguments.Any())
            {
                return;
            }
            IReadOnlyList <IType>     typeArguments;
            MemberReferenceExpression memberRefExpr;

            switch (invocationExpression.Target)
            {
            case MemberReferenceExpression mre:
                typeArguments = mre.TypeArguments.Any() ? method.TypeArguments : EmptyList <IType> .Instance;
                memberRefExpr = mre;
                break;

            case IdentifierExpression ide:
                typeArguments = ide.TypeArguments.Any() ? method.TypeArguments : EmptyList <IType> .Instance;
                memberRefExpr = null;
                break;

            default: return;
            }

            var firstArgument = invocationExpression.Arguments.First();

            if (firstArgument is NamedArgumentExpression)
            {
                return;
            }
            var target = firstArgument.GetResolveResult();

            if (target is ConstantResolveResult crr && crr.ConstantValue == null)
            {
                target = new ConversionResolveResult(method.Parameters[0].Type, crr, Conversion.NullLiteralConversion);
            }
            ResolveResult[] args     = new ResolveResult[invocationExpression.Arguments.Count - 1];
            string[]        argNames = null;
            int             pos      = 0;

            foreach (var arg in invocationExpression.Arguments.Skip(1))
            {
                if (arg is NamedArgumentExpression nae)
                {
                    if (argNames == null)
                    {
                        argNames = new string[args.Length];
                    }
                    argNames[pos] = nae.Name;
                    args[pos]     = nae.Expression.GetResolveResult();
                }
                else
                {
                    args[pos] = arg.GetResolveResult();
                }
                pos++;
            }
            if (!CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args, argNames))
            {
                return;
            }
            if (firstArgument is DirectionExpression dirExpr)
            {
                if (!context.Settings.RefExtensionMethods || dirExpr.FieldDirection == FieldDirection.Out)
                {
                    return;
                }
                firstArgument = dirExpr.Expression;
                target        = firstArgument.GetResolveResult();
                dirExpr.Detach();
            }
            else if (firstArgument is NullReferenceExpression)
            {
                Debug.Assert(context.RequiredNamespacesSuperset.Contains(method.Parameters[0].Type.Namespace));
                firstArgument = firstArgument.ReplaceWith(expr => new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.Parameters[0].Type), expr.Detach()));
            }
            if (invocationExpression.Target is IdentifierExpression identifierExpression)
            {
                identifierExpression.Detach();
                memberRefExpr = new MemberReferenceExpression(firstArgument.Detach(), method.Name, identifierExpression.TypeArguments.Detach());
                invocationExpression.Target = memberRefExpr;
            }
            else
            {
                memberRefExpr.Target = firstArgument.Detach();
            }
            if (invocationExpression.GetResolveResult() is CSharpInvocationResolveResult irr)
            {
                // do not forget to update the CSharpInvocationResolveResult => set IsExtensionMethodInvocation == true
                invocationExpression.RemoveAnnotations <CSharpInvocationResolveResult>();
                var newResolveResult = new CSharpInvocationResolveResult(
                    irr.TargetResult, irr.Member, irr.Arguments, irr.OverloadResolutionErrors,
                    isExtensionMethodInvocation: true, irr.IsExpandedForm, irr.IsDelegateInvocation,
                    irr.GetArgumentToParameterMap(), irr.InitializerStatements);
                invocationExpression.AddAnnotation(newResolveResult);
            }
        }
Exemple #24
0
        public JsNode VisitInvocationResolveResultAsCtor(CSharpInvocationResolveResult res)
        {
            if (res.Type.Kind == TypeKind.Delegate)
            {
                return(Visit(res.Arguments.Single()));
            }
            var me    = (IMethod)res.Member;
            var meAtt = Sk.GetJsMethodAttribute(me);
            var ce    = me.GetDeclaringTypeDefinition();
            var att   = ce == null ? null : ce.GetJsTypeAttribute();

            if (att != null && att.Mode == JsMode.Json && (meAtt == null || meAtt.Name == null))
            {
                var jtfn  = ce == null ? null : Sk.GetJsonTypeFieldName(ce);
                var node2 = VisitInvocationResolveResult(res);
                var json  = Importer.InitializersToJson(res.InitializerStatements, res.Type);
                if (jtfn != null)
                {
                    var x = json as JsJsonObjectExpression;
                    if (x != null)
                    {
                        x.Add(jtfn, SkJs.EntityTypeRefToMember(res.Type));
                    }
                }
                return(json);
            }
            else
            {
                var invokeExp = (JsInvocationExpression)VisitInvocationResolveResult(res);
                var newExp    = new JsNewObjectExpression {
                    Invocation = invokeExp
                };
                JsExpression finalExp;
                if (meAtt != null && meAtt.OmitNewOperator)
                {
                    finalExp = invokeExp;
                }
                else
                {
                    finalExp = newExp;
                }

                if (meAtt != null && meAtt.JsonInitializers)
                {
                    var json = Importer.InitializersToJson(res.InitializerStatements, res.Type);
                    invokeExp.Arguments.Add(json);
                }
                else if (res.InitializerStatements.IsNotNullOrEmpty())
                {
                    var func = Js.Function();

                    var inits2 = res.InitializerStatements.Select(t => Visit(t)).ToList();
                    //var init1 = res.InitializerStatements[0];

                    var target  = AstNodeConverter.FindInitializedObjectResolveResult(res);// ((init1 as OperatorResolveResult).Operands[0] as MemberResolveResult).TargetResult as InitializedObjectResolveResult;
                    var varName = Importer.Initializers[target];
                    func.Add(Js.Var(varName, finalExp).Statement());

                    foreach (var init in inits2)
                    {
                        var exp = ((JsExpression)init);
                        func.Add(exp.Statement());
                    }
                    func.Add(Js.Return(Js.Member(varName)));
                    finalExp = Importer.WrapFunctionAndInvoke(res, func);
                }

                return(finalExp);
            }
        }
Exemple #25
0
        void TransformIntoBaseMethodCallIfNeeded(CSharpInvocationResolveResult res, JsInvocationExpression node2)
        {
            var target = res.TargetResult as ThisResolveResult;

            if (target != null && target.CausesNonVirtualInvocation) //base.
            {
                //var info = res.GetInfo();
                //var node = info.Nodes.FirstOrDefault();
                var ce = target.Type;// node.FindThisEntity();
                if (ce != null && Sk.IsExtJsType(ce.GetDefinitionOrArrayType()))
                {
                    node2.Member = Js.This().Member("callParent");
                    if (node2.Arguments.IsNotNullOrEmpty())
                    {
                        node2.Arguments = new List <JsExpression> {
                            Js.NewJsonArray(node2.Arguments.ToArray())
                        }
                    }
                    ;
                    //var me2 = (node2.Member as JsMemberExpression);
                    //me2.Name = "callParent";
                    return;
                }
                IMethod me2;
                var     me = res.Member;
                if (me is IProperty)
                {
                    me2 = ((IProperty)me).Getter;
                }
                else if (me is IMethod)
                {
                    me2 = (IMethod)res.Member;
                }
                else
                {
                    throw new Exception("Can't resolve method from member: " + res.Member);
                }
                var member = SkJs.EntityMethodToJsFunctionRef(me2);
                member       = member.Member("call");
                node2.Member = member;
                if (node2.Arguments == null)
                {
                    node2.Arguments = new List <JsExpression>();
                }
                node2.Arguments.Insert(0, Js.This());
            }
        }

        void ProcessByRefs1()
        {
            ByRefs       = new List <ByReferenceResolveResult>();
            ByRefIndexes = new List <int>();
            RefToRefs    = new List <int>();
            var c = 0;

            foreach (var bin in PrmBindings)
            {
                var binding = bin.Binding;
                var byRef   = binding.CallResult as ByReferenceResolveResult;
                if (byRef == null)
                {
                    c++;
                    continue;
                }
                var x = byRef.ElementResult as LocalResolveResult;
                if (x != null && x.Variable != null && x.Variable.Type.Kind == TypeKind.ByReference)
                {
                    if (binding.Parameter.IsRef || binding.Parameter.IsOut)
                    {
                        RefToRefs.Add(c);
                    }
                    c++;
                    continue;
                }
                ByRefs.Add(byRef);
                ByRefIndexes.Add(c);
                c++;
            }
        }

        void ProcessByRefs2()
        {
            var c = 0;

            for (var i = 0; i < Node2.Arguments.Count; i++)
            {
                if (Node2.Arguments[i] is JsMemberExpression)
                {
                    JsMemberExpression jsmex = Node2.Arguments[i] as JsMemberExpression;
                    if (RefToRefs.Contains(i))
                    {
                        Node2.Arguments[i] = jsmex.PreviousMember; //remove the .Value ref wrapper
                    }
                    else if (ByRefIndexes.Contains(i))
                    {
                        Node2.Arguments[i] = Js.Member(RefIndexToName(c));
                        c++;
                    }
                }
                else if (Node2.Arguments[i] is JsIndexerAccessExpression)
                {
                    if (ByRefIndexes.Contains(i))
                    {
                        Node2.Arguments[i] = Js.Member(RefIndexToName(c));
                        c++;
                    }
                }
            }
        }

        void ProcessByRefs3()
        {
            if (ByRefs.IsNotNullOrEmpty())
            {
                var func = Js.Function();

                //It must assigned to a temporary variable, because typed arrays do not acceppt json.
                //调整原来使用临时对象.Value的赋值方式,修改为Object.defineProperty定义get|set方法的实现
                //临时对象统一调用jsclr里的$Ref方法进行创建
                for (var i = 0; i < ByRefs.Count; i++)
                {
                    var byRef = ByRefs[i];
                    var expr  = VisitExpression(byRef);
                    if (expr is JsMemberExpression)
                    {
                        var memberExpr = expr as JsMemberExpression;
                        if (memberExpr.PreviousMember != null)
                        {
                            var refFuncInvoke = new JsInvocationExpression
                            {
                                Member = new JsMemberExpression {
                                    Name = "$Ref"
                                },
                                Arguments = new List <JsExpression> {
                                    memberExpr.PreviousMember, Js.String(memberExpr.Name)
                                }
                            };
                            func.Add(Js.Var(RefIndexToName(i), refFuncInvoke).Statement());
                        }
                        else
                        {
                            //如果是局部变量的话使用旧实现方式
                            var refFuncInvoke = new JsInvocationExpression
                            {
                                Member = new JsMemberExpression {
                                    Name = "$Ref"
                                },
                                Arguments = new List <JsExpression> {
                                    Js.Member("null"), memberExpr
                                }
                            };
                            func.Add(Js.Var(RefIndexToName(i), refFuncInvoke).Statement());
                        }
                    }
                    else if (expr is JsIndexerAccessExpression)
                    {
                        var indexerExpr   = expr as JsIndexerAccessExpression;
                        var indexArg      = indexerExpr.Arguments[0];
                        var refFuncInvoke = new JsInvocationExpression
                        {
                            Member = new JsMemberExpression {
                                Name = "$Ref"
                            },
                            Arguments = new List <JsExpression> {
                                indexerExpr.Member, indexArg
                            }
                        };
                        func.Add(Js.Var(RefIndexToName(i), refFuncInvoke).Statement());
                    }
                }

                func.Add(Js.Var("$res", Node2).Statement());

                for (var i = 0; i < ByRefs.Count; i++)
                {
                    var byRef      = ByRefs[i];
                    var memberExpr = VisitExpression(byRef) as JsMemberExpression;
                    if (memberExpr != null && memberExpr.PreviousMember == null)
                    {
                        func.Add(memberExpr.Assign(Js.Member(RefIndexToName(i)).Member("Value")).Statement());
                    }
                }

                func.Add(Js.Return(Js.Member("$res")));
                Node2 = Importer.WrapFunctionAndInvoke(Res, func);
            }
        }
Exemple #26
0
        public JNode VisitOperatorResolveResult(OperatorResolveResult res)
        {
            if (res.Operands.Count == 1)
            {
                if (res.UserDefinedOperatorMethod != null && !JMeta.UseNativeOperatorOverloads(res.UserDefinedOperatorMethod.DeclaringTypeDefinition))
                {
                    var fake = Cs.InvokeMethod(res.UserDefinedOperatorMethod, null, res.Operands[0]);
                    return(Visit(fake));
                }

                var isProperty = false;
                var meRes      = res.Operands[0] as MemberResolveResult;
                if (meRes != null && meRes.Member != null && IsEntityFunctionProperty(meRes.Member, res))
                {
                    isProperty = true;
                }

                JExpression node2;
                if (res.OperatorType == System.Linq.Expressions.ExpressionType.Negate ||
                    res.OperatorType == System.Linq.Expressions.ExpressionType.PreDecrementAssign ||
                    res.OperatorType == System.Linq.Expressions.ExpressionType.PreIncrementAssign ||
                    res.OperatorType == System.Linq.Expressions.ExpressionType.Not ||
                    res.OperatorType == System.Linq.Expressions.ExpressionType.OnesComplement)
                {
                    var simpler = res.OperatorType.ExtractCompoundAssignment();
                    if (isProperty && simpler != null)
                    {
                        var fakeCs = meRes.Member.AccessSelf().Binary(simpler.Value, Cs.Value(1, Project), meRes.Type);
                        node2 = VisitExpression(fakeCs);
                    }
                    else
                    {
                        node2 = new JPreUnaryExpression {
                            Operator = Visit(res.OperatorType), Right = VisitExpression(res.Operands[0])
                        };
                    }
                }
                else if (res.OperatorType == System.Linq.Expressions.ExpressionType.PostIncrementAssign ||
                         res.OperatorType == System.Linq.Expressions.ExpressionType.PostDecrementAssign ||
                         res.OperatorType == System.Linq.Expressions.ExpressionType.PreIncrementAssign ||
                         res.OperatorType == System.Linq.Expressions.ExpressionType.PreDecrementAssign)
                {
                    if (isProperty)
                    {
                        var simpler = res.OperatorType.ExtractCompoundAssignment();
                        var fakeCs  = meRes.Member.AccessSelf().Binary(simpler.Value, Cs.Value(1, Project), meRes.Type);
                        node2 = VisitExpression(fakeCs);
                    }
                    else
                    {
                        node2 = new JPostUnaryExpression {
                            Operator = Visit(res.OperatorType), Left = VisitExpression(res.Operands[0])
                        };
                    }
                }
                else
                {
                    throw new NotImplementedException();
                }
                return(node2);
            }
            else if (res.Operands.Count == 2)
            {
                if (res.UserDefinedOperatorMethod != null && !JMeta.UseNativeOperatorOverloads(res.UserDefinedOperatorMethod.DeclaringTypeDefinition))
                {
                    var fake = Cs.InvokeMethod(res.UserDefinedOperatorMethod, null, res.Operands[0], res.Operands[1]);
                    return(Visit(fake));
                }

                if (res.OperatorType == System.Linq.Expressions.ExpressionType.Coalesce)
                {
                    var fake  = Cs.Conditional(res.Operands[0].NotEqual(Cs.Null(), Project), res.Operands[0], res.Operands[1], res.Type);
                    var fake2 = Visit(fake);
                    fake2 = new JParenthesizedExpression {
                        Expression = (JExpression)fake2
                    };
                    return(fake2);
                }
                var mrrOp0 = res.Operands[0] as MemberResolveResult;
                if (mrrOp0 != null && mrrOp0.Member.SymbolKind == SymbolKind.Event)
                {
                    var pe = (IEvent)mrrOp0.Member;
                    if (res.OperatorType == System.Linq.Expressions.ExpressionType.AddAssign || res.OperatorType == System.Linq.Expressions.ExpressionType.SubtractAssign)
                    {
                        var accessor = res.OperatorType == System.Linq.Expressions.ExpressionType.AddAssign ? pe.AddAccessor : pe.RemoveAccessor;
                        var fake     = new CSharpInvocationResolveResult(mrrOp0.TargetResult, accessor, new List <ResolveResult>
                        {
                            res.Operands[1]
                        });
                        var node6 = Visit(fake);
                        return(node6);
                    }
                }
                if (mrrOp0 != null && IsEntityFunctionProperty(mrrOp0.Member, res))
                {
                    var compOpType = res.OperatorType.ExtractCompoundAssignment();

                    var pe = (IProperty)mrrOp0.Member;
                    if (compOpType != null)
                    {
                        var fake = new CSharpInvocationResolveResult(mrrOp0.TargetResult, pe.Setter, new List <ResolveResult>
                        {
                            new OperatorResolveResult(res.Type, compOpType.Value, new CSharpInvocationResolveResult(mrrOp0.TargetResult, pe.Getter, null), res.Operands[1])
                        });
                        var node6 = Visit(fake);
                        return(node6);
                    }
                    else if (res.OperatorType == System.Linq.Expressions.ExpressionType.Assign)
                    {
                        var args = new List <ResolveResult>();
                        if (pe.IsIndexer)
                        {
                            var irrOp0 = (CSharpInvocationResolveResult)res.Operands[0];
                            args.AddRange(irrOp0.Arguments);
                        }
                        args.Add(res.Operands[1]);
                        var fake  = new CSharpInvocationResolveResult(mrrOp0.TargetResult, pe.Setter, args).AssociateWithOriginal(res);
                        var node6 = Visit(fake);
                        node6 = WrapSetterToReturnValueIfNeeded(res, node6);
                        return(node6);
                    }
                }
                if (res.Operands[0] is ConversionResolveResult && res.Operands[1] is ConstantResolveResult)
                {
                    var leftConv   = (ConversionResolveResult)res.Operands[0];
                    var rightConst = (ConstantResolveResult)res.Operands[1];
                    if (leftConv.Conversion.IsNumericConversion && leftConv.Input.Type == Cs.CharType(Project))
                    {
                        var value = ((char)(int)rightConst.ConstantValue).ToString();
                        var fake  = Cs.Binary(leftConv.Input, res.OperatorType, Cs.Value(value, Project), leftConv.Input.Type);
                        return(Visit(fake));
                    }
                }
                if (res.Operands[0].Type.Kind == TypeKind.Delegate && res.Operands[1].Type.Kind == TypeKind.Delegate)
                {
                    if (res.OperatorType == System.Linq.Expressions.ExpressionType.AddAssign || res.OperatorType == System.Linq.Expressions.ExpressionType.SubtractAssign)
                    {
                        var op    = res.OperatorType == System.Linq.Expressions.ExpressionType.AddAssign ? System.Linq.Expressions.ExpressionType.Add : System.Linq.Expressions.ExpressionType.Subtract;
                        var fake  = Cs.Assign(res.Operands[0], Cs.Binary(res.Operands[0], op, res.Operands[1], res.Type));
                        var node6 = Visit(fake);
                        return(node6);
                    }
                    else if (res.OperatorType == System.Linq.Expressions.ExpressionType.Add || res.OperatorType == System.Linq.Expressions.ExpressionType.Subtract)
                    {
                        var combineMethod = Compiler.Project.Compilation.FindType(KnownTypeCode.Delegate).GetMethods(t => t.Name == "Combine").FirstOrDefault();
                        var removeMethod  = Compiler.Project.Compilation.FindType(KnownTypeCode.Delegate).GetMethods(t => t.Name == "Remove").FirstOrDefault();

                        var meOp = res.OperatorType == System.Linq.Expressions.ExpressionType.Add ? combineMethod : removeMethod;

                        var fake  = Cs.Member(null, meOp).Invoke(res.Operands[0], res.Operands[1]);
                        var node6 = Visit(fake);
                        return(node6);
                    }
                }

                var node5 = new JBinaryExpression {
                    Operator = Visit(res.OperatorType), Left = VisitExpression(res.Operands[0]), Right = VisitExpression(res.Operands[1])
                };

                if (res.OperatorType == System.Linq.Expressions.ExpressionType.Equal && node5.Operator == "==")
                {
                    var att = JMeta.GetJsExportAttribute(Project.Compilation.MainAssembly);
                    if (att != null && att.UseExactEquals)
                    {
                        node5.Operator = "===";
                    }
                }
                if (res.OperatorType == System.Linq.Expressions.ExpressionType.NotEqual && node5.Operator == "!=")
                {
                    var att = JMeta.GetJsExportAttribute(Project.Compilation.MainAssembly);
                    if (att != null && att.UseExactEquals)
                    {
                        node5.Operator = "!==";
                    }
                }

                return(node5);
            }
            else if (res.Operands.Count == 3)
            {
                if (res.OperatorType == System.Linq.Expressions.ExpressionType.Conditional)
                {
                    var node5 = new JConditionalExpression {
                        Condition = VisitExpression(res.Operands[0]), TrueExpression = VisitExpression(res.Operands[1]), FalseExpression = VisitExpression(res.Operands[2])
                    };
                    return(node5);
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
            else
            {
                throw new NotImplementedException();
            }
        }
        protected void VisitMemberReferenceExpression()
        {
            MemberReferenceExpression memberReferenceExpression = this.MemberReferenceExpression;
            int  pos      = this.Emitter.Output.Length;
            bool isRefArg = this.Emitter.IsRefArg;

            this.Emitter.IsRefArg = false;

            ResolveResult resolveResult           = null;
            ResolveResult expressionResolveResult = null;
            string        targetVar     = null;
            string        valueVar      = null;
            bool          isStatement   = false;
            bool          isConstTarget = false;

            var targetrr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Target, this.Emitter);

            if (targetrr is ConstantResolveResult)
            {
                isConstTarget = true;
            }

            var memberTargetrr = targetrr as MemberResolveResult;

            if (memberTargetrr != null && memberTargetrr.Type.Kind == TypeKind.Enum && memberTargetrr.Member is DefaultResolvedField && Helpers.EnumEmitMode(memberTargetrr.Type) == 2)
            {
                isConstTarget = true;
            }

            if (memberReferenceExpression.Target is ParenthesizedExpression ||
                (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.Int64)) ||
                (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.UInt64)) ||
                (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.Decimal)))
            {
                isConstTarget = false;
            }

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

            if (isInvoke)
            {
                resolveResult           = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter);
                expressionResolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter);

                if (expressionResolveResult is InvocationResolveResult)
                {
                    resolveResult = expressionResolveResult;
                }
                else if (expressionResolveResult is MemberResolveResult)
                {
                    if (((MemberResolveResult)expressionResolveResult).Member is IProperty)
                    {
                        resolveResult = expressionResolveResult;
                    }
                }
            }
            else
            {
                resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter);
            }

            bool oldIsAssignment = this.Emitter.IsAssignment;
            bool oldUnary        = this.Emitter.IsUnaryAccessor;

            if (resolveResult == null)
            {
                this.Emitter.IsAssignment    = false;
                this.Emitter.IsUnaryAccessor = false;
                if (isConstTarget)
                {
                    this.Write("(");
                }
                memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                if (isConstTarget)
                {
                    this.Write(")");
                }
                this.Emitter.IsAssignment    = oldIsAssignment;
                this.Emitter.IsUnaryAccessor = oldUnary;
                this.WriteDot();
                string name = memberReferenceExpression.MemberName;
                this.Write(name.ToLowerCamelCase());

                return;
            }

            bool isDynamic = false;

            if (resolveResult is DynamicInvocationResolveResult)
            {
                var dynamicResolveResult = (DynamicInvocationResolveResult)resolveResult;
                var group = dynamicResolveResult.Target as MethodGroupResolveResult;

                if (group != null && group.Methods.Count() > 1)
                {
                    var method = group.Methods.FirstOrDefault(m =>
                    {
                        if (dynamicResolveResult.Arguments.Count != m.Parameters.Count)
                        {
                            return(false);
                        }

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

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

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

                        return(true);
                    }) ?? group.Methods.Last();

                    isDynamic     = true;
                    resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method);
                    resolveResult = new InvocationResolveResult(resolveResult, method, dynamicResolveResult.Arguments);
                }
            }

            if (resolveResult is MethodGroupResolveResult)
            {
                var oldResult = (MethodGroupResolveResult)resolveResult;
                resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter);

                if (resolveResult is DynamicInvocationResolveResult)
                {
                    var method = oldResult.Methods.Last();
                    resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method);
                }
            }

            MemberResolveResult member = resolveResult as MemberResolveResult;
            var globalTarget           = member != null?this.Emitter.IsGlobalTarget(member.Member) : null;

            if (member != null &&
                member.Member.Attributes.Any(a => a.AttributeType.FullName == "Bridge.NonScriptableAttribute"))
            {
                throw new EmitterException(this.MemberReferenceExpression, "Member " + member.ToString() + " is marked as not usable from script");
            }

            if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod)
            {
                var interceptor = this.Emitter.Plugins.OnReference(this, this.MemberReferenceExpression, member);

                if (interceptor.Cancel)
                {
                    return;
                }

                if (!string.IsNullOrEmpty(interceptor.Replacement))
                {
                    this.Write(interceptor.Replacement);
                    return;
                }
            }

            if (globalTarget != null && globalTarget.Item1)
            {
                var target = globalTarget.Item2;

                if (!string.IsNullOrWhiteSpace(target))
                {
                    bool assign           = false;
                    var  memberExpression = member.Member is IMethod ? memberReferenceExpression.Parent.Parent : memberReferenceExpression.Parent;
                    var  targetExpression = member.Member is IMethod ? memberReferenceExpression.Parent : memberReferenceExpression;
                    var  assignment       = memberExpression as AssignmentExpression;
                    if (assignment != null && assignment.Right == targetExpression)
                    {
                        assign = true;
                    }
                    else
                    {
                        var varInit = memberExpression as VariableInitializer;
                        if (varInit != null && varInit.Initializer == targetExpression)
                        {
                            assign = true;
                        }
                        else if (memberExpression is InvocationExpression)
                        {
                            var targetInvocation = (InvocationExpression)memberExpression;
                            if (targetInvocation.Arguments.Any(a => a == targetExpression))
                            {
                                assign = true;
                            }
                        }
                    }

                    if (assign)
                    {
                        if (resolveResult is InvocationResolveResult)
                        {
                            this.PushWriter(target);
                        }
                        else
                        {
                            this.Write(target);
                        }

                        return;
                    }
                }

                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter("");
                }

                return;
            }

            Tuple <bool, bool, string> inlineInfo = member != null ? (isDynamic ? ((Emitter)this.Emitter).GetInlineCodeFromMember(member.Member, null) : this.Emitter.GetInlineCode(memberReferenceExpression)) : null;
            //string inline = member != null ? this.Emitter.GetInline(member.Member) : null;
            string inline = inlineInfo != null ? inlineInfo.Item3 : null;

            if (string.IsNullOrEmpty(inline) && member != null &&
                member.Member is IMethod &&
                !(member is InvocationResolveResult) &&
                !(
                    memberReferenceExpression.Parent is InvocationExpression &&
                    memberReferenceExpression.NextSibling != null &&
                    memberReferenceExpression.NextSibling.Role is TokenRole &&
                    ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "("
                    )
                )
            {
                var method = (IMethod)member.Member;
                if (method.TypeArguments.Count > 0)
                {
                    inline = MemberReferenceBlock.GenerateInlineForMethodReference(method, this.Emitter);
                }
            }

            if (member != null && member.Member is IMethod && isInvoke)
            {
                var i_rr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter) as CSharpInvocationResolveResult;

                if (i_rr != null && !i_rr.IsExpandedForm)
                {
                    var tpl = this.Emitter.GetAttribute(member.Member.Attributes, JS.NS.BRIDGE + ".TemplateAttribute");

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

            bool hasInline = !string.IsNullOrEmpty(inline);
            bool hasThis   = hasInline && Helpers.HasThis(inline);

            inline = hasInline ? Helpers.ConvertTokens(this.Emitter, inline, member.Member) : inline;
            bool isInterfaceMember = false;

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

            bool nativeImplementation = true;
            bool isInterface          = inline == null && member != null && member.Member.DeclaringTypeDefinition != null && member.Member.DeclaringTypeDefinition.Kind == TypeKind.Interface;
            var  hasTypeParemeter     = isInterface && Helpers.IsTypeParameterType(member.Member.DeclaringType);

            if (isInterface)
            {
                var itypeDef = member.Member.DeclaringTypeDefinition;
                var variance = MetadataUtils.IsJsGeneric(itypeDef, this.Emitter) &&
                               itypeDef.TypeParameters != null &&
                               itypeDef.TypeParameters.Any(typeParameter => typeParameter.Variance != VarianceModifier.Invariant);

                if (variance)
                {
                    isInterfaceMember = true;
                }
                else
                {
                    var ei = this.Emitter.Validator.IsExternalInterface(itypeDef);

                    if (ei != null)
                    {
                        nativeImplementation = ei.IsNativeImplementation;
                    }
                    else
                    {
                        nativeImplementation = member.Member.DeclaringTypeDefinition.ParentAssembly.AssemblyName == CS.NS.ROOT ||
                                               !this.Emitter.Validator.IsExternalType(member.Member.DeclaringTypeDefinition);
                    }

                    if (ei != null && ei.IsSimpleImplementation)
                    {
                        nativeImplementation = false;
                        isInterfaceMember    = false;
                    }
                    else if (ei != null || hasTypeParemeter)
                    {
                        if (hasTypeParemeter || !nativeImplementation)
                        {
                            isInterfaceMember = true;
                        }
                    }
                }
            }

            string interfaceTempVar = null;

            if (hasThis)
            {
                this.Write("");
                var    oldBuilder = this.Emitter.Output;
                var    oldInline  = inline;
                string thisArg    = null;
                bool   isSimple   = true;

                if (this.MemberReferenceExpression.Target is BaseReferenceExpression)
                {
                    thisArg = "this";
                }
                else
                {
                    this.Emitter.Output          = new StringBuilder();
                    this.Emitter.IsAssignment    = false;
                    this.Emitter.IsUnaryAccessor = false;
                    if (isConstTarget)
                    {
                        this.Write("(");
                    }
                    this.WriteSimpleTarget(resolveResult);
                    if (isConstTarget)
                    {
                        this.Write(")");
                    }

                    thisArg = this.Emitter.Output.ToString();

                    if (Regex.Matches(inline, @"\{(\*?)this\}").Count > 1)
                    {
                        var  mrr     = resolveResult as MemberResolveResult;
                        bool isField = mrr != null && mrr.Member is IField &&
                                       (mrr.TargetResult is ThisResolveResult ||
                                        mrr.TargetResult is LocalResolveResult || mrr.TargetResult is MemberResolveResult && ((MemberResolveResult)mrr.TargetResult).Member is IField);

                        isSimple = (mrr != null && (mrr.TargetResult is ThisResolveResult || mrr.TargetResult is ConstantResolveResult || mrr.TargetResult is LocalResolveResult)) || isField;
                    }
                }

                int thisIndex;
                inline = member != null?Helpers.ConvertTokens(this.Emitter, inline, member.Member) : inline;

                if (!isSimple)
                {
                    StringBuilder sb = new StringBuilder();

                    sb.Append("(");
                    var tempVar = this.GetTempVarName();
                    inline    = inline.Replace("{this}", tempVar);
                    thisIndex = tempVar.Length + 2;

                    sb.Append(tempVar);
                    sb.Append(" = ");
                    sb.Append(thisArg);
                    sb.Append(", ");

                    sb.Append(inline);
                    sb.Append(")");

                    inline = sb.ToString();
                }
                else
                {
                    thisIndex = inline.IndexOf("{this}", StringComparison.Ordinal);
                    inline    = inline.Replace("{this}", thisArg);
                }

                if (member != null && member.Member is IProperty)
                {
                    this.Emitter.Output = new StringBuilder();
                    inline = inline.Replace("{0}", "[[0]]");
                    new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit();
                    inline = this.Emitter.Output.ToString();
                    inline = inline.Replace("[[0]]", "{0}");
                }

                this.Emitter.IsAssignment    = oldIsAssignment;
                this.Emitter.IsUnaryAccessor = oldUnary;
                this.Emitter.Output          = oldBuilder;

                int[] range = null;

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

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

                return;
            }

            if (member != null && member.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(member.Member) && this.Emitter.IsInlineConst(member.Member))
            {
                var  parentExpression = memberReferenceExpression.Parent as MemberReferenceExpression;
                bool wrap             = false;

                if (parentExpression != null)
                {
                    var ii = this.Emitter.GetInlineCode(parentExpression);

                    if (string.IsNullOrEmpty(ii.Item3))
                    {
                        wrap = true;
                        this.WriteOpenParentheses();
                    }
                }

                this.WriteScript(Bridge.Translator.Emitter.ConvertConstant(member.ConstantValue, memberReferenceExpression, this.Emitter));

                if (wrap)
                {
                    this.WriteCloseParentheses();
                }
            }
            else if (hasInline && member.Member.IsStatic)
            {
                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter(inline);
                }
                else
                {
                    if (member != null && member.Member is IMethod)
                    {
                        new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference();
                    }
                    else
                    {
                        new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit();
                    }
                }
            }
            else
            {
                if (member != null && member.IsCompileTimeConstant && member.Member.DeclaringType.Kind == TypeKind.Enum)
                {
                    var typeDef = member.Member.DeclaringType as ITypeDefinition;

                    if (typeDef != null)
                    {
                        var enumMode = Helpers.EnumEmitMode(typeDef);

                        if ((this.Emitter.Validator.IsExternalType(typeDef) && enumMode == -1) || enumMode == 2)
                        {
                            this.WriteScript(member.ConstantValue);

                            return;
                        }

                        if (enumMode >= 3 && enumMode < 7)
                        {
                            string enumStringName = this.Emitter.GetEntityName(member.Member);
                            this.WriteScript(enumStringName);
                            return;
                        }
                    }
                }

                if (resolveResult is TypeResolveResult)
                {
                    TypeResolveResult typeResolveResult = (TypeResolveResult)resolveResult;
                    this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter));
                    return;
                }
                else if (member != null &&
                         member.Member is IMethod &&
                         !(member is InvocationResolveResult) &&
                         !(
                             memberReferenceExpression.Parent is InvocationExpression &&
                             memberReferenceExpression.NextSibling != null &&
                             memberReferenceExpression.NextSibling.Role is TokenRole &&
                             ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "("
                             )
                         )
                {
                    if (!string.IsNullOrEmpty(inline))
                    {
                        if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod)
                        {
                            new InlineArgumentsBlock(this.Emitter,
                                                     new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline,
                                                     (IMethod)member.Member, targetrr).EmitFunctionReference();
                        }
                        else if (resolveResult is InvocationResolveResult ||
                                 (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment))
                        {
                            this.PushWriter(inline);
                        }
                        else
                        {
                            this.Write(inline);
                        }
                    }
                    else
                    {
                        var  resolvedMethod = (IMethod)member.Member;
                        bool isStatic       = resolvedMethod != null && resolvedMethod.IsStatic;

                        var isExtensionMethod = resolvedMethod.IsExtensionMethod;

                        this.Emitter.IsAssignment    = false;
                        this.Emitter.IsUnaryAccessor = false;

                        if (!isStatic)
                        {
                            this.Write(isExtensionMethod ? JS.Funcs.BRIDGE_BIND_SCOPE : JS.Funcs.BRIDGE_CACHE_BIND);
                            this.WriteOpenParentheses();

                            if (memberReferenceExpression.Target is BaseReferenceExpression)
                            {
                                this.WriteThis();
                            }
                            else
                            {
                                interfaceTempVar = this.WriteTarget(resolveResult, isInterfaceMember, memberTargetrr, targetrr, false);
                            }

                            this.Write(", ");
                        }

                        this.Emitter.IsAssignment    = oldIsAssignment;
                        this.Emitter.IsUnaryAccessor = oldUnary;

                        if (isExtensionMethod)
                        {
                            this.Write(BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter));
                        }
                        else
                        {
                            this.Emitter.IsAssignment    = false;
                            this.Emitter.IsUnaryAccessor = false;
                            if (isConstTarget)
                            {
                                this.Write("(");
                            }

                            if (interfaceTempVar != null)
                            {
                                this.Write(interfaceTempVar);
                            }
                            else
                            {
                                this.WriteSimpleTarget(resolveResult);
                            }

                            if (isConstTarget)
                            {
                                this.Write(")");
                            }
                            this.Emitter.IsAssignment    = oldIsAssignment;
                            this.Emitter.IsUnaryAccessor = oldUnary;
                        }

                        if (isInterfaceMember)
                        {
                            this.WriteInterfaceMember(interfaceTempVar, member, false);
                        }
                        else
                        {
                            this.WriteDot();
                            this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation));
                        }

                        if (!isStatic)
                        {
                            this.Write(")");
                        }
                    }

                    return;
                }
                else
                {
                    bool isProperty = false;

                    if (member != null && member.Member.SymbolKind == SymbolKind.Property && (member.Member.DeclaringTypeDefinition == null || !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)))
                    {
                        isProperty = true;
                        bool writeTargetVar = false;

                        if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign)
                        {
                            writeTargetVar = true;
                        }
                        else if (this.Emitter.IsUnaryAccessor)
                        {
                            writeTargetVar = true;

                            isStatement = memberReferenceExpression.Parent is UnaryOperatorExpression && memberReferenceExpression.Parent.Parent is ExpressionStatement;

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

                            if (!isStatement)
                            {
                                this.WriteOpenParentheses();
                            }
                        }

                        if (writeTargetVar)
                        {
                            bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult);

                            if (!(targetrr is ThisResolveResult || targetrr is TypeResolveResult || targetrr is LocalResolveResult || isField))
                            {
                                targetVar = this.GetTempVarName();

                                this.Write(targetVar);
                                this.Write(" = ");
                            }
                        }
                    }

                    if (isProperty && this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null)
                    {
                        valueVar = this.GetTempVarName();

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

                    this.Emitter.IsAssignment    = false;
                    this.Emitter.IsUnaryAccessor = false;
                    if (isConstTarget)
                    {
                        this.Write("(");
                    }

                    if (targetVar == null && isInterfaceMember)
                    {
                        interfaceTempVar = this.WriteTarget(resolveResult, isInterfaceMember, memberTargetrr, targetrr, true);
                    }
                    else
                    {
                        this.WriteSimpleTarget(resolveResult);
                    }

                    if (member != null && targetrr != null && targetrr.Type.Kind == TypeKind.Delegate && (member.Member.Name == "Invoke"))
                    {
                        var method = member.Member as IMethod;
                        if (!(method != null && method.IsExtensionMethod))
                        {
                            return;
                        }
                    }

                    if (isConstTarget)
                    {
                        this.Write(")");
                    }
                    this.Emitter.IsAssignment    = oldIsAssignment;
                    this.Emitter.IsUnaryAccessor = oldUnary;

                    if (targetVar != null)
                    {
                        if (this.Emitter.IsUnaryAccessor && !isStatement)
                        {
                            this.WriteComma(false);

                            valueVar = this.GetTempVarName();

                            this.Write(valueVar);
                            this.Write(" = ");

                            this.Write(targetVar);
                        }
                        else
                        {
                            this.WriteSemiColon();
                            this.WriteNewLine();
                            this.Write(targetVar);
                        }
                    }
                }

                var targetResolveResult = targetrr as MemberResolveResult;

                if (targetResolveResult == null || this.Emitter.IsGlobalTarget(targetResolveResult.Member) == null)
                {
                    if (isRefArg)
                    {
                        this.WriteComma();
                    }
                    else if (!isInterfaceMember && !this.NoTarget)
                    {
                        this.WriteDot();
                    }
                }

                if (member == null)
                {
                    if (targetrr != null && targetrr.Type.Kind == TypeKind.Dynamic)
                    {
                        this.Write(memberReferenceExpression.MemberName);
                    }
                    else
                    {
                        this.Write(memberReferenceExpression.MemberName.ToLowerCamelCase());
                    }
                }
                else if (!string.IsNullOrEmpty(inline))
                {
                    if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod)
                    {
                        new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference();
                    }
                    else if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment))
                    {
                        this.PushWriter(inline);
                    }
                    else
                    {
                        this.Write(inline);
                    }
                }
                else if (member.Member.SymbolKind == SymbolKind.Property && (member.Member.DeclaringTypeDefinition == null || (!this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition) || member.Member.IsStatic)))
                {
                    if (member.Member is IProperty && targetrr != null && targetrr.Type.GetDefinition() != null && this.Emitter.Validator.IsObjectLiteral(targetrr.Type.GetDefinition()) && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition))
                    {
                        this.Write(this.Emitter.GetLiteralEntityName(member.Member));
                    }
                    else
                    {
                        if (isInterfaceMember)
                        {
                            this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false);
                        }
                        else
                        {
                            var name     = OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation);
                            var property = (IProperty)member.Member;
                            var proto    = member.IsVirtualCall || property.IsVirtual || property.IsOverride;

                            if (this.MemberReferenceExpression.Target is BaseReferenceExpression && !property.IsIndexer && proto)
                            {
                                var alias = BridgeTypes.ToJsName(member.Member.DeclaringType, this.Emitter,
                                                                 isAlias: true);
                                if (alias.StartsWith("\""))
                                {
                                    alias = alias.Insert(1, "$");
                                    name  = alias + "+\"$" + name + "\"";
                                    this.WriteIdentifier(name, false);
                                }
                                else
                                {
                                    name = "$" + alias + "$" + name;
                                    this.WriteIdentifier(name);
                                }
                            }
                            else
                            {
                                this.WriteIdentifier(name);
                            }
                        }
                    }
                }
                else if (member.Member.SymbolKind == SymbolKind.Field)
                {
                    bool isConst = this.Emitter.IsMemberConst(member.Member);

                    if (isConst && this.Emitter.IsInlineConst(member.Member))
                    {
                        this.WriteScript(Bridge.Translator.Emitter.ConvertConstant(member.ConstantValue, memberReferenceExpression, this.Emitter));
                    }
                    else
                    {
                        if (isInterfaceMember)
                        {
                            this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false);
                        }
                        else
                        {
                            var fieldName = OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation);

                            if (isRefArg)
                            {
                                this.WriteScript(fieldName);
                            }
                            else
                            {
                                this.WriteIdentifier(fieldName);
                            }
                        }
                    }
                }
                else if (resolveResult is InvocationResolveResult)
                {
                    InvocationResolveResult       invocationResult  = (InvocationResolveResult)resolveResult;
                    CSharpInvocationResolveResult cInvocationResult = resolveResult as CSharpInvocationResolveResult;
                    var expresssionMember = expressionResolveResult as MemberResolveResult;

                    if (isInterfaceMember)
                    {
                        this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false);
                    }
                    else if (expresssionMember != null &&
                             cInvocationResult != null &&
                             cInvocationResult.IsDelegateInvocation &&
                             invocationResult.Member != expresssionMember.Member)
                    {
                        this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName(!nativeImplementation));
                    }
                    else
                    {
                        this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName(!nativeImplementation));
                    }
                }
                else if (member.Member is IEvent)
                {
                    if (this.Emitter.IsAssignment &&
                        (this.Emitter.AssignmentType == AssignmentOperatorType.Add ||
                         this.Emitter.AssignmentType == AssignmentOperatorType.Subtract))
                    {
                        if (isInterfaceMember)
                        {
                            this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract, Helpers.GetAddOrRemove(this.Emitter.AssignmentType == AssignmentOperatorType.Add));
                        }
                        else
                        {
                            this.Write(Helpers.GetEventRef(member.Member, this.Emitter, this.Emitter.AssignmentType != AssignmentOperatorType.Add, ignoreInterface: !nativeImplementation));
                        }

                        this.WriteOpenParentheses();
                    }
                    else
                    {
                        if (isInterfaceMember)
                        {
                            this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false);
                        }
                        else
                        {
                            this.Write(this.Emitter.GetEntityName(member.Member));
                        }
                    }
                }
                else
                {
                    if (isInterfaceMember)
                    {
                        this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false);
                    }
                    else
                    {
                        this.Write(this.Emitter.GetEntityName(member.Member));
                    }
                }

                Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this, pos);
            }
        }
Exemple #28
0
 public virtual object VisitCSharpInvocationResolveResult(CSharpInvocationResolveResult rr, object data)
 {
     VisitChildResolveResults(rr, data);
     return(null);
 }
        protected void VisitIdentifierExpression()
        {
            IdentifierExpression identifierExpression = this.IdentifierExpression;

            ResolveResult resolveResult           = null;
            ResolveResult expressionResolveResult = null;

            /*if (identifierExpression.Parent is InvocationExpression && (((InvocationExpression)(identifierExpression.Parent)).Target == identifierExpression))
             * {
             *  resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression.Parent, this.Emitter);
             *  expressionResolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter);
             * }
             * else
             * {
             *  resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter);
             * }*/

            resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter);

            var id = identifierExpression.Identifier;

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

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

                Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this);

                return;
            }

            IMemberDefinition member = this.ResolveFieldOrMethod(id, identifierExpression.TypeArguments.Count);

            if (member == null && memberResult != null)
            {
                var iMethod = memberResult.Member as IMethod;

                if (iMethod != null)
                {
                    member = this.ResolveFieldOrMethod(id, iMethod.TypeParameters.Count);
                }
            }

            if (member != null)
            {
                MethodDefinition method               = member as MethodDefinition;
                FieldDefinition  field                = member as FieldDefinition;
                bool             isStatic             = method != null && method.IsStatic || field != null && field.IsStatic;
                string           appendAdditionalCode = null;

                if (method != null)
                {
                    string inline = this.Emitter.GetInline(method);

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

                    if (memberResult != null &&
                        memberResult.Member is IMethod &&
                        !(memberResult is InvocationResolveResult) &&
                        !(
                            identifierExpression.Parent is InvocationExpression &&
                            identifierExpression.NextSibling != null &&
                            identifierExpression.NextSibling.Role is TokenRole &&
                            ((TokenRole)identifierExpression.NextSibling.Role).Token == "("
                            )
                        )
                    {
                        var resolvedMethod = (IMethod)memberResult.Member;

                        if (!isStatic)
                        {
                            var isExtensionMethod = resolvedMethod.IsExtensionMethod;
                            this.Write(Bridge.Translator.Emitter.ROOT + "." + (isExtensionMethod ? Bridge.Translator.Emitter.DELEGATE_BIND_SCOPE : Bridge.Translator.Emitter.DELEGATE_BIND) + "(");
                            this.WriteThis();
                            this.Write(", ");
                            appendAdditionalCode = ")";
                        }
                    }
                }

                bool isConst       = false;
                bool isInlineConst = false;
                if (memberResult != null)
                {
                    isConst = this.Emitter.IsMemberConst(memberResult.Member);
                    if (isConst)
                    {
                        isInlineConst = this.Emitter.IsInlineConst(memberResult.Member);
                    }
                }

                if (!(resolveResult is TypeResolveResult) && !isInlineConst)
                {
                    if (isStatic)
                    {
                        if (memberResult != null)
                        {
                            this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter));
                        }
                        else
                        {
                            this.Write(BridgeTypes.ToJsName(member.DeclaringType, this.Emitter));
                        }
                    }
                    else
                    {
                        this.WriteThis();
                    }

                    this.WriteDot();
                }


                if (method != null)
                {
                    if (resolveResult is InvocationResolveResult)
                    {
                        InvocationResolveResult       invocationResult  = (InvocationResolveResult)resolveResult;
                        CSharpInvocationResolveResult cInvocationResult = (CSharpInvocationResolveResult)resolveResult;
                        var expresssionMember = expressionResolveResult as MemberResolveResult;

                        if (expresssionMember != null &&
                            cInvocationResult != null &&
                            cInvocationResult.IsDelegateInvocation &&
                            invocationResult.Member != expresssionMember.Member)
                        {
                            this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName());
                        }
                        else
                        {
                            this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName());
                        }
                    }
                    else if (resolveResult is MemberResolveResult)
                    {
                        MemberResolveResult memberResolveResult = (MemberResolveResult)resolveResult;
                        this.Write(OverloadsCollection.Create(this.Emitter, memberResolveResult.Member).GetOverloadName());
                    }
                    else
                    {
                        this.Write(this.Emitter.GetDefinitionName(method));
                    }

                    if (appendAdditionalCode != null)
                    {
                        this.Write(appendAdditionalCode);
                    }
                }
                else if (memberResult != null)
                {
                    if (isInlineConst)
                    {
                        this.WriteScript(memberResult.ConstantValue);
                    }
                    else if (memberResult != null && memberResult.Member is DefaultResolvedEvent && this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract))
                    {
                        this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove");
                        this.Write(OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName());
                        this.WriteOpenParentheses();
                    }
                    else
                    {
                        if (resolveResult is InvocationResolveResult)
                        {
                            InvocationResolveResult       invocationResult  = (InvocationResolveResult)resolveResult;
                            CSharpInvocationResolveResult cInvocationResult = (CSharpInvocationResolveResult)resolveResult;
                            var expresssionMember = expressionResolveResult as MemberResolveResult;

                            if (expresssionMember != null &&
                                cInvocationResult != null &&
                                cInvocationResult.IsDelegateInvocation &&
                                invocationResult.Member != expresssionMember.Member)
                            {
                                this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName());
                            }
                            else
                            {
                                this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName());
                            }
                        }
                        else
                        {
                            this.Write(OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName());
                        }
                    }
                }
                else if (resolveResult is TypeResolveResult)
                {
                    this.Write(BridgeTypes.ToJsName(((TypeResolveResult)resolveResult).Type, this.Emitter));
                }

                Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this);

                return;
            }

            if (resolveResult is TypeResolveResult)
            {
                this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter));
                return;
            }

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

            bool hasInline = !string.IsNullOrEmpty(inlineCode);
            bool hasThis   = hasInline && inlineCode.Contains("{this}");

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

                if (memberResult.Member.IsStatic)
                {
                    this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter));
                }
                else
                {
                    this.WriteThis();
                }

                inlineCode          = inlineCode.Replace("{this}", this.Emitter.Output.ToString());
                this.Emitter.Output = oldBuilder;

                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter(inlineCode);
                }
                else
                {
                    this.Write(inlineCode);
                }

                return;
            }

            if (hasInline && memberResult.Member.IsStatic)
            {
                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter(inlineCode);
                }
                else
                {
                    this.Write(inlineCode);
                }
            }
            else if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Property && memberResult.TargetResult.Type.Kind != TypeKind.Anonymous)
            {
                bool   isStatement = false;
                string valueVar    = null;

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

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

                    if (!isStatement)
                    {
                        this.WriteOpenParentheses();

                        valueVar = this.GetTempVarName();

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

                this.WriteTarget(memberResult);

                if (!string.IsNullOrWhiteSpace(inlineCode))
                {
                    this.Write(inlineCode);
                }
                else if (Helpers.IsFieldProperty(memberResult.Member, this.Emitter))
                {
                    this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter));
                }
                else if (!this.Emitter.IsAssignment)
                {
                    if (this.Emitter.IsUnaryAccessor)
                    {
                        bool isDecimal  = Helpers.IsDecimalType(memberResult.Member.ReturnType, this.Emitter.Resolver);
                        bool isNullable = NullableType.IsNullable(memberResult.Member.ReturnType);
                        if (isStatement)
                        {
                            this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true));
                            this.WriteOpenParentheses();

                            if (isDecimal)
                            {
                                if (isNullable)
                                {
                                    this.Write("Bridge.Nullable.lift1");
                                    this.WriteOpenParentheses();
                                    if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                        this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                    {
                                        this.WriteScript("inc");
                                    }
                                    else
                                    {
                                        this.WriteScript("dec");
                                    }

                                    this.WriteComma();

                                    this.WriteTarget(memberResult);

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

                                    if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                        this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                    {
                                        this.Write("inc");
                                    }
                                    else
                                    {
                                        this.Write("dec");
                                    }

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

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

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


                                this.Write("1");
                            }

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

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

                            if (isDecimal)
                            {
                                if (isNullable)
                                {
                                    this.Write("Bridge.Nullable.lift1");
                                    this.WriteOpenParentheses();
                                    if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                        this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                    {
                                        this.WriteScript("inc");
                                    }
                                    else
                                    {
                                        this.WriteScript("dec");
                                    }

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

                                    this.WriteDot();

                                    if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                        this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                    {
                                        this.Write("inc");
                                    }
                                    else
                                    {
                                        this.Write("dec");
                                    }

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

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

                                this.Write("1");
                            }

                            this.WriteCloseParentheses();
                            this.WriteComma();

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

                            this.WriteCloseParentheses();

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

                    if (memberResult.Member.IsStatic)
                    {
                        trg = BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter);
                    }
                    else
                    {
                        trg = "this";
                    }

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

                if (!string.IsNullOrWhiteSpace(inlineCode))
                {
                    this.Write(inlineCode);
                }
                else
                {
                    this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove");
                    this.Write(OverloadsCollection.Create(this.Emitter, memberResult.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName());
                }

                this.WriteOpenParentheses();
            }
            else
            {
                if (!string.IsNullOrWhiteSpace(inlineCode))
                {
                    this.Write(inlineCode);
                }
                else if (isResolved)
                {
                    if (resolveResult is TypeResolveResult)
                    {
                        var typeResolveResult = (TypeResolveResult)resolveResult;

                        this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter));

                        if (typeResolveResult.Type.TypeParameterCount > 0)
                        {
                            this.WriteOpenParentheses();
                            new TypeExpressionListBlock(this.Emitter, this.IdentifierExpression.TypeArguments).Emit();
                            this.WriteCloseParentheses();
                        }
                    }
                    else if (resolveResult is LocalResolveResult)
                    {
                        var localResolveResult = (LocalResolveResult)resolveResult;
                        this.Write(localResolveResult.Variable.Name);
                    }
                    else if (memberResult != null)
                    {
                        this.WriteTarget(memberResult);
                        this.Write(this.Emitter.GetEntityName(memberResult.Member));
                    }
                    else
                    {
                        this.Write(resolveResult.ToString());
                    }

                    Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this);
                }
                else
                {
                    throw new EmitterException(identifierExpression, "Cannot resolve identifier: " + id);
                }
            }
        }
Exemple #30
0
 public override string VisitCSharpInvocationResolveResult(CSharpInvocationResolveResult rr, object data)
 {
     return(VisitInvocationResolveResult(rr, data));
 }