Beispiel #1
0
 private void InjectStaticInitializerIfNoneSpecified(TypeNode typeNode){
   if (typeNode.NodeType == NodeType.EnumNode) return;
   MemberList staticCons = typeNode.GetMembersNamed(StandardIds.CCtor);
   if (staticCons != null && staticCons.Count > 0) return;
   StatementList statements = null;
   MemberList members = typeNode.Members;
   for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++){
     Field f = members[i] as Field;
     if (f == null) continue;
     if (!f.IsStatic) continue;
     if (f.IsLiteral) continue;
     if (f.Initializer == null) continue;
     statements = new StatementList(1);
     break;
   }
   if (statements == null && typeNode.Contract != null && typeNode.Contract.FrameField != null)
     statements = new StatementList(1);
   if (statements != null){
     FieldInitializerBlock finitBlock = new FieldInitializerBlock(typeNode, true);
     statements.Add(finitBlock);
     StaticInitializer cctor = new StaticInitializer(typeNode, null, new Block(statements));
     typeNode.Members.Add(cctor);
     if (typeNode.PartiallyDefines != null){
       staticCons = typeNode.PartiallyDefines.GetMembersNamed(StandardIds.CCtor);
       if (staticCons == null || staticCons.Count == 0){
         finitBlock.Type = typeNode.PartiallyDefines;
         cctor.DeclaringType = typeNode.PartiallyDefines;
         typeNode.PartiallyDefines.Members.Add(cctor);
       }
     }
   }
 }
        /// <summary>
        /// Returns correct version of the ContinueWith method.
        /// </summary>
        /// <remarks>
        /// This function returns ContinueWith overload that takes TaskContinuationOptions.
        /// </remarks>
        private static Method GetContinueWithMethod(Class closureClass, TypeNode taskTemplate, TypeNode taskType)
        {
            var continueWithCandidates = taskTemplate.GetMembersNamed(Identifier.For("ContinueWith"));
            
            // Looking for an overload with TaskContinuationOptions
            const int expectedNumberOfArguments = 2;

            for (int i = 0; i < continueWithCandidates.Count; i++)
            {
                var cand = continueWithCandidates[i] as Method;
                if (cand == null) continue;

                // For non-generic version we're looking for ContinueWith(Action<Task>, TaskContinuationOptions)

                if (!taskType.IsGeneric)
                {
                    if (cand.IsGeneric) continue;

                    if (cand.ParameterCount != expectedNumberOfArguments) continue;

                    if (cand.Parameters[0].Type.GetMetadataName() != "Action`1") continue;
                    
                    if (cand.Parameters[1].Type.GetMetadataName() != "TaskContinuationOptions") continue;

                    return cand;
                }

                // For generic version we're looking for ContinueWith(Func<Task, T>, TaskContinuationOptions)
                if (!cand.IsGeneric) continue;

                if (cand.TemplateParameters.Count != 1) continue;

                if (cand.ParameterCount != expectedNumberOfArguments) continue;

                if (cand.Parameters[0].Type.GetMetadataName() != "Func`2") continue;
                if (cand.Parameters[1].Type.GetMetadataName() != "TaskContinuationOptions") continue;

                // now create instance, first of task
                var taskInstance = taskTemplate.GetTemplateInstance(
                    closureClass.DeclaringModule,
                    taskType.TemplateArguments[0]);

                // ST: some black magic is happening, but it seems it is required to get ContinueWith
                // from generic instantiated version of the task
                var candMethod = (Method)taskInstance.GetMembersNamed(Identifier.For("ContinueWith"))[i];

                // Candidate method would have following signature:
                // Task<T> ContinueWith(Task<T> t) for generic version
                return candMethod.GetTemplateInstance(null, taskType);
            }

            return null;
        }
Beispiel #3
0
    public RuntimeContractMethods(TypeNode userContractType, ContractNodes contractNodes, AssemblyNode targetAssembly,
                                  bool throwOnFailure, int rewriteLevel, bool publicSurfaceOnly, bool callSiteRequires,
                                  int recursionGuard, bool hideFromDebugger,
                                  bool userExplicitValidation
                                 )
    {
      this.contractNodes = contractNodes;
      this.targetAssembly = targetAssembly;
      this.ThrowOnFailure = throwOnFailure;
      this.RewriteLevel = rewriteLevel;
      this.PublicSurfaceOnly = publicSurfaceOnly;
      this.CallSiteRequires = callSiteRequires;
      this.regularRecursionGuard = recursionGuard;
      this.HideFromDebugger = hideFromDebugger;
      this.UseExplicitValidation = userExplicitValidation;

      // extract methods from user methods
      #region Get the user-specified rewriter methods (optional) REVIEW!! Needs a lot of error handling
      if (userContractType != null)
      {
        Method method = null;
        MethodList reqMethods = userContractType.GetMethods(Identifier.For("Requires"), SystemTypes.Boolean, SystemTypes.String, SystemTypes.String);
        for (int i = 0; i < reqMethods.Count; i++)
        {
          method = reqMethods[i];
          if (method != null)
          {
            if (method.TemplateParameters == null || method.TemplateParameters.Count != 1)
            {
              /*if (method != null) */ this.requiresMethod = method;
            }
            else
            {
              this.requiresWithExceptionMethod = method;
            }
          }
        }
        method = userContractType.GetMethod(Identifier.For("Ensures"), SystemTypes.Boolean, SystemTypes.String, SystemTypes.String);
        if (method != null) this.ensuresMethod = method;
        method = userContractType.GetMethod(Identifier.For("EnsuresOnThrow"), SystemTypes.Boolean, SystemTypes.String, SystemTypes.String, SystemTypes.Exception);
        if (method != null) this.ensuresOnThrowMethod = method;
        method = userContractType.GetMethod(Identifier.For("Invariant"), SystemTypes.Boolean, SystemTypes.String, SystemTypes.String);
        if (method != null) this.invariantMethod = method;
        method = userContractType.GetMethod(Identifier.For("Assert"), SystemTypes.Boolean, SystemTypes.String, SystemTypes.String);
        if (method != null) this.assertMethod = method;
        method = userContractType.GetMethod(Identifier.For("Assume"), SystemTypes.Boolean, SystemTypes.String, SystemTypes.String);
        if (method != null) this.assumeMethod = method;

        // Need to make sure that the type ContractFailureKind is the one used in the user-supplied methods, which is not necessarily
        // the one that is defined in the assembly that defines the contract class. For instance, extracting/rewriting from a 4.0 assembly
        // but where the user-supplied assembly is pre-4.0.
        var mems = userContractType.GetMembersNamed(ContractNodes.ReportFailureName);
        TypeNode contractFailureKind = contractNodes.ContractFailureKind;
        //if (mems != null) 
        {
          foreach(var mem in mems){
            method = mem as Method;
            if (method == null) continue;
            if (method.Parameters.Count != 4) continue;
            if (method.Parameters[0].Type.Name != contractNodes.ContractFailureKind.Name) continue;
            if (method.Parameters[1].Type != SystemTypes.String) continue;
            if (method.Parameters[2].Type != SystemTypes.String) continue;
            if (method.Parameters[3].Type != SystemTypes.Exception) continue;
            this.failureMethod = method;
            contractFailureKind = method.Parameters[0].Type;
            break;
          }
        }

        if (this.failureMethod == null) 
        {
          mems = userContractType.GetMembersNamed(ContractNodes.RaiseContractFailedEventName);
          // if (mems != null) 
          {
            foreach (var mem in mems) {
              method = mem as Method;
              if (method == null) continue;
              if (method.Parameters.Count != 4) continue;
              if (method.Parameters[0].Type.Name.UniqueIdKey != contractNodes.ContractFailureKind.Name.UniqueIdKey) continue;
              if (method.Parameters[1].Type != SystemTypes.String) continue;
              if (method.Parameters[2].Type != SystemTypes.String) continue;
              if (method.Parameters[3].Type != SystemTypes.Exception) continue;
              this.raiseFailureEventMethod = method;
              contractFailureKind = method.Parameters[0].Type;
              break;
            }
          }
        } else {
          method = userContractType.GetMethod(ContractNodes.RaiseContractFailedEventName, contractFailureKind, SystemTypes.String, SystemTypes.String, SystemTypes.Exception);
          if (method != null) this.raiseFailureEventMethod = method;
        }
        if (this.raiseFailureEventMethod != null) { // either take all both RaiseContractFailedEvent and TriggerFailure or neither
          method = userContractType.GetMethod(ContractNodes.TriggerFailureName, contractFailureKind, SystemTypes.String, SystemTypes.String, SystemTypes.String, SystemTypes.Exception);
          if (method != null) this.triggerFailureMethod = method;
        }

      }
      #endregion Get the user-specified rewriter methods (optional) REVIEW!! Needs a lot of error handling

    }
        private static Member FuzzilyGetMatchingMember(TypeNode t, Member m)
        {
            Contract.Requires(t != null);
            Contract.Requires(m != null);

            var candidates = t.GetMembersNamed(m.Name);
            Contract.Assert(candidates != null, "Clousot can prove it");
            for (int i = 0, n = candidates.Count; i < n; i++)
            {
                Member mem = candidates[i];
                if (mem == null) continue;

                if (!mem.Name.Matches(m.Name)) continue;

                // type case statement would be *so* nice right now
                // Can't test the NodeType because for mscorlib.Contracts, structs are read in as classes
                // because they don't extend the "real" System.ValueType, but the one declared in mscorlib.Contracts.
                //if (mem.NodeType != m.NodeType) continue;
                Method x = mem as Method; // handles regular Methods and InstanceInitializers
                if (x != null)
                {
                    Method m_prime = m as Method;
                    if (m_prime == null) continue;

                    if ((x.TemplateParameters == null) != (m_prime.TemplateParameters == null)) continue;

                    if (FuzzyEqual(m_prime.Parameters, x.Parameters)
                        && FuzzyEqual(m_prime.ReturnType, x.ReturnType)
                        && TemplateParameterCount(x) == TemplateParameterCount(m_prime))
                    {
                        return mem;
                    }

                    continue;
                }

                Field memAsField = mem as Field;
                if (memAsField != null)
                {
                    Field mAsField = m as Field;
                    if (mAsField == null) continue;

                    if (FuzzyEqual(mAsField.Type, memAsField.Type)) return mem;
                    
                    continue;
                }

                Event memAsEvent = mem as Event;
                if (memAsEvent != null)
                {
                    Event mAsEvent = m as Event;
                    if (mAsEvent == null) continue;
                    
                    if (FuzzyEqual(mAsEvent.HandlerType, memAsEvent.HandlerType)) return mem;
                    
                    continue;
                }

                Property memAsProperty = mem as Property;
                if (memAsProperty != null)
                {
                    Property mAsProperty = m as Property;
                    if (mAsProperty == null) continue;

                    if (FuzzyEqual(mAsProperty.Type, memAsProperty.Type)) return mem;

                    continue;
                }

                TypeNode memAsTypeNode = mem as TypeNode; // handles Class, Interface, etc.
                if (memAsTypeNode != null)
                {
                    TypeNode mAsTypeNode = m as TypeNode;
                    if (mAsTypeNode == null) continue;

                    if (FuzzyEqual(mAsTypeNode, memAsTypeNode)) return mem;

                    continue;
                }

                Contract.Assume(false, "Pseudo-typecase failed to find a match");
            }

            return null;
        }