Beispiel #1
0
        /// <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)));
        }
Beispiel #2
0
        /// <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);
                }
            }
        }