Example #1
0
    /// <summary>
    /// Given a method contract (<paramref name="methodContract"/> for a unspecialized/uninstantiated method reference/definition
    /// (<paramref name="unspec"/>), specialize and instantiate (i.e., the generics) in the contract so that it is a contract
    /// relative to the specialized/instantiated method reference/definition (<paramref name="mr"/>).
    /// </summary>
    /// <param name="host"></param>
    /// <param name="methodContract"></param>
    /// <param name="mr"></param>
    /// <param name="unspec"></param>
    /// <returns>
    /// A deep copy of <paramref name="methodContract"/>, properly specialized and instantiated.
    /// </returns>
    public static MethodContract InstantiateAndSpecializeContract(IMetadataHost host, IMethodContract methodContract, IMethodReference mr, IMethodReference unspec) {
      //Contract.Requires(mr is IGenericMethodInstanceReference || mr is ISpecializedMethodReference);

      var copier = new CodeAndContractDeepCopier(host);
      var mutableContract = copier.Copy(methodContract);

      var unspecializedTypeReferences = new List<ITypeReference>();
      var specializedTypeReferences = new List<ITypeReference>();

      var copyOfUnspecializedContainingType = copier.Copy(unspec.ContainingType);
      unspecializedTypeReferences.Add(copyOfUnspecializedContainingType);
      var containingType = mr.ContainingType;
      var gtir2 = containingType as IGenericTypeInstanceReference;
      var copyOfSpecializedContainingType = gtir2 != null ? copier.Copy(gtir2) : copier.Copy(containingType);
      specializedTypeReferences.Add(copyOfSpecializedContainingType);

      var unspecializedMethodDefinition = unspec as IMethodDefinition;

      #region Map generic type parameters
      var smr = mr as ISpecializedMethodReference;
      if (smr != null) {
        if (unspecializedMethodDefinition != null) {
          foreach (var t in unspecializedMethodDefinition.ContainingTypeDefinition.GenericParameters) {
            // without the cast, the copy is not object equals to references within the contract
            var copyOfT = copier.Copy((IGenericTypeParameterReference)t);
            unspecializedTypeReferences.Add(copyOfT);
          }
          var gtir = smr.ContainingType as IGenericTypeInstanceReference;
          if (gtir != null) {
            foreach (var t in gtir.GenericArguments) {
              var copyOfT = copier.Copy(t);
              specializedTypeReferences.Add(copyOfT);
            }
          }
        }
      }
      #endregion
      #region Map generic method parameters
      var gmir = mr as IGenericMethodInstanceReference;
      if (gmir != null) {
        var unspecialized = gmir.GenericMethod.ResolvedMethod;
        foreach (var t in unspecialized.GenericParameters) {
          var copyOfT = copier.Copy(t);
          unspecializedTypeReferences.Add(copyOfT);
        }
        foreach (var t in gmir.GenericArguments) {
          var copyOfT = copier.Copy(t);
          specializedTypeReferences.Add(copyOfT);
        }
      }
      #endregion
      var d = new Dictionary<uint, ITypeReference>();
      IteratorHelper.Zip(unspecializedTypeReferences, specializedTypeReferences, (u, s) => d.Add(u.InternedKey, s));
      var specializer = new CodeSpecializer(host, d);

      mutableContract = (MethodContract)specializer.Rewrite(mutableContract);
      mutableContract = (MethodContract)ContractHelper.CopyContractIntoNewContext(host, mutableContract, smr != null ? smr.ResolvedMethod : mr.ResolvedMethod, unspecializedMethodDefinition);
      return mutableContract;
    }
Example #2
0
    /// <summary>
    /// Returns a method contract containing the 'effective' contract for the given
    /// method definition. The effective contract contains all contracts for the method:
    /// any that it has on its own, as well as all those inherited from any methods
    /// that it overrides or interface methods that it implements (either implicitly
    /// or explicitly).
    /// All parameters in inherited contracts are substituted for by
    /// the method's own parameters.
    /// If there are no contracts, then it returns null.
    /// Any preconditions that were written as legacy-preconditions or calls to Requires&lt;E&gt; are
    /// included iff <paramref name="keepLegacyPreconditions"/>.
    /// </summary>
    public static IMethodContract GetMethodContractForIncludingInheritedContracts(IContractAwareHost host, IMethodDefinition methodDefinition, bool keepLegacyPreconditions = true) {
      MethodContract cumulativeContract = new MethodContract();
      bool atLeastOneContract = false;
      IMethodContract/*?*/ mc = ContractHelper.GetMethodContractFor(host, methodDefinition);
      if (mc != null) {
        Microsoft.Cci.MutableContracts.ContractHelper.AddMethodContract(cumulativeContract, mc);
        atLeastOneContract = true;
      }
      #region Overrides of base class methods
      if (!methodDefinition.IsNewSlot) { // REVIEW: Is there a better test?
        IMethodDefinition overriddenMethod = MemberHelper.GetImplicitlyOverriddenBaseClassMethod(methodDefinition) as IMethodDefinition;
        while (overriddenMethod != null && !(overriddenMethod is Dummy)) {
          IMethodContract/*?*/ overriddenContract = ContractHelper.GetMethodContractFor(host, overriddenMethod);
          if (overriddenContract != null) {

            overriddenContract = CopyContractIntoNewContext(host, overriddenContract, methodDefinition, overriddenMethod);
            overriddenContract = FilterUserMessageAndLegacyPreconditions(host, overriddenContract, methodDefinition.ContainingTypeDefinition, keepLegacyPreconditions);

            // if the method is generic, then need to specialize the contract to have the same method type parameters as the method
            if (methodDefinition.IsGeneric) {
              var d = new Dictionary<uint, ITypeReference>();
              IteratorHelper.Zip(overriddenMethod.GenericParameters, methodDefinition.GenericParameters, (i, j) => d.Add(i.InternedKey, j));
              var cs = new CodeSpecializer(host, d);
              overriddenContract = cs.Rewrite(overriddenContract);
            }

            Microsoft.Cci.MutableContracts.ContractHelper.AddMethodContract(cumulativeContract, overriddenContract);
            atLeastOneContract = true;
          }
          overriddenMethod = MemberHelper.GetImplicitlyOverriddenBaseClassMethod(overriddenMethod) as IMethodDefinition;
        }
      }
      #endregion Overrides of base class methods
      #region Implicit interface implementations
      foreach (IMethodDefinition ifaceMethod in ContractHelper.GetAllImplicitlyImplementedInterfaceMethods(methodDefinition)) {
        IMethodContract/*?*/ ifaceContract = ContractHelper.GetMethodContractFor(host, ifaceMethod);
        if (ifaceContract == null) continue;
        ifaceContract = CopyContractIntoNewContext(host, ifaceContract, methodDefinition, ifaceMethod);
        ifaceContract = FilterUserMessageAndLegacyPreconditions(host, ifaceContract, methodDefinition.ContainingTypeDefinition, keepLegacyPreconditions);
        Microsoft.Cci.MutableContracts.ContractHelper.AddMethodContract(cumulativeContract, ifaceContract);
        atLeastOneContract = true;
      }
      #endregion Implicit interface implementations
      #region Explicit interface implementations and explicit method overrides
      foreach (IMethodReference ifaceMethodRef in MemberHelper.GetExplicitlyOverriddenMethods(methodDefinition)) {
        IMethodDefinition/*?*/ ifaceMethod = ifaceMethodRef.ResolvedMethod;
        if (ifaceMethod == null) continue;
        IMethodContract/*?*/ ifaceContract = ContractHelper.GetMethodContractFor(host, ifaceMethod);
        if (ifaceContract == null) continue;
        ifaceContract = CopyContractIntoNewContext(host, ifaceContract, methodDefinition, ifaceMethod);
        ifaceContract = FilterUserMessageAndLegacyPreconditions(host, ifaceContract, methodDefinition.ContainingTypeDefinition, keepLegacyPreconditions);
        Microsoft.Cci.MutableContracts.ContractHelper.AddMethodContract(cumulativeContract, ifaceContract);
        atLeastOneContract = true;
      }
      #endregion Explicit interface implementations and explicit method overrides
      return atLeastOneContract ? cumulativeContract : null;
    }