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); } } }
private void Touch(IEnumerable <Attribute> attrs, TypeChain typeChain = null) { Contract.Requires(attrs != null); foreach (var attr in attrs) { this.Touch(attr, typeChain); } }
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); }