Esempio n. 1
0
        // Collect and filter members for subsequent code gen
        private void CollectMembers()
        {
            var fields     = new Seq <CST.FieldDef>();
            var events     = new Seq <CST.EventDef>();
            var properties = new Seq <CST.PropertyDef>();
            var methods    = new Seq <CST.MethodDef>();
            var exportedInstanceMethods = new Seq <CST.MethodDef>();

            StaticInitializer  = null;
            DefaultConstructor = null;
            numRelevantMethods = 0;

            foreach (var fieldDef in TyconEnv.Type.Members.OfType <CST.FieldDef>().Where(d => d.Invalid == null))
            {
                if (fieldDef.IsUsed)
                {
                    fields.Add(fieldDef);
                }
                else if (TypeTrace == null || TypeTrace.IncludeType)
                {
                    Env.Log
                        (new UnusedDefinitionMessage
                            (CST.MessageContextBuilders.Member
                                (Env.Global, TyconEnv.Assembly, TyconEnv.Type, fieldDef)));
                }
            }

            foreach (var eventDef in TyconEnv.Type.Members.OfType <CST.EventDef>().Where(d => d.Invalid == null))
            {
                if (eventDef.IsUsed)
                {
                    events.Add(eventDef);
                }
                else if (TypeTrace == null || TypeTrace.IncludeType)
                {
                    Env.Log
                        (new UnusedDefinitionMessage
                            (CST.MessageContextBuilders.Member
                                (Env.Global, TyconEnv.Assembly, TyconEnv.Type, eventDef)));
                }
            }

            foreach (var propDef in TyconEnv.Type.Members.OfType <CST.PropertyDef>().Where(d => d.Invalid == null))
            {
                if (propDef.IsUsed)
                {
                    properties.Add(propDef);
                }
                else if (TypeTrace == null || TypeTrace.IncludeType)
                {
                    Env.Log
                        (new UnusedDefinitionMessage
                            (CST.MessageContextBuilders.Member
                                (Env.Global, TyconEnv.Assembly, TyconEnv.Type, propDef)));
                }
            }

            var state = Env.InteropManager.GetTypeRepresentation(TyconEnv.Assembly, TyconEnv.Type).State;

            var s = TyconEnv.Type.Style;

            if (!(s is CST.InterfaceTypeStyle || s is CST.DelegateTypeStyle))
            {
                foreach (
                    var methodDef in
                    TyconEnv.Type.Members.OfType <CST.MethodDef>().Where(d => d.Invalid == null && !d.IsAbstract))
                {
                    if (!methodDef.IsUsed)
                    {
                        if (TypeTrace == null || TypeTrace.IncludeType)
                        {
                            Env.Log
                                (new UnusedDefinitionMessage
                                    (CST.MessageContextBuilders.Member
                                        (Env.Global, TyconEnv.Assembly, TyconEnv.Type, methodDef)));
                        }
                    }
                    else if (!Env.Validity.IsMustHaveADefinition(methodDef.QualifiedMemberName(Env.Global, TyconEnv.Assembly, TyconEnv.Type)) &&
                             (Env.InteropManager.IsInlinable(TyconEnv.Assembly, TyconEnv.Type, methodDef, state) ||
                              Env.InlinedMethods.IsInlinable(TyconEnv.Assembly, TyconEnv.Type, methodDef)))
                    {
                        if (TypeTrace == null || TypeTrace.IncludeType)
                        {
                            Env.Log
                                (new InlinedDefinitionMessage
                                    (CST.MessageContextBuilders.Member
                                        (Env.Global, TyconEnv.Assembly, TyconEnv.Type, methodDef)));
                        }
                    }
                    else if (state != InstanceState.JavaScriptOnly && state != InstanceState.ManagedAndJavaScript &&
                             !methodDef.IsStatic && methodDef.IsConstructor && methodDef.Arity > 1 &&
                             methodDef.ValueParameters[1].Equals(Env.JSContextRef))
                    {
                        // Silently ignore importing constructors unless they are needed.
                        // (Remember, the managed interop rewriter will interpert 'Merged' as
                        // 'JavaScriptOnly', and thus may need importing constructors.)
                    }
                    else
                    {
                        if (methodDef.IsStatic && methodDef.IsConstructor)
                        {
                            if (methodDef.TypeArity > 0)
                            {
                                throw new InvalidOperationException
                                          ("static constructors cannot be polymorphic");
                            }
                            StaticInitializer = new CST.MethodRef(TyconEnv.AddSelfTypeBoundArguments().TypeRef, methodDef.MethodSignature, null);
                        }
                        else if (!methodDef.IsStatic && methodDef.IsConstructor && methodDef.Arity == 1 &&
                                 !Env.InteropManager.IsFactory(TyconEnv.Assembly, TyconEnv.Type, methodDef))
                        {
                            if (methodDef.TypeArity > 0)
                            {
                                throw new InvalidOperationException
                                          ("instance constructors cannot be polymorphic");
                            }
                            DefaultConstructor = new CST.MethodRef(TyconEnv.AddSelfTypeBoundArguments().TypeRef, methodDef.MethodSignature, null);
                        }
                        if (Env.InteropManager.IsExported(TyconEnv.Assembly, TyconEnv.Type, methodDef))
                        {
                            if (Env.InteropManager.IsBindToInstance
                                    (TyconEnv.Assembly, TyconEnv.Type, methodDef))
                            {
                                exportedInstanceMethods.Add(methodDef);
                            }
                            // else: will be exported by assembly's Initialize function
                        }

                        methods.Add(methodDef);

                        if (TypeTrace == null || TypeTrace.Methods.Contains(methodDef.MethodSignature))
                        {
                            numRelevantMethods++;
                        }
                    }
                }
            }
            // else: ignore members of interface and delegate types
            // TODO: Need to emit reflection data for methods of interface types, thus will need
            //       to collect interface methods

            Fields     = fields;
            Events     = events;
            Properties = properties;
            Methods    = methods;
            ExportedInstanceMethods = exportedInstanceMethods;
        }