/// <summary> /// Creates a reference resolver. /// </summary> /// <param name="resolver"> /// The assembly resolver to use. /// </param> /// <param name="typeEnvironment"> /// The reference resolver's type environment. /// </param> public ReferenceResolver( AssemblyResolver resolver, TypeEnvironment typeEnvironment) { this.AssemblyResolver = resolver; this.TypeEnvironment = typeEnvironment; this.assemblyCache = new Dictionary <string, IAssembly>(); this.typeResolvers = new Dictionary <IAssembly, TypeResolver>(); this.cacheLock = new ReaderWriterLockSlim(); this.fieldIndex = new Index <IType, KeyValuePair <string, IType>, IField>( type => type.Fields .Select(field => new KeyValuePair <KeyValuePair <string, IType>, IField>( new KeyValuePair <string, IType>( field.Name.ToString(), field.FieldType), field))); this.methodIndex = new Index <IType, ClrMethodSignature, IMethod>( type => type.Methods .Concat( type.Properties.SelectMany(prop => prop.Accessors)) .Select(method => new KeyValuePair <ClrMethodSignature, IMethod>( ClrMethodSignature.Create(method), method))); this.propertyIndex = new Index <IType, ClrPropertySignature, IProperty>( type => type.Properties.Select(prop => new KeyValuePair <ClrPropertySignature, IProperty>( ClrPropertySignature.Create(prop), prop))); }
/// <summary> /// Resolves a method reference. /// </summary> /// <param name="methodRef">The method reference to resolve.</param> /// <param name="assembly">The assembly that declares the reference.</param> /// <returns>The method referred to by the reference.</returns> internal IMethod Resolve(MethodReference methodRef, ClrAssembly assembly) { if (methodRef is MethodSpecification) { if (methodRef is GenericInstanceMethod) { var genInstMethod = (GenericInstanceMethod)methodRef; var elemMethod = Resolve(genInstMethod.ElementMethod, assembly); return(elemMethod.MakeGenericMethod( genInstMethod.GenericArguments .Select(arg => Resolve(arg, assembly)) .Zip(elemMethod.GenericParameters, BoxTypeArgumentIfNecessary) .ToArray())); } else { throw new NotSupportedException( "Cannot resolve unsupported method specification type " + $"'{methodRef.GetType()}' for method reference '{methodRef}'."); } } var declaringType = Resolve(methodRef.DeclaringType, assembly); var name = NameConversion.ParseSimpleName(methodRef.Name); var standinReplacer = CreateStandinReplacingVisitor(declaringType); var standinRetType = Resolve(methodRef.ReturnType, assembly, declaringType, true); var returnType = TypeHelpers.BoxIfReferenceType( standinReplacer.Visit(standinRetType)); var parameterTypes = methodRef.Parameters .Select(param => TypeHelpers.BoxIfReferenceType( standinReplacer.Visit( Resolve(param.ParameterType, assembly, declaringType, true)))) .ToArray(); return(PickSingleResolvedMember( methodRef, methodIndex.GetAll( declaringType, ClrMethodSignature.Create( name, methodRef.GenericParameters.Count, returnType, parameterTypes)))); }
private void AnalyzeOverrides() { // A method's base methods consist of its implicit // and explicit overrides. (Flame doesn't distinguish // between these two.) // // * Explicit overrides are extracted directly from // the method definition. // // * Implicit overrides are derived by inspecting // the base types of the type declaring the method: // a method declared/defined in one of the base types // is an implicit override candidate if it is not // already overridden either by a method in another // base type or (explicitly) in the declaring type. // // The ugly bit is that *all* virtual methods in // a type participate in override resolution: explicit // overrides can be resolved individually, but implicit // overrides always depend on other methods. // // We know that the (type) inheritance graph is a DAG, so // we can safely derive overrides by walking the inheritance // graph. Specifically, we'll construct a set of virtual // methods for each type: // // * Initialize the virtual method set as the union of // the virtual method sets of the base types. // // * Remove all explicit overrides from the set and add // them to the overriding methods. // // * Remove all implicit overrides from the set and add // them to the overriding methods. // virtualMethodSet = new HashSet <IMethod>(); contentsInitializer.Initialize(); foreach (var baseType in baseTypeList) { if (baseType is ClrTypeDefinition) { // Optimization for ClrTypeDefinition instances. var clrBaseType = (ClrTypeDefinition)baseType; clrBaseType.OverrideInitializer.Initialize(); virtualMethodSet.UnionWith(clrBaseType.virtualMethodSet); } else { // General case. virtualMethodSet.UnionWith(baseType.GetVirtualMethodSet()); } } var allMethodDefs = methodDefList .Concat(propertyDefList.SelectMany(prop => prop.Accessors)) .ToArray(); // Special case: interfaces. These guys never override anything, // so we can skip the regular override resolution process and skip // right to the part where we add all methods to the virtual // method set. if (Definition.IsInterface) { virtualMethodSet.UnionWith(allMethodDefs); foreach (var method in allMethodDefs) { method.BaseMethodStore = new List <IMethod>(); } return; } // Handle explicit overrides. foreach (var method in allMethodDefs) { method.BaseMethodStore = new List <IMethod>(); foreach (var overrideRef in method.Definition.Overrides) { var overrideMethod = Assembly.Resolve(overrideRef); method.BaseMethodStore.Add(overrideMethod); virtualMethodSet.Remove(overrideMethod); } } // Populate a mapping of method signatures to lists of methods // so we can efficiently match methods to overrides. var virtualMethodSignatures = new Dictionary <ClrMethodSignature, List <IMethod> >(); foreach (var virtualMethod in virtualMethodSet) { var signature = ClrMethodSignature.Create(virtualMethod); List <IMethod> virtualMethodList; if (!virtualMethodSignatures.TryGetValue( signature, out virtualMethodList)) { virtualMethodList = new List <IMethod>(); virtualMethodSignatures[signature] = virtualMethodList; } virtualMethodList.Add(virtualMethod); } // Handle implicit overrides. foreach (var method in allMethodDefs) { if (method.Definition.IsVirtual) { var signature = ClrMethodSignature.Create(method); List <IMethod> virtualMethodList; if (virtualMethodSignatures.TryGetValue( signature, out virtualMethodList)) { foreach (var overrideMethod in virtualMethodList) { if (virtualMethodSet.Contains(overrideMethod)) { method.BaseMethodStore.Add(overrideMethod); virtualMethodSet.Remove(overrideMethod); } } } } } // Add virtual methods to virtual method set. foreach (var method in allMethodDefs) { if (method.Definition.IsVirtual && !method.Definition.IsFinal) { virtualMethodSet.Add(method); } } }