A collection of methods that can be called in a way that provides tools with information about contracts.
Inheritance: IContractMethods
Example #1
0
 /// <summary>
 /// Given a mutable module that is a "declarative" module, i.e., it has contracts expressed as contract calls
 /// at the beginning of method bodies, this method will extract them, leaving the method bodies without those
 /// calls and return a contract provider for the module containing any extracted contracts.
 /// </summary>
 public static ContractProvider ExtractContracts(IContractAwareHost host, Module module, PdbReader/*?*/ pdbReader, ILocalScopeProvider/*?*/ localScopeProvider) {
   var contractMethods = new ContractMethods(host);
   var cp = new Microsoft.Cci.MutableContracts.ContractProvider(contractMethods, module);
   var extractor = new SeparateContractsFromCode(host, pdbReader, localScopeProvider, cp);
   extractor.Traverse(module);
   return cp;
 }
Example #2
0
    /// <summary>
    /// If the unit is a reference assembly, then just attach a contract extractor to it.
    /// Otherwise, create an aggregating extractor that encapsulates the unit and any
    /// reference assemblies that are found on the search path.
    /// Each contract extractor is actually a composite comprising a code-contracts
    /// extractor layered on top of a lazy extractor.
    /// </summary>
    protected void AttachContractExtractorAndLoadReferenceAssembliesFor(IUnit alreadyLoadedUnit) {

      // Because of unification, the "alreadyLoadedUnit" might have actually already been loaded previously
      // and gone through here (and so already has a contract provider attached to it).
      if (this.unit2ContractExtractor.ContainsKey(alreadyLoadedUnit.UnitIdentity))
        this.unit2ContractExtractor.Remove(alreadyLoadedUnit.UnitIdentity);
      //return;

      var contractMethods = new ContractMethods(this);
      using (var lazyContractProviderForLoadedUnit = new LazyContractExtractor(this, alreadyLoadedUnit, contractMethods, this.AllowExtractorsToUsePdbs)) {
        var contractProviderForLoadedUnit = new CodeContractsContractExtractor(this, lazyContractProviderForLoadedUnit);
        if (ContractHelper.IsContractReferenceAssembly(this, alreadyLoadedUnit)) {
          // If we're asked to explicitly load a reference assembly, then go ahead and attach a contract provider to it,
          // but *don't* look for reference assemblies for *it*.
          this.unit2ContractExtractor.Add(alreadyLoadedUnit.UnitIdentity, contractProviderForLoadedUnit);
        } else {
          #region Load any reference assemblies for the loaded unit
          var loadedAssembly = alreadyLoadedUnit as IAssembly; // Only assemblies can have associated reference assemblies.
          var oobProvidersAndHosts = new List<KeyValuePair<IContractProvider, IMetadataHost>>();
          if (loadedAssembly != null) {
            var refAssemWithoutLocation =
              new AssemblyIdentity(this.NameTable.GetNameFor(alreadyLoadedUnit.Name.Value + ".Contracts"),
                loadedAssembly.AssemblyIdentity.Culture,
                loadedAssembly.AssemblyIdentity.Version,
                loadedAssembly.AssemblyIdentity.PublicKeyToken,
                "");
            var referenceAssemblyIdentity = this.ProbeAssemblyReference(alreadyLoadedUnit, refAssemWithoutLocation);
            IUnit referenceUnit = null;
            IContractAwareHost hostForReferenceAssembly = this; // default
            if (referenceAssemblyIdentity.Location.Equals("unknown://location")) {
              // It might be the case that this was returned because the identity constructed for it had the wrong version number
              // (or something else that didn't match the identity of hte already loaded unit). But it might be that the probing
              // logic succeeded in loading *some* reference assembly. And we're not picky: the reference assembly is just
              // the first assembly found with the right name.
              foreach (var u in this.LoadedUnits) {
                if (u.Name.Equals(refAssemWithoutLocation.Name)) {
                  // fine, use this one!
                  referenceUnit = u;
                  break;
                }
              }
              if (referenceUnit != null && loadedAssembly.AssemblyIdentity.Equals(this.CoreAssemblySymbolicIdentity)) {
                // Need to use a separate host because the reference assembly for the core assembly thinks *it* is the core assembly
                var separateHost = new SimpleHostEnvironment(this.NameTable, this.InternFactory, this.PreserveILLocations);
                this.disposableObjectAllocatedByThisHost.Add(separateHost);
                referenceUnit = separateHost.LoadUnitFrom(referenceUnit.Location);
                hostForReferenceAssembly = separateHost;
              }
            } else {
              // referenceAssemblyIdentity.Location != "unknown://location")
              #region Load reference assembly
              if (loadedAssembly.AssemblyIdentity.Equals(this.CoreAssemblySymbolicIdentity)) {
                // Need to use a separate host because the reference assembly for the core assembly thinks *it* is the core assembly
                var separateHost = new SimpleHostEnvironment(this.NameTable, this.InternFactory, this.PreserveILLocations);
                this.disposableObjectAllocatedByThisHost.Add(separateHost);
                referenceUnit = separateHost.LoadUnitFrom(referenceAssemblyIdentity.Location);
                hostForReferenceAssembly = separateHost;
              } else {
                // Load reference assembly, but don't cause a recursive call!! So don't call LoadUnit or LoadUnitFrom
                referenceUnit = this.peReader.OpenModule(BinaryDocument.GetBinaryDocumentForFile(referenceAssemblyIdentity.Location, this));
                this.RegisterAsLatest(referenceUnit);
              }
              #endregion
            }
            #region Attach a contract provider to it
            if (referenceUnit != null && !(referenceUnit is Dummy)) {
              IAssembly referenceAssembly = referenceUnit as IAssembly;
              if (referenceAssembly != null) {
                var referenceAssemblyContractProvider = new CodeContractsContractExtractor(hostForReferenceAssembly,
                  new LazyContractExtractor(hostForReferenceAssembly, referenceAssembly, contractMethods, this.AllowExtractorsToUsePdbs));
                oobProvidersAndHosts.Add(new KeyValuePair<IContractProvider, IMetadataHost>(referenceAssemblyContractProvider, hostForReferenceAssembly));
                if (!this.unit2ReferenceAssemblies.ContainsKey(alreadyLoadedUnit)) {
                  this.unit2ReferenceAssemblies[alreadyLoadedUnit] = new List<IUnitReference>();
                }
                // Reference assemblies don't have references to the real assembly but they are "dependent"
                // on them in that they should be dumped and reloaded if the real assembly changes.
                this.unit2ReferenceAssemblies[alreadyLoadedUnit].Add(referenceAssembly);
              }
            }
            #endregion
          }
          var aggregateContractProvider = new AggregatingContractExtractor(this, contractProviderForLoadedUnit, oobProvidersAndHosts);
          this.unit2ContractExtractor.Add(alreadyLoadedUnit.UnitIdentity, aggregateContractProvider);
          #endregion Load any reference assemblies for the loaded unit
        }
        foreach (var c in this.callbacks) {
          contractProviderForLoadedUnit.RegisterContractProviderCallback(c);
        }
      }
    }