Exemplo n.º 1
0
        private void Touch(Attribute attr, TypeChain typeChain = null)
        {
            var type = this.mdDecoder.AttributeType(attr);

            this.Touch(type);

            this.Touch(this.mdDecoder.AttributeConstructor(attr));

            foreach (var arg in this.mdDecoder.PositionalArguments(attr).Enumerate())
            {
                if (arg == null || arg is string || arg.GetType().IsPrimitive)
                {
                    continue;
                }
                if (arg is Type)
                {
                    this.Touch((Type)arg);
                }
                else
                {
                    throw new NotImplementedException("Attribute argument of type " + arg.GetType().Name);
                }
            }

            if (typeChain != null && this.mdDecoder.FullName(type) == NameFor.ContractClassAttribute)
            {
                var arg = this.mdDecoder.PositionalArguments(attr)[0];
                if (arg is Type)
                {
                    typeChain.ContractClass = this.GetTypeChain((Type)arg);
                }
            }
        }
Exemplo n.º 2
0
        private void Touch(IEnumerable <Attribute> attrs, TypeChain typeChain = null)
        {
            Contract.Requires(attrs != null);

            foreach (var attr in attrs)
            {
                this.Touch(attr, typeChain);
            }
        }
Exemplo n.º 3
0
        private TypeChain GetTypeChain(Type type)
        {
            TypeChain chain;

            if (this.cachedTouchedTypes.TryGetValue(type, out chain))
            {
                return(chain);
            }

            if (this.mdDecoder.IsVoid(type) || this.mdDecoder.IsPrimitive(type) || this.mdDecoder.Equal(type, this.mdDecoder.System_Object) || // primitive types
                this.mdDecoder.IsFormalTypeParameter(type) || this.mdDecoder.IsMethodFormalTypeParameter(type)) // abstract types
            {
                this.cachedTouchedTypes.Add(type, null);
                return(null);
            }

            Type modified;
            IIndexable <Pair <bool, Type> > modifiers;

            if (this.mdDecoder.IsModified(type, out modified, out modifiers)) // modified types
            {
                foreach (var p in modifiers.Enumerate())
                {
                    this.Touch(p.Two);
                }
                chain = this.GetTypeChain(modified);
                this.cachedTouchedTypes.Add(type, chain);
            }
            else if (this.mdDecoder.IsArray(type) || this.mdDecoder.IsManagedPointer(type) || this.mdDecoder.IsUnmanagedPointer(type)) // boxing types
            {
                chain = this.GetTypeChain(this.mdDecoder.ElementType(type));
                this.cachedTouchedTypes.Add(type, chain);
            }
            else
            {
                IIndexable <Type> typeArguments;
                if (this.mdDecoder.NormalizedIsSpecialized(type, out typeArguments)) // specialized types
                {
                    foreach (var t in typeArguments.Enumerate())
                    {
                        this.Touch(t);
                    }
                    chain = this.GetTypeChain(this.mdDecoder.Unspecialized(type));
                    this.cachedTouchedTypes.Add(type, chain);
                }
                else if (this.mdDecoder.Namespace(type) == null && this.mdDecoder.Name(type) == this.mdDecoder.FullName(type)) // weird types like function pointers (TODO)
                {
                    this.cachedTouchedTypes.Add(type, null);
                    return(null);
                }
                else // named types
                {
                    // here type should be a INamedTypeDefinition
                    if (!this.IsAssemblySelected(this.mdDecoder.DeclaringModuleName(type)))
                    {
                        // do not keep types from other assemblies
                        this.cachedTouchedTypes.Add(type, null);
                        return(null);
                    }

                    chain = new TypeChain(type);
                    this.cachedTouchedTypes.Add(type, chain); // put this here because of cyclic dependences

                    Type parentType;
                    if (this.mdDecoder.IsNested(type, out parentType)) // nested types
                    {
                        var parentChain = this.GetTypeChain(parentType);
                        if (parentChain == null)
                        {
                            this.cachedTouchedTypes[type] = null;
                            return(null);
                        }
                        parentChain.Add(type, chain);
                    }
                    else
                    {
                        this.Add(type, chain);
                    }
                }
            }
            // No need to keep dependences of types that we won't keep anyway
            if (chain == null)
            {
                return(null);
            }

            // Put this here to avoid infinite recursion

            if (this.mdDecoder.HasBaseClass(type)) // add the base class
            {
                this.Touch(this.mdDecoder.BaseClass(type));
            }

            foreach (var t in this.mdDecoder.Interfaces(type)) // add the implemented interfaces
            {
                this.Touch(t);
            }

            this.Touch(this.mdDecoder.GetAttributes(type), chain);

            foreach (var f in this.mdDecoder.Fields(type))
            {
                this.Touch(f);
            }
            foreach (var p in this.mdDecoder.Properties(type))
            {
                Method getter;
                if (this.mdDecoder.HasGetter(p, out getter))
                {
                    this.Touch(getter);
                }
            }
            foreach (var m in this.mdDecoder.Methods(type))
            {
                if (this.contractDecoder.IsPure(m))
                {
                    this.Touch(m);
                }
            }

            return(chain);
        }