Beispiel #1
0
        // Public API

        /// <summary>
        /// Modifies <paramref name="assembly"/> by extracting any Code Contracts
        /// from the method bodies in the assembly.
        /// <param name="assembly">
        /// The assembly to which the contracts will be added (i.e., the AST for the assembly
        /// will be enriched with method contracts and object invariants).
        /// </param>
        /// <param name="referenceAssembly">
        /// When not null, then the contracts are extracted from this assembly and then copied over
        /// to <paramref name="assembly"/>. Note that in that case, no contracts are extracted
        /// directly from <paramref name="assembly"/>: all of the contracts in <paramref name="assembly"/>
        /// after this method returns came from this assembly.
        /// </param>
        /// <param name="contracts">
        /// When not null, this will be used for the definitions of the contract methods (and
        /// attributes) in <paramref name="assembly"/> (or <paramref name="referenceAssembly"/>, if that
        /// is not null). When null, then we will make an effort to find the contract methods. In
        /// either case, the definitions might be found within <paramref name="assembly"/> (or
        /// <paramref name="referenceAssembly"/>) anyway.
        /// </param>
        /// <param name="targetContractNodes">
        /// This parameter is used for the definitions of the contract methods (and
        /// attributes) that are the definitions that are embedded within the contracts,
        /// e.g., the definition of the ForAll method are found in the return value.
        /// It may be the same as <paramref name="contracts"/>. If it is passed in as null,
        /// then it will be filled in with the nodes used by the Extractor.
        /// </param>
        /// <param name="useClousotExtractor">
        /// When true, use a "Clousot" extractor, which does some extra processing needed for static
        /// analysis.
        /// </param>
        /// <returns>
        /// True iff extraction was possible. (I.e., a set of contractNodes was found to use for
        /// the extraction --- it does *not* guarantee that any contracts were found in the assembly.)
        /// </returns>
        /// </summary>
        ///
        public static bool ExtractContracts(AssemblyNode /*!*/ assembly,
                                            AssemblyNode /*?*/ referenceAssembly,
                                            ContractNodes /*?*/ contracts,
                                            ContractNodes /*?*/ backupContracts,
                                            ContractNodes /*?*/ targetContractNodes,
                                            out ContractNodes /*?*/ contractNodesUsedToExtract,
                                            Action <CompilerError> /*?*/ errorHandler,
                                            bool useClousotExtractor)
        {
            Contract.Requires(assembly != null);

            AssemblyNode assemblyToVisit = referenceAssembly ?? assembly;

            // Try to use supplied contracts, if present. But don't just try extracting and somehow
            // figuring out if any contracts had been present. Instead, see if:
            //   a) the contract methods are defined in the assembly we are extracting from, or
            //   b) the assembly reference microsoft.contracts.dll (the backup contracts and we found that assembly)
            //   c) the assembly we are extracting from has an external reference to the assembly
            //      the supplied contract methods came from.
            //   d) the contracts found in mscorlib
            //

            // see if the assembly references the backup contracts (Microsoft.Contracts.dll)
            contractNodesUsedToExtract = IdentifyContractAssemblyIfReferenced(backupContracts, assemblyToVisit);

            // see if assembly defines the contracts itself
            if (contractNodesUsedToExtract == null)
            {
                contractNodesUsedToExtract = ContractNodes.GetContractNodes(assemblyToVisit, errorHandler);
            }

            // see if the assembly references the supplied contract assembly
            if (contractNodesUsedToExtract == null)
            {
                contractNodesUsedToExtract = IdentifyContractAssemblyIfReferenced(contracts, assemblyToVisit);
            }

            // see if the contracts are in the system assembly
            if (contractNodesUsedToExtract == null && assemblyToVisit != SystemTypes.SystemAssembly)
            {
                contractNodesUsedToExtract = ContractNodes.GetContractNodes(SystemTypes.SystemAssembly, errorHandler);
            }

            if (contractNodesUsedToExtract == null)
            {
                return(false);
            }

            var fSharp = false;

            // TODO: Thread the program options through here somehow and let this be specified as an option
            Contract.Assume(assemblyToVisit.Attributes != null);
            foreach (var attr in assemblyToVisit.Attributes)
            {
                Contract.Assume(attr != null);
                Contract.Assume(attr.Type != null);
                Contract.Assume(attr.Type.Name != null);
                Contract.Assume(attr.Type.Name.Name != null);

                if (attr.Type.Name.Name.Contains("FSharpInterfaceDataVersionAttribute"))
                {
                    fSharp = true;
                    break;
                }
            }

            var ultimateTarget = (referenceAssembly != null) ? assembly : null;

            Contract.Assert(assembly != null);

            ExtractorVisitor ev = useClousotExtractor
                ? new ClousotExtractor(contractNodesUsedToExtract, ultimateTarget, assembly, errorHandler)
                : new ExtractorVisitor(contractNodesUsedToExtract, ultimateTarget, assembly, false, fSharp);

            ev.Visit(assemblyToVisit);

            if (!useClousotExtractor)
            {
                FilterForRuntime eoar = new FilterForRuntime(contractNodesUsedToExtract, targetContractNodes);
                assemblyToVisit = eoar.TransformForTarget(assemblyToVisit);
            }

            if (referenceAssembly != null)
            {
                CopyOutOfBandContracts coob = new CopyOutOfBandContracts(assembly, referenceAssembly,
                                                                         contractNodesUsedToExtract, targetContractNodes);
                coob.VisitAssembly(referenceAssembly);
            }

            return(true);
        }
        public static bool ExtractContracts(AssemblyNode /*!*/ assembly,
            AssemblyNode /*?*/ referenceAssembly,
            ContractNodes /*?*/ contracts,
            ContractNodes /*?*/ backupContracts,
            ContractNodes /*?*/ targetContractNodes,
            out ContractNodes /*?*/ contractNodesUsedToExtract,
            Action<CompilerError> /*?*/ errorHandler,
            bool useClousotExtractor)
        {
            Contract.Requires(assembly != null);

            AssemblyNode assemblyToVisit = referenceAssembly ?? assembly;

            // Try to use supplied contracts, if present. But don't just try extracting and somehow
            // figuring out if any contracts had been present. Instead, see if:
            //   a) the contract methods are defined in the assembly we are extracting from, or
            //   b) the assembly reference microsoft.contracts.dll (the backup contracts and we found that assembly)
            //   c) the assembly we are extracting from has an external reference to the assembly
            //      the supplied contract methods came from.
            //   d) the contracts found in mscorlib
            //

            // see if the assembly references the backup contracts (Microsoft.Contracts.dll)
            contractNodesUsedToExtract = IdentifyContractAssemblyIfReferenced(backupContracts, assemblyToVisit);

            // see if assembly defines the contracts itself
            if (contractNodesUsedToExtract == null)
            {
                contractNodesUsedToExtract = ContractNodes.GetContractNodes(assemblyToVisit, errorHandler);
            }

            // see if the assembly references the supplied contract assembly
            if (contractNodesUsedToExtract == null)
            {
                contractNodesUsedToExtract = IdentifyContractAssemblyIfReferenced(contracts, assemblyToVisit);
            }

            // see if the contracts are in the system assembly
            if (contractNodesUsedToExtract == null && assemblyToVisit != SystemTypes.SystemAssembly)
            {
                contractNodesUsedToExtract = ContractNodes.GetContractNodes(SystemTypes.SystemAssembly, errorHandler);
            }

            if (contractNodesUsedToExtract == null) return false;

            var fSharp = false;

            // TODO: Thread the program options through here somehow and let this be specified as an option
            Contract.Assume(assemblyToVisit.Attributes != null);
            foreach (var attr in assemblyToVisit.Attributes)
            {
                Contract.Assume(attr != null);
                Contract.Assume(attr.Type != null);
                Contract.Assume(attr.Type.Name != null);
                Contract.Assume(attr.Type.Name.Name != null);

                if (attr.Type.Name.Name.Contains("FSharpInterfaceDataVersionAttribute"))
                {
                    fSharp = true;
                    break;
                }
            }

            var ultimateTarget = (referenceAssembly != null) ? assembly : null;

            Contract.Assert(assembly != null);

            ExtractorVisitor ev = useClousotExtractor
                ? new ClousotExtractor(contractNodesUsedToExtract, ultimateTarget, assembly, errorHandler)
                : new ExtractorVisitor(contractNodesUsedToExtract, ultimateTarget, assembly, false, fSharp);

            ev.Visit(assemblyToVisit);

            if (!useClousotExtractor)
            {
                FilterForRuntime eoar = new FilterForRuntime(contractNodesUsedToExtract, targetContractNodes);
                assemblyToVisit = eoar.TransformForTarget(assemblyToVisit);
            }

            if (referenceAssembly != null)
            {
                CopyOutOfBandContracts coob = new CopyOutOfBandContracts(assembly, referenceAssembly,
                    contractNodesUsedToExtract, targetContractNodes);
                coob.VisitAssembly(referenceAssembly);
            }

            return true;
        }