public CollectOldExpressions(Module module, Method method, ContractNodes contractNodes, Dictionary<TypeNode, Local> closureLocals, 
     int localCounterStart, Class initialClosureClass)
     : this(module, method, contractNodes, closureLocals, localCounterStart)
 {
     this.topLevelClosureClass = initialClosureClass;
     this.currentClosureClass = initialClosureClass;
 }
        public ScrubContractClass(ExtractorVisitor parent, Class contractClass, TypeNode originalType)
        {
            Contract.Requires(TypeNode.IsCompleteTemplate(contractClass));
            Contract.Requires(TypeNode.IsCompleteTemplate(originalType));

            this.parent = parent;
            this.contractClass = contractClass;
            this.abstractClass = originalType;
        }
Exemple #3
0
 private ClassParameter ConvertToClassParameter(TypeNode typeParameter, InterfaceList interfaces, Class baseClass, ClassExpression cExpr){
   ClassParameter cParam = typeParameter is MethodTypeParameter ? new MethodClassParameter() : new ClassParameter();
   this.typeParamToClassParamMap[typeParameter.UniqueKey] = cParam;
   cParam.SourceContext = typeParameter.SourceContext;
   cParam.TypeParameterFlags = ((ITypeParameter)typeParameter).TypeParameterFlags;
   if (typeParameter.IsUnmanaged) { cParam.SetIsUnmanaged(); }
   cParam.Name = typeParameter.Name;
   cParam.Namespace = StandardIds.ClassParameter;
   cParam.BaseClass = baseClass == null ? SystemTypes.Object : baseClass;
   cParam.BaseClassExpression = cExpr;
   cParam.DeclaringMember = ((ITypeParameter)typeParameter).DeclaringMember;
   cParam.DeclaringModule = typeParameter.DeclaringModule;
   cParam.DeclaringType = typeParameter is MethodTypeParameter ? null : typeParameter.DeclaringType;
   cParam.Flags = typeParameter.Flags & ~TypeFlags.Interface;
   cParam.ParameterListIndex = ((ITypeParameter)typeParameter).ParameterListIndex;
   MemberList mems = cParam.DeclaringType == null ? null : cParam.DeclaringType.Members;
   int n = mems == null ? 0 : mems.Count;
   for (int i = 0; i < n; i++){
     if ((mems[i] as TypeNode) == typeParameter){
       mems[i] = cParam;
       break;
     }
   }
   if (cExpr != null){
     n = interfaces.Count - 1;
     InterfaceList actualInterfaces = new InterfaceList(n);
     for (int i = 0; i < n; i++)
       actualInterfaces.Add(interfaces[i + 1]);
     cParam.Interfaces = actualInterfaces;
   }else
     cParam.Interfaces = interfaces;
   if (cExpr != null) cParam.BaseClass = this.VisitClassExpression(cExpr);
   return cParam;
 }
Exemple #4
0
        private static void ClearStatics()
        {
            AttributeUsageAttribute = null;
            ConditionalAttribute = null;
            DefaultMemberAttribute = null;
            InternalsVisibleToAttribute = null;
            ObsoleteAttribute = null;

            GenericICollection = null;
            GenericIEnumerable = null;
            GenericIList = null;
            ICloneable = null;
            ICollection = null;
            IEnumerable = null;
            IList = null;

            //Special attributes    
            AllowPartiallyTrustedCallersAttribute = null;
            AssemblyCompanyAttribute = null;
            AssemblyConfigurationAttribute = null;
            AssemblyCopyrightAttribute = null;
            AssemblyCultureAttribute = null;
            AssemblyDelaySignAttribute = null;
            AssemblyDescriptionAttribute = null;
            AssemblyFileVersionAttribute = null;
            AssemblyFlagsAttribute = null;
            AssemblyInformationalVersionAttribute = null;
            AssemblyKeyFileAttribute = null;
            AssemblyKeyNameAttribute = null;
            AssemblyProductAttribute = null;
            AssemblyTitleAttribute = null;
            AssemblyTrademarkAttribute = null;
            AssemblyVersionAttribute = null;
            ClassInterfaceAttribute = null;
            CLSCompliantAttribute = null;
            ComImportAttribute = null;
            ComRegisterFunctionAttribute = null;
            ComSourceInterfacesAttribute = null;
            ComUnregisterFunctionAttribute = null;
            ComVisibleAttribute = null;
            DebuggableAttribute = null;
            DebuggerHiddenAttribute = null;
            DebuggerStepThroughAttribute = null;
            DebuggingModes = null;
            DllImportAttribute = null;
            FieldOffsetAttribute = null;
            FlagsAttribute = null;
            GuidAttribute = null;
            ImportedFromTypeLibAttribute = null;
            InAttribute = null;
            IndexerNameAttribute = null;
            InterfaceTypeAttribute = null;
            MethodImplAttribute = null;
            NonSerializedAttribute = null;
            OptionalAttribute = null;
            OutAttribute = null;
            ParamArrayAttribute = null;
            RuntimeCompatibilityAttribute = null;
            SatelliteContractVersionAttribute = null;
            SerializableAttribute = null;
            SecurityAttribute = null;
            SecurityCriticalAttribute = null;
            SecurityTransparentAttribute = null;
            SecurityTreatAsSafeAttribute = null;
            STAThreadAttribute = null;
            StructLayoutAttribute = null;
            SuppressMessageAttribute = null;
            SuppressUnmanagedCodeSecurityAttribute = null;
            SecurityAction = null;

            //Classes need for System.TypeCode
            DBNull = null;
            DateTime = null;
            TimeSpan = null;

            //Classes and interfaces used by the Framework
            Activator = null;
            AppDomain = null;
            ApplicationException = null;
            ArgumentException = null;
            ArgumentNullException = null;
            ArgumentOutOfRangeException = null;
            ArrayList = null;
            AsyncCallback = null;
            Assembly = null;
            CodeAccessPermission = null;
            CollectionBase = null;
            CultureInfo = null;
            DictionaryBase = null;
            DictionaryEntry = null;
            DuplicateWaitObjectException = null;
            Environment = null;
            EventArgs = null;
            ExecutionEngineException = null;
            GenericArraySegment = null;
            GenericArrayToIEnumerableAdapter = null;
            GenericDictionary = null;
            GenericIComparable = null;
            GenericIComparer = null;
            GenericIDictionary = null;
            GenericIEnumerator = null;
            GenericKeyValuePair = null;
            GenericList = null;
            GenericNullable = null;
            GenericQueue = null;
            GenericSortedDictionary = null;
            GenericStack = null;
            GC = null;
            Guid = null;
            __HandleProtector = null;
            HandleRef = null;
            Hashtable = null;
            IASyncResult = null;
            IComparable = null;
            IDictionary = null;
            IComparer = null;
            IDisposable = null;
            IEnumerator = null;
            IFormatProvider = null;
            IHashCodeProvider = null;
            IMembershipCondition = null;
            IndexOutOfRangeException = null;
            InvalidCastException = null;
            InvalidOperationException = null;
            IPermission = null;
            ISerializable = null;
            IStackWalk = null;
            Marshal = null;
            MarshalByRefObject = null;
            MemberInfo = null;
            NativeOverlapped = null;
            Monitor = null;
            NotSupportedException = null;
            NullReferenceException = null;
            OutOfMemoryException = null;
            ParameterInfo = null;
            Queue = null;
            ReadOnlyCollectionBase = null;
            ResourceManager = null;
            ResourceSet = null;
            SerializationInfo = null;
            Stack = null;
            StackOverflowException = null;
            Stream = null;
            StreamingContext = null;
            StringBuilder = null;
            StringComparer = null;
            StringComparison = null;
            SystemException = null;
            Thread = null;
            WindowsImpersonationContext = null;
        }
Exemple #5
0
 public override Class VisitClass(Class Class) {
   PrepareGuardedClass(Class);
   return base.VisitClass(Class);
 }
        private void CheckForWrapperImplementationsForInheritedInterfaceImplementations(Class Class)
        {
            Contract.Requires(Class != null);

            if (Class.Interfaces == null) return;

            if (this.runtimeCheckingLevel == 0) return;

            if (!HelperMethods.ContractOption(Class, "runtime", "checking") ||
                !HelperMethods.ContractOption(Class, "contract", "inheritance"))
            {
                return;
            }

            for (int i = 0; i < Class.Interfaces.Count; i++)
            {
                var intf = Class.Interfaces[i];
                if (intf == null) continue;

                CheckForWrapperImplementationsForInheritedInterfaceImplementations(Class, intf);
            }
        }
        public override Class VisitClass(Class Class)
        {
            Class = base.VisitClass(Class);
                
            Class.Template = null;

            return Class;
        }
Exemple #8
0
    void AddReadContent(Class serializer, Block block, TypeNode type, StatementList statements, Identifier reader, 
      Expression target, Expression required, Expression result, SchemaValidator validator) {
    
      // position us in the content.
      statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToContent")), new ExpressionList())));
      Local elementName = new Local(Identifier.Empty,SystemTypes.String);
      statements.Add(new AssignmentStatement(elementName, new QualifiedIdentifier(reader, Identifier.For("LocalName"))));
      
      // make sure the element is not empty.
      If isEmpty = AddEmptyElementCheck(statements, reader);

      // Read the contents.
      statements = isEmpty.FalseBlock.Statements;
      statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Read")), new ExpressionList())));
      statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToContent")), new ExpressionList())));

      ValidationState context = new ValidationState();
      context.ErrorHandler = this.errorHandler;
      validator.validator.InitValidation(context);
      ArrayList members = null;
      if (validator.validator is AllElementsContentValidator) {
        members = validator.validator.ExpectedElements(context, false, false);
        AddReadAllGroup(serializer, block, type, statements, reader, target, required, result, members, validator.validator.MixedMember);
      } else {

        // There should be one root level anonymous Item0 member.
        SequenceNode seq = (SequenceNode)validator.RootNode; // this is a wrapper node.
        if (seq == null) {
          // perhaps it is ContentType.Empty or Mixed.
          if (validator.validator.ContentType == XmlSchemaContentType.Mixed ||
            validator.validator.ContentType == XmlSchemaContentType.TextOnly){
            Debug.Assert(validator.validator.MixedMember != null);
            statements.Add(new AssignmentStatement(GetMemberBinding(target, validator.validator.MixedMember), 
              new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadStringElement")), new ExpressionList())));         
          }
          return;
        } else {
          ContentNode n = seq.LeftChild;
          AddReadContentNode(n, block, statements, reader, target, required, result, validator);
        }
      }    

      // consume final end tag
      statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadEndTag")), new ExpressionList(elementName))));
    }
Exemple #9
0
        public override Class VisitClass(Class Class)
        {
            WriteStart("class {0}", Class.Name.Name);

            if (this.braceOnNewLine)
            {
                WriteFinish(string.Empty);
                WriteLine("{");
            }
            else
                WriteFinish(" {");

            In();
            Class.Members = this.VisitMemberList(Class.Members);
            Out();
            WriteLine("};");

            return Class;
        }
Exemple #10
0
 private Block ProcessOldExpressionsInAsync(Method method, EnsuresList asyncpostconditions, Dictionary<TypeNode, Local> closureLocals, ref int oldLocalNameCounter, Class asyncClosure)
 {
     Contract.Requires(asyncpostconditions != null);
     CollectOldExpressions coe = new CollectOldExpressions(
       this.module,
       method,
       this.rewriterNodes,
       closureLocals,
       oldLocalNameCounter,
       asyncClosure
       );
     foreach (Ensures e in asyncpostconditions)
     {
         if (!EmitEnsures(e, method.DeclaringType, this.skipQuantifiers)) continue;
         coe.Visit(e);
     }
     oldLocalNameCounter = coe.Counter;
     var oldAssignments = coe.PrestateValuesOfOldExpressions;
     // don't wrap in a try catch if the method is a constructor (peverify issue)
     if (!(method is InstanceInitializer))
     {
         WrapOldAssignmentsInTryCatch(method, oldAssignments);
     }
     return oldAssignments;
 }
Exemple #11
0
    /// <summary>
    /// Tries to reuse or create the attribute
    /// </summary>
    private static InstanceInitializer GetRuntimeContractsAttributeCtor(AssemblyNode assembly)
    {
      EnumNode runtimeContractsFlags = assembly.GetType(ContractNodes.ContractNamespace, Identifier.For("RuntimeContractsFlags")) as EnumNode;
      Class RuntimeContractsAttributeClass = assembly.GetType(ContractNodes.ContractNamespace, Identifier.For("RuntimeContractsAttribute")) as Class;

      if (runtimeContractsFlags == null)
      {
        #region Add [Flags]
        Member flagsConstructor = RewriteHelper.flagsAttributeNode.GetConstructor();
        AttributeNode flagsAttribute = new AttributeNode(new MemberBinding(null, flagsConstructor), null, AttributeTargets.Class);
        #endregion Add [Flags]
        runtimeContractsFlags = new EnumNode(assembly,
          null, /* declaringType */
          new AttributeList(2),
          TypeFlags.Sealed,
          ContractNodes.ContractNamespace,
          Identifier.For("RuntimeContractsFlags"),
          new InterfaceList(),
          new MemberList());
        runtimeContractsFlags.Attributes.Add(flagsAttribute);
        RewriteHelper.TryAddCompilerGeneratedAttribute(runtimeContractsFlags);
        runtimeContractsFlags.UnderlyingType = SystemTypes.Int32;

        Type copyFrom = typeof(RuntimeContractEmitFlags);
        foreach (System.Reflection.FieldInfo fi in copyFrom.GetFields())
        {
          if (fi.IsLiteral)
          {
            AddEnumValue(runtimeContractsFlags, fi.Name, fi.GetRawConstantValue());
          }
        }
        assembly.Types.Add(runtimeContractsFlags);

      }


      InstanceInitializer ctor = (RuntimeContractsAttributeClass == null) ? null : RuntimeContractsAttributeClass.GetConstructor(runtimeContractsFlags);

      if (RuntimeContractsAttributeClass == null)
      {
        RuntimeContractsAttributeClass = new Class(assembly,
          null, /* declaringType */
          new AttributeList(),
          TypeFlags.Sealed,
          ContractNodes.ContractNamespace,
          Identifier.For("RuntimeContractsAttribute"),
          SystemTypes.Attribute,
          new InterfaceList(),
          new MemberList(0));

        RewriteHelper.TryAddCompilerGeneratedAttribute(RuntimeContractsAttributeClass);
        assembly.Types.Add(RuntimeContractsAttributeClass);
      }
      if (ctor == null) {

        Block returnBlock = new Block(new StatementList(new Return()));

        Block body = new Block(new StatementList());
        Block b = new Block(new StatementList());
        ParameterList pl = new ParameterList();
        Parameter levelParameter = new Parameter(Identifier.For("contractFlags"), runtimeContractsFlags);
        pl.Add(levelParameter);

        ctor = new InstanceInitializer(RuntimeContractsAttributeClass, null, pl, body);
        ctor.Flags = MethodFlags.Assembly | MethodFlags.HideBySig | MethodFlags.SpecialName | MethodFlags.RTSpecialName;

        Method baseCtor = SystemTypes.Attribute.GetConstructor();

        b.Statements.Add(new ExpressionStatement(new MethodCall(new MemberBinding(null, baseCtor), new ExpressionList(ctor.ThisParameter))));
        b.Statements.Add(returnBlock);
        body.Statements.Add(b);

        RuntimeContractsAttributeClass.Members.Add(ctor);
      }

      return ctor;
    }
Exemple #12
0
    private Method FindAndInstantiateBaseClassInvariantMethod(Class asClass, out Field baseReentrancyFlag)
    {
      baseReentrancyFlag = null;
      if (asClass == null || asClass.BaseClass == null) return null;
      if (!this.Emit(RuntimeContractEmitFlags.InheritContracts)) return null; // don't call base class invariant if we don't inherit

      var baseClass = asClass.BaseClass;

      if (!this.InheritInvariantsAcrossAssemblies && (baseClass.DeclaringModule != asClass.DeclaringModule))
        return null;

      var result = baseClass.GetMethod(Identifier.For("$InvariantMethod$"), null);

      if (result != null && !HelperMethods.IsVisibleFrom(result, asClass)) return null;

      if (result == null && baseClass.Template != null)
      {
        // instantiation of generated method has not happened.
        var generic = baseClass.Template.GetMethod(Identifier.For("$InvariantMethod$"), null);
        if (generic != null)
        {
          if (!HelperMethods.IsVisibleFrom(generic, asClass)) return null;
          // generate proper reference.
          result = GetMethodInstanceReference(generic, baseClass);
        }
      }
      // extract base reentrancy flag
      if (result != null) {
        var instantiatedParent = result.DeclaringType;
        baseReentrancyFlag = instantiatedParent.GetField(Identifier.For("$evaluatingInvariant$"));

        if (baseReentrancyFlag == null && baseClass.Template != null)
        {
          // instantiation of generated baseReentrancy flag has not happened.
          var generic = baseClass.Template.GetField(Identifier.For("$evaluatingInvariant$"));
          if (generic != null)
          {
            if (HelperMethods.IsVisibleFrom(generic, asClass))
            {
              baseReentrancyFlag = GetFieldInstanceReference(generic, baseClass);
            }
          }
        }
      }

      return result;
    }
Exemple #13
0
        /// <summary>
        /// There are 2 cases:
        /// 1) Task has no return value. In this case, we emit
        ///      void CheckMethod(Task t) {
        ///         var ae = t.Exception as AggregateException;
        ///         if (ae != null) { ae.Handle(this.CheckException); throw ae; }
        ///      }
        ///      bool CheckException(Exception e) {
        ///          .. check exceptional post
        ///      }
        /// 2) Task(T) returns a T value
        ///      T CheckMethod(Task t) {
        ///         try {
        ///            var r = t.Result;
        ///            .. check ensures on r ..
        ///            return r;
        ///         }
        ///         catch (AggregateException ae) {
        ///            ae.Handle(this.CheckException); 
        ///            throw;
        ///         }
        ///      }
        ///      bool CheckException(Exception e) {
        ///          .. check exceptional post
        ///      }
        /// </summary>
        public EmitAsyncClosure(Method from, Rewriter parent)
        {
            this.fromMethod = from;
            this.parent = parent;
            this.checkMethodId = Identifier.For("CheckPost");
            this.checkExceptionMethodId = Identifier.For("CheckException");
            this.declaringType = from.DeclaringType;
            var closureName = HelperMethods.NextUnusedMemberName(declaringType, "<" + from.Name.Name + ">AsyncContractClosure");
            this.closureClass = new Class(declaringType.DeclaringModule, declaringType, null, TypeFlags.NestedPrivate, null, Identifier.For(closureName), SystemTypes.Object, null, null);
            declaringType.Members.Add(this.closureClass);
            RewriteHelper.TryAddCompilerGeneratedAttribute(this.closureClass);

            this.dup = new Duplicator(this.declaringType.DeclaringModule, this.declaringType);

            var taskType = from.ReturnType;
            var taskArgs = taskType.TemplateArguments == null ? 0 : taskType.TemplateArguments.Count;

            this.AggregateExceptionType = new Cache<TypeNode>(() =>
                HelperMethods.FindType(parent.assemblyBeingRewritten, StandardIds.System, Identifier.For("AggregateException")));
            this.Func2Type = new Cache<TypeNode>(() =>
                HelperMethods.FindType(SystemTypes.SystemAssembly, StandardIds.System, Identifier.For("Func`2")));

            if (from.IsGeneric)
            {
                this.closureClass.TemplateParameters = new TypeNodeList();
                var parentCount = this.declaringType.ConsolidatedTemplateParameters == null ? 0 : this.declaringType.ConsolidatedTemplateParameters.Count;
                for (int i = 0; i < from.TemplateParameters.Count; i++)
                {
                    var tp = HelperMethods.NewEqualTypeParameter(dup, (ITypeParameter)from.TemplateParameters[i], this.closureClass, parentCount + i);

                    this.closureClass.TemplateParameters.Add(tp);
                }
                this.closureClass.IsGeneric = true;
                this.closureClass.EnsureMangledName();
                this.forwarder = new Specializer(this.declaringType.DeclaringModule, from.TemplateParameters, this.closureClass.TemplateParameters);
                this.forwarder.VisitTypeParameterList(this.closureClass.TemplateParameters);

                taskType = this.forwarder.VisitTypeReference(taskType);
            }
            else
            {
                this.closureClassInstance = this.closureClass;
            }

            var taskTemplate = HelperMethods.Unspecialize(taskType);
            var continueWithCandidates = taskTemplate.GetMembersNamed(Identifier.For("ContinueWith"));
            Method continueWithMethod = null;
            for (int i = 0; i < continueWithCandidates.Count; i++)
            {
                var cand = continueWithCandidates[i] as Method;
                if (cand == null) continue;
                if (taskArgs == 0)
                {
                    if (cand.IsGeneric) continue;
                    if (cand.ParameterCount != 1) continue;

                    var p = cand.Parameters[0];
                    var ptype = p.Type;
                    var ptypeTemplate = ptype;

                    while (ptypeTemplate.Template != null)
                    {
                        ptypeTemplate = ptypeTemplate.Template;
                    }

                    if (ptypeTemplate.Name.Name != "Action`1") continue;

                    continueWithMethod = cand;
                    break;
                }
                else
                {
                    if (!cand.IsGeneric) continue;
                    if (cand.TemplateParameters.Count != 1) continue;
                    if (cand.ParameterCount != 1) continue;
                    var p = cand.Parameters[0];
                    var ptype = p.Type;
                    var ptypeTemplate = ptype;
                    while (ptypeTemplate.Template != null)
                    {
                        ptypeTemplate = ptypeTemplate.Template;
                    }
                    if (ptypeTemplate.Name.Name != "Func`2") continue;

                    // now create instance, first of task
                    var taskInstance = taskTemplate.GetTemplateInstance(this.closureClass.DeclaringModule, taskType.TemplateArguments[0]);
                    var candMethod = taskInstance.GetMembersNamed(Identifier.For("ContinueWith"))[i] as Method;
                    continueWithMethod = candMethod.GetTemplateInstance(null, taskType.TemplateArguments[0]);
                    break;
                }
            }

            if (continueWithMethod != null)
            {
                this.continuewithMethod = continueWithMethod;
                EmitCheckMethod(taskType, taskArgs == 1);

                var ctor = new InstanceInitializer(this.closureClass, null, null, null);
                this.constructor = ctor;
                ctor.CallingConvention = CallingConventionFlags.HasThis;
                ctor.Flags |= MethodFlags.Public | MethodFlags.HideBySig;
                ctor.Body = new Block(new StatementList(
                    new ExpressionStatement(new MethodCall(new MemberBinding(ctor.ThisParameter, SystemTypes.Object.GetConstructor()), new ExpressionList())),
                    new Return()
                    ));
                this.closureClass.Members.Add(ctor);

            }

            // now that we added the ctor and the check method, let's instantiate the closure class if necessary
            if (this.closureClassInstance == null)
            {
                var consArgs = new TypeNodeList();
                var args = new TypeNodeList();
                var parentCount = this.closureClass.DeclaringType.ConsolidatedTemplateParameters == null ? 0 : this.closureClass.DeclaringType.ConsolidatedTemplateParameters.Count;
                
                for (int i = 0; i < parentCount; i++)
                {
                    consArgs.Add(this.closureClass.DeclaringType.ConsolidatedTemplateParameters[i]);
                }
                
                var methodCount = from.TemplateParameters == null ? 0: from.TemplateParameters.Count;
                for (int i = 0; i < methodCount; i++)
                {
                    consArgs.Add(from.TemplateParameters[i]);
                    args.Add(from.TemplateParameters[i]);
                }

                this.closureClassInstance = (Class)this.closureClass.GetConsolidatedTemplateInstance(this.parent.assemblyBeingRewritten, closureClass.DeclaringType, closureClass.DeclaringType, args, consArgs);
            }

            // create closure initializer for context method
            this.ClosureLocal = new Local(this.ClosureClass);
            this.ClosureInitializer = new Block(new StatementList());

            this.ClosureInitializer.Statements.Add(new AssignmentStatement(this.ClosureLocal, new Construct(new MemberBinding(null, this.Ctor), new ExpressionList())));
        }
Exemple #14
0
    private void VisitBaseClass(Class Class)
    {
      // F:
      Contract.Requires(Class != null);

      // make sure the possibly generic base class is rewritten before this class
      var baseClass = Class.BaseClass;
      if (baseClass == null) return;

      while (baseClass.Template is Class)
      {
        baseClass = (Class)baseClass.Template;
      }

      // make sure base class is in same assembly
      if (Class.DeclaringModule != baseClass.DeclaringModule) return;

      VisitClass(baseClass);
    }
Exemple #15
0
    public override void VisitClass(Class Class)
    {
      if (Class == null) return;
      if (visitedClasses[Class.UniqueKey] != null) return;
      visitedClasses[Class.UniqueKey] = Class;

      VisitBaseClass(Class);

      base.VisitClass(Class);
    }
Exemple #16
0
    private Class MakeContractException() {
      Class contractExceptionType;

      #region If we're rewriting an assembly for v4 or above and it *isn't* Silverlight (so serialization support is needed), then use new embedded dll as the type
      if (4 <= TargetPlatform.MajorVersion) {
        var iSafeSerializationData = SystemTypes.SystemAssembly.GetType(Identifier.For("System.Runtime.Serialization"), Identifier.For("ISafeSerializationData")) as Interface;
        if (iSafeSerializationData != null) {
          // Just much easier to write the C# and have the compiler generate everything than to try and create it all manually
          System.Reflection.Assembly embeddedAssembly;
          Stream embeddedAssemblyStream;
          embeddedAssembly = System.Reflection.Assembly.GetExecutingAssembly();
          embeddedAssemblyStream = embeddedAssembly.GetManifestResourceStream("Microsoft.Contracts.Foxtrot.InternalException.dll");
          byte[] data = new byte[0];
          using (var br = new BinaryReader(embeddedAssemblyStream)) {
            var len = embeddedAssemblyStream.Length;
            if (len < Int32.MaxValue)
              data = br.ReadBytes((int)len);
            AssemblyNode assemblyNode = AssemblyNode.GetAssembly(data, TargetPlatform.StaticAssemblyCache, true, false, true);
            contractExceptionType = assemblyNode.GetType(Identifier.For(""), Identifier.For("ContractException")) as Class;
          }
          if (contractExceptionType == null)
            throw new RewriteException("Tried to create the ContractException type from the embedded dll, but failed");
          var d = new Duplicator(this.targetAssembly, this.RuntimeContractType);
          d.FindTypesToBeDuplicated(new TypeNodeList(contractExceptionType));

          var ct = d.Visit(contractExceptionType);
          contractExceptionType = (Class)ct;
          contractExceptionType.Flags |= TypeFlags.NestedPrivate;
          this.RuntimeContractType.Members.Add(contractExceptionType);
          return contractExceptionType;
        }
      }
      #endregion

      contractExceptionType = new Class(this.targetAssembly, this.RuntimeContractType, new AttributeList(), TypeFlags.Class | TypeFlags.NestedPrivate | TypeFlags.Serializable, null, Identifier.For("ContractException"), SystemTypes.Exception, null, null);

      RewriteHelper.TryAddCompilerGeneratedAttribute(contractExceptionType);

      var kindField = new Field(contractExceptionType, null, FieldFlags.Private, Identifier.For("_Kind"), contractNodes.ContractFailureKind, null);
      var userField = new Field(contractExceptionType, null, FieldFlags.Private, Identifier.For("_UserMessage"), SystemTypes.String, null);
      var condField = new Field(contractExceptionType, null, FieldFlags.Private, Identifier.For("_Condition"), SystemTypes.String, null);
      contractExceptionType.Members.Add(kindField);
      contractExceptionType.Members.Add(userField);
      contractExceptionType.Members.Add(condField);

      #region Constructor for setting the fields
      var parameters = new ParameterList();
      var kindParam = new Parameter(Identifier.For("kind"), this.contractNodes.ContractFailureKind);
      var failureParam = new Parameter(Identifier.For("failure"), SystemTypes.String);
      var usermsgParam = new Parameter(Identifier.For("usermsg"), SystemTypes.String);
      var conditionParam = new Parameter(Identifier.For("condition"), SystemTypes.String);
      var innerParam = new Parameter(Identifier.For("inner"), SystemTypes.Exception);
      parameters.Add(kindParam);
      parameters.Add(failureParam);
      parameters.Add(usermsgParam);
      parameters.Add(conditionParam);
      parameters.Add(innerParam);
      var body = new Block(new StatementList());
      var ctor = new InstanceInitializer(contractExceptionType, null, parameters, body);
      ctor.Flags |= MethodFlags.Public | MethodFlags.HideBySig;
      ctor.CallingConvention = CallingConventionFlags.HasThis;
      body.Statements.Add(new ExpressionStatement(new MethodCall(new MemberBinding(ctor.ThisParameter, contractExceptionType.BaseClass.GetConstructor(SystemTypes.String, SystemTypes.Exception)), new ExpressionList(failureParam, innerParam))));
      body.Statements.Add(new AssignmentStatement(new MemberBinding(ctor.ThisParameter, kindField), kindParam));
      body.Statements.Add(new AssignmentStatement(new MemberBinding(ctor.ThisParameter, userField), usermsgParam));
      body.Statements.Add(new AssignmentStatement(new MemberBinding(ctor.ThisParameter, condField), conditionParam));
      body.Statements.Add(new Return());
      contractExceptionType.Members.Add(ctor);
      #endregion

      if (SystemTypes.SerializationInfo != null && SystemTypes.SerializationInfo.BaseClass != null) {
        // Silverlight (e.g.) is a platform that doesn't support serialization. So check to make sure the type really exists.
        // 
        var baseCtor = SystemTypes.Exception.GetConstructor(SystemTypes.SerializationInfo, SystemTypes.StreamingContext);

        if (baseCtor != null) {
          #region Deserialization Constructor
          parameters = new ParameterList();
          var info = new Parameter(Identifier.For("info"), SystemTypes.SerializationInfo);
          var context = new Parameter(Identifier.For("context"), SystemTypes.StreamingContext);
          parameters.Add(info);
          parameters.Add(context);
          body = new Block(new StatementList());
          ctor = new InstanceInitializer(contractExceptionType, null, parameters, body);
          ctor.Flags |= MethodFlags.Private | MethodFlags.HideBySig;
          ctor.CallingConvention = CallingConventionFlags.HasThis;
          // : base(info, context) 
          body.Statements.Add(new ExpressionStatement(new MethodCall(new MemberBinding(ctor.ThisParameter, baseCtor), new ExpressionList(info, context))));
          // _Kind = (ContractFailureKind)info.GetInt32("Kind");
          var getInt32 = SystemTypes.SerializationInfo.GetMethod(Identifier.For("GetInt32"), SystemTypes.String);
          body.Statements.Add(new AssignmentStatement(
              new MemberBinding(new This(), kindField),
              new MethodCall(new MemberBinding(info, getInt32), new ExpressionList(new Literal("Kind", SystemTypes.String)))
              ));
          // _UserMessage = info.GetString("UserMessage");
          var getString = SystemTypes.SerializationInfo.GetMethod(Identifier.For("GetString"), SystemTypes.String);
          body.Statements.Add(new AssignmentStatement(
              new MemberBinding(new This(), userField),
              new MethodCall(new MemberBinding(info, getString), new ExpressionList(new Literal("UserMessage", SystemTypes.String)))
              ));
          // _Condition = info.GetString("Condition");
          body.Statements.Add(new AssignmentStatement(
              new MemberBinding(new This(), condField),
              new MethodCall(new MemberBinding(info, getString), new ExpressionList(new Literal("Condition", SystemTypes.String)))
              ));
          body.Statements.Add(new Return());
          contractExceptionType.Members.Add(ctor);
          #endregion

          #region GetObjectData

          var securityCriticalCtor = SystemTypes.SecurityCriticalAttribute.GetConstructor();
          var securityCriticalAttribute = new AttributeNode(new MemberBinding(null, securityCriticalCtor), null, System.AttributeTargets.Method);
          var attrs = new AttributeList(securityCriticalAttribute);
          parameters = new ParameterList();
          info = new Parameter(Identifier.For("info"), SystemTypes.SerializationInfo);
          context = new Parameter(Identifier.For("context"), SystemTypes.StreamingContext);
          parameters.Add(info);
          parameters.Add(context);
          body = new Block(new StatementList());
          var getObjectDataName = Identifier.For("GetObjectData");
          var getObjectData = new Method(contractExceptionType, attrs, getObjectDataName, parameters, SystemTypes.Void, body);
          getObjectData.CallingConvention = CallingConventionFlags.HasThis;
          // public override
          getObjectData.Flags = MethodFlags.Public | MethodFlags.Virtual;
          // base.GetObjectData(info, context);
          var baseGetObjectData = SystemTypes.Exception.GetMethod(getObjectDataName, SystemTypes.SerializationInfo, SystemTypes.StreamingContext);
          body.Statements.Add(new ExpressionStatement(
            new MethodCall(new MemberBinding(new This(), baseGetObjectData), new ExpressionList(info, context), NodeType.Call, SystemTypes.Void)
            ));
          // info.AddValue("Kind", _Kind);
          var addValueObject = SystemTypes.SerializationInfo.GetMethod(Identifier.For("AddValue"), SystemTypes.String, SystemTypes.Object);
          body.Statements.Add(new ExpressionStatement(
            new MethodCall(new MemberBinding(info, addValueObject), new ExpressionList(new Literal("Kind", SystemTypes.String), new BinaryExpression(new MemberBinding(new This(), kindField), new Literal(contractNodes.ContractFailureKind), NodeType.Box)), NodeType.Call, SystemTypes.Void)
            ));
          // info.AddValue("UserMessage", _UserMessage);
          body.Statements.Add(new ExpressionStatement(
            new MethodCall(new MemberBinding(info, addValueObject), new ExpressionList(new Literal("UserMessage", SystemTypes.String), new MemberBinding(new This(), userField)), NodeType.Call, SystemTypes.Void)
            ));
          // info.AddValue("Condition", _Condition);
          body.Statements.Add(new ExpressionStatement(
            new MethodCall(new MemberBinding(info, addValueObject), new ExpressionList(new Literal("Condition", SystemTypes.String), new MemberBinding(new This(), condField)), NodeType.Call, SystemTypes.Void)
            ));

          body.Statements.Add(new Return());
          contractExceptionType.Members.Add(getObjectData);
          #endregion
        }
      }

      this.RuntimeContractType.Members.Add(contractExceptionType);
      return contractExceptionType;
    }
Exemple #17
0
        internal static void TryAddCompilerGeneratedAttribute(Class Class)
        {
          Contract.Requires(Class != null);

            TryAddCompilerGeneratedAttribute(Class, System.AttributeTargets.Class);
        }
Exemple #18
0
 private Class CreateWrapperClass(Class c)
 {
   var flags = WrapperTypeFlags(c);
   var wrapper = new Class(this.assemblyBeingRewritten, null, null, flags, null, c.Name, SystemTypes.Object, null, null);
   RewriteHelper.TryAddCompilerGeneratedAttribute(wrapper);
   if (c.TemplateParameters != null)
   {
     Duplicator d = new Duplicator(this.assemblyBeingRewritten, wrapper);
     d.FindTypesToBeDuplicated(c.TemplateParameters);
     var templateParams = CopyTypeParameterList(wrapper, c, d);
     wrapper.TemplateParameters = templateParams;
     wrapper.IsGeneric = true;
   }
   return wrapper;
 }
Exemple #19
0
    internal Class CreateSerializerFor(TypeNode type) {
      // todo: look in the genCache for other serializer assemblies that may have already
      // created the serializer for this type and make an assembly reference to that 
      // serializer instead of creating a complete duplicate.
      TypeNode saved = tempChecker.currentType;

      Class c = (Class)serializers[type];
      if (c != null) return c;
      c = new Class();      
      c.Flags = TypeFlags.Class | TypeFlags.BeforeFieldInit;
      // copy the accessibility of the type we are serializing.
      c.Flags |= (type.Flags & (TypeFlags.Public | TypeFlags.NestedAssembly));
      c.Name = Identifier.For(GetSerializerName(type));
      c.Namespace = Identifier.For(GetSerializerNamespace(type));
      c.DeclaringModule = this.module;
      c.Members = new MemberList();
      c.Attributes = new AttributeList();
      c.BaseClass = Runtime.XmlSerializer;
      tempChecker.currentType = c;

      InstanceInitializer ii = Runtime.XmlSerializerAttribute.GetConstructor();
      MemberBinding mb = new MemberBinding(null, ii);
      mb.Type = Runtime.XmlSerializerAttribute;
      c.Attributes.Add(new AttributeNode(mb, null));
      if (cunit != null) {
        cunit.Namespaces[0].Types.Add(c);
      }
      this.module.Types.Add(c);

      Identifier typeId = Identifier.For("type"); // what we are writing to.
      Identifier rootName = Identifier.For("rootName"); // what we are writing to.
      Identifier rootNamespace = Identifier.For("rootNamespace"); // what we are writing to.

      // Constructor
      Method constructor = new InstanceInitializer();
      constructor.Name = StandardIds.Ctor;
      constructor.DeclaringType = c;
      constructor.Flags = MethodFlags.Public|MethodFlags.HideBySig|MethodFlags.SpecialName|MethodFlags.RTSpecialName;
      constructor.Parameters = new ParameterList();
      constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, typeId, SystemTypes.Type, null, null));
      constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootName, SystemTypes.String, null, null));
      constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootNamespace, SystemTypes.String, null, null));
      constructor.ReturnType = SystemTypes.Void;
      c.Members.Add(constructor);

      // pass args thru to base XmlSerializer constructor.
      Block b = constructor.Body = new Block(new StatementList());
      b.Statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(new Base(), StandardIds.Ctor), 
        new ExpressionList(typeId, rootName, rootNamespace), NodeType.Call)));      
      //AddConsoleWrite(b.Statements, new Literal("Hello!!",SystemTypes.String));

      // Serialize(T source, XmlSerializationWriter writer) method
      Identifier src = Identifier.For("source"); // object being serialized.
      Identifier writer = Identifier.For("writer"); // what we are writing to.

      Method serialize = new Method();
      serialize.Name = Identifier.For("Serialize");        
      serialize.DeclaringType = c;
      serialize.Flags = MethodFlags.Public|MethodFlags.Static|MethodFlags.HideBySig;
      serialize.Parameters = new ParameterList();
      serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, src, type, null, null));
      serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, writer, Runtime.XmlSerializationWriter, null, null));
      serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootName, SystemTypes.String, null, null));
      serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootNamespace, SystemTypes.String, null, null));
      serialize.ReturnType = SystemTypes.Void;
      c.Members.Add(serialize);

      // T Deserialize(XmlReader reader, bool required, out bool result) method
      Identifier reader = Identifier.For("reader"); // what we are reading from.
      Identifier required = Identifier.For("required"); // whether an object is required or not.
      Identifier result = Identifier.For("result"); // whether we found anything.

      Method deserialize = new Method();
      deserialize.Name = Identifier.For("Deserialize");        
      deserialize.DeclaringType = c;
      deserialize.Flags = MethodFlags.Public|MethodFlags.Static|MethodFlags.HideBySig;
      deserialize.Parameters = new ParameterList();
      deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, reader, Runtime.XmlSerializationReader, null, null));
      deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, required, SystemTypes.Boolean, null, null));
      deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.Out, result, SystemTypes.Boolean.GetReferenceType(), null, null));
      deserialize.ReturnType = type;
      c.Members.Add(deserialize);

      // It is important that we add the serializer to the cache AFTER we create the methods, but 
      // BEFORE we create the method bodies so that we can handle recurrsive calls to AddCallSerializer which
      // happens in recurrsive structures like "class Foo { public Foo f; }".  Otherwise we'd get stuck in an
      // infinite loop.
      serializers[type] = c;

      // Body of serialize method.
      b = serialize.Body = new Block(new StatementList());
      StatementList statements = b.Statements;
      
      if (!AddWriteSimpleType(type, statements, c, writer, src, rootName, rootNamespace)) {
        MethodCall call = new MethodCall();
        call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteStartElement"));
        call.Operands = new ExpressionList();
        call.Operands.Add(rootName);
        call.Operands.Add(rootNamespace);
        statements.Add(new If(new BinaryExpression(rootName,Literal.Null,NodeType.Ne),
          new Block(new StatementList(new ExpressionStatement(call))),null));

        Expression source = src;

        if (type.Template == SystemTypes.GenericBoxed) {
          statements = AddCheckForNull(statements, Duplicate(src, c), type);
          type = Checker.GetCollectionElementType(type); 
          source = CastTo(src, type);//unbox it
        }

        if (type is TupleType) {
          AddWriteTuple(type as TupleType, statements, c, source, writer);
        } else if (type is TypeUnion) {
          AddWriteChoice(type as TypeUnion, statements, c, source, writer);
        } else if (IsStream(type)) {
          AddWriteStream(type, statements, c, source, writer);
        } else {
          SchemaElementDecl sd = SchemaElementDecl.Compile(this.module, type, Checker.GetCollectionElementType(type), this.errorHandler, schemaElementDeclCache);
          SchemaValidator validator = validator = sd.CreateValidator(this.errorHandler);      
          statements = AddCheckForNull(statements, Duplicate(src, c), type);
          AddWriteAttributes(statements, c, writer, source, validator);
          AddWriteContent(type, statements, c, writer, source, validator);        
        }
        call = new MethodCall();
        call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteEndElement"));
        call.Operands = new ExpressionList();
        statements.Add(new If(new BinaryExpression(rootName,Literal.Null,NodeType.Ne),
          new Block(new StatementList(new ExpressionStatement(call))),null));
      }
      // body of deserialize method.
      b = deserialize.Body = new Block(new StatementList());
      statements = b.Statements;

      Local target = new Local(Identifier.Empty, type);

      if (type.Template == SystemTypes.GenericBoxed){
        type = Checker.GetCollectionElementType(type);
      }

      if (type is TupleType) {
        AddReadTuple(b, type as TupleType, statements, reader, target, required, result);
      } else if (type is TypeUnion) {
        AddReadChoice(b, type as TypeUnion, statements, reader, target, required, result);
      } else if (IsStream(type)) {
        AddReadStream(b, type, statements, reader, target, result);
      } else {
        if (type is TypeAlias) {
          type = ((TypeAlias)type).AliasedType;
        }

        // Then we are already positioned on the element to be deserialized. 
        statements.Add(new AssignmentStatement(required, Literal.True));
        if (!AddReadSimpleType(type, statements, reader, target, result, false)) {
          if (!type.IsValueType && !type.IsAbstract && type.GetConstructor() != null) {
            Construct cons = new Construct(new MemberBinding(null, type), new ExpressionList(), type);
            statements.Add(new AssignmentStatement(target, cons));
          }
          SchemaElementDecl sd = SchemaElementDecl.Compile(this.module, type, Checker.GetCollectionElementType(type), this.errorHandler, schemaElementDeclCache);
          SchemaValidator validator = validator = sd.CreateValidator(this.errorHandler);      
          AddReadAttributes(type, statements, reader, target, validator);
          AddReadContent(c, b, type, statements, reader, target, required, result, validator);
        }
      }
      statements.Add(new Return(target));
      tempChecker.currentType = saved;
      return c;
    }
 public virtual Class VisitClass(Class Class)
 {
     return (Class)this.VisitTypeNode(Class);
 }
Exemple #21
0
    void AddReadAllGroup(Class serializer, Block block, TypeNode type, StatementList statements, Identifier reader, 
      Expression target, Expression required, Expression result, ArrayList members, Member mixedMember) {

      // todo: keep track of which members have been read and report error on duplicates
      MethodCall read = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Read")), new ExpressionList());

      Local sb = new Local(SystemTypes.StringBuilder);
      bool isMixed = mixedMember != null;
      if (isMixed) {
        statements.Add(new AssignmentStatement(sb,
          new Construct(new MemberBinding(null, SystemTypes.StringBuilder), new ExpressionList(), SystemTypes.StringBuilder)));
      }

      Block whileBody = new Block(new StatementList());
      BinaryExpression notEndTag = new BinaryExpression(
        new QualifiedIdentifier(reader, Identifier.For("NodeType")) ,
        new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("EndElement")), NodeType.Ne);
      BinaryExpression notEOF = new BinaryExpression(
        new QualifiedIdentifier(reader, Identifier.For("EOF")), Literal.True, NodeType.Ne);
      While w = new While(new BinaryExpression(notEndTag, notEOF, NodeType.And), whileBody);
      statements.Add(w);

      Local nameLocal = new Local(Identifier.For("name"),SystemTypes.String,block);
      Local nsLocal = new Local(Identifier.For("ns"),SystemTypes.String,block);
      Local nodeType = new Local(Identifier.For("nodeType"),Runtime.XmlNodeType,block);

      whileBody.Statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName"))));
      whileBody.Statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI"))));
      whileBody.Statements.Add(new AssignmentStatement(nodeType, new QualifiedIdentifier(reader, Identifier.For("NodeType"))));
      
      Block childBlock = whileBody;

      if (isMixed) {
        // Append the text node to the current StringBuilder contents.
        childBlock = new Block(new StatementList());
        If ifText = new If(IsTextNode(nodeType), new Block(new StatementList()), childBlock);

        whileBody.Statements.Add(ifText);
        ExpressionList args = new ExpressionList();
        args.Add(new QualifiedIdentifier(reader, Identifier.For("Value")));
        ifText.TrueBlock.Statements.Add(new ExpressionStatement(new MethodCall(
          new QualifiedIdentifier(sb, Identifier.For("Append")), args)));
        ifText.TrueBlock.Statements.Add(new ExpressionStatement(read)); // advance to next node
      }      

      If ifElement = new If(new BinaryExpression(nodeType,
        new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("Element")), NodeType.Eq),
        new Block(new StatementList()), new Block(new StatementList()));
      childBlock.Statements.Add(ifElement);
      childBlock = ifElement.TrueBlock;

      //AddConsoleWrite(statements, new Literal("name=",SystemTypes.String));
      //AddConsoleWriteLine(statements, nameLocal);
      //AddConsoleWrite(statements, new Literal("nodeType=",SystemTypes.String));
      //AddConsoleWriteLine(statements, nodeType);

      foreach (NamedNode childNode in members) {
        if (!(childNode.Member is Field || childNode.Member is Property)) {
          AddError(statements, reader, RuntimeError.SerializationOfTypeNotSupported, 
            new Literal(childNode.Member.GetType().FullName, SystemTypes.String));
        } else {
          Expression mb = GetMemberBinding(target, childNode.Member);
          childBlock = AddReadChild(block, childBlock.Statements, childNode.Name, childNode.TypeNode, mb, reader, result, true, false).FalseBlock;
          // todo: throw error if child is required. (e.g. NonEmptyIEnumerable...)
        }
      }
      // if it isn't any of the expected elements then throw an error.
      AddError(childBlock.Statements, reader, RuntimeError.NoSuchMember,
        new Expression[2]{new Literal(tempChecker.GetTypeName(type),SystemTypes.String), nameLocal});

      // If it's not an element then consume it anyway to keep the reader advancing.
      // Probably a comment or PI or something.
      ifElement.FalseBlock.Statements.Add(new ExpressionStatement(new MethodCall(
        new QualifiedIdentifier(reader, Identifier.For("Skip")), new ExpressionList())));

      if (isMixed) {
        statements.Add(new AssignmentStatement(GetMemberBinding(target, mixedMember), 
          new MethodCall(new QualifiedIdentifier(sb, Identifier.For("ToString")), new ExpressionList())));         
      }
      statements.Add(new AssignmentStatement(result, Literal.True));

    }
        private static void AddInterfaceImplementationWrapper(Class Class, Method intfMethod, Method baseMethod)
        {
            var d = new Duplicator(Class.DeclaringModule, Class);
            
            d.SkipBodies = true;

            var copy = d.VisitMethod(baseMethod);
            
            copy.Flags = MethodFlags.Private | MethodFlags.HideBySig | MethodFlags.Virtual | MethodFlags.NewSlot |
                         MethodFlags.Final;
            
            copy.ImplementedInterfaceMethods = new MethodList(intfMethod);
            copy.Name = Identifier.For("InheritedInterfaceImplementationContractWrapper$" + intfMethod.Name.Name);
            copy.ClearBody();
            copy.ThisParameter.Type = Class;
            
            var bodyBlock = new Block(new StatementList());
            copy.Body = new Block(new StatementList(bodyBlock));

            // add call to baseMethod
            var calledMethod = (baseMethod.TemplateParameters != null && baseMethod.TemplateParameters.Count > 0)
                ? baseMethod.GetTemplateInstance(Class, copy.TemplateParameters)
                : baseMethod;

            var argList = new ExpressionList();
            for (int i = 0; i < copy.Parameters.Count; i++)
            {
                argList.Add(copy.Parameters[i]);
            }

            var callExpression = new MethodCall(new MemberBinding(copy.ThisParameter, calledMethod), argList);
            if (HelperMethods.IsVoidType(intfMethod.ReturnType))
            {
                bodyBlock.Statements.Add(new ExpressionStatement(callExpression));
            }
            else
            {
                bodyBlock.Statements.Add(new Return(callExpression));
            }
            
            Class.Members.Add(copy);
        }
        public override void VisitClass(Class Class)
        {
            if (Class == null) return;

            var savedState = this.currentState;

            this.currentState = savedState.Derive(Class);

            try
            {
                this.CheckClass(Class);

                CheckForWrapperImplementationsForInheritedInterfaceImplementations(Class);
            }
            finally
            {
                this.currentState = savedState;
            }

            base.VisitClass(Class);
        }
        /// <summary>
        /// Verifies that a class marked as holding the contract for an interface implements the interface.
        /// </summary>
        private void CheckClass(Class Class)
        {
            Contract.Requires(Class != null);

            // Compiler generated classes are closures that should get checked when visiting
            // the code that generated the closure, not from this end
            if (HelperMethods.IsCompilerGenerated(Class))
            {
                return;
            }

            // Contract classes need to implement the interface/abstract class that they are a contract for

            TypeNode originalType = HelperMethods.GetTypeFromAttribute(Class, ContractNodes.ContractClassForAttributeName);

            // Check that contract classes are abstract

            if (originalType != null && !Class.IsAbstract)
            {
                this.HandleError(
                    new Warning(1020, "Contract class '" + Class.FullName + "' should be an abstract class.",
                        new SourceContext()));
            }

            Interface iface = originalType as Interface;
            if (iface != null)
            {
                // base class should be object and interfaces should contain exactly 1, the interface
                if (Class.BaseClass != null && !(IsSystemObject(Class.BaseClass)))
                {
                    // should be an error
                    this.HandleError(
                        new Warning(1066,
                            "Class '" + Class.FullName + "' is annotated as being the contract for the interface '" +
                            iface.FullName + "' and cannot have an explicit base class other than System.Object.",
                            new SourceContext()));
                }

                Interface instance = null;
                for (int i = 0, n = Class.Interfaces == null ? 0 : Class.Interfaces.Count; i < n; i++)
                {
                    Interface J = Class.Interfaces[i];
                    if (J == iface || J.IsStructurallyEquivalentTo(iface))
                    {
                        instance = J;
                        break;
                    }
                }

                if (instance == null)
                {
                    this.HandleError(
                        new Error(1008,
                            "Class '" + Class.FullName + "' is annotated as being the contract for the interface '" +
                            iface.FullName + "' but doesn't implement the interface.",
                            new SourceContext()));
                }
                else
                {
                    // check other interfaces derive from core interface instance (.NET flattens the interface inheritance)
                    for (int i = 0, n = Class.Interfaces == null ? 0 : Class.Interfaces.Count; i < n; i++)
                    {
                        Interface J = Class.Interfaces[i];
                        if (J != instance && !instance.IsAssignableTo(J))
                        {
                            this.HandleError(
                                new Error(1068,
                                    string.Format("Class '{0}' is annotated as being the contract for the interface '{1}' but implements unrelated interface '{2}'.",
                                        Class.FullName, iface.FullName, J.FullName),
                                    new SourceContext()));
                        }
                    }
                }
            }
            else
            {
                Class abstractClass = originalType as Class;
                if (abstractClass != null)
                {
                    if (!(abstractClass == Class.BaseClass || abstractClass.IsStructurallyEquivalentTo(Class.BaseClass)))
                    {
                        this.HandleError(
                            new Error(1009,
                                "Class '" + Class.FullName + "' is annotated as being the contract for the abstract class '" +
                                abstractClass.FullName + "' but doesn't extend the class.",
                                new SourceContext()));
                    }

                    if (Class.Interfaces != null && Class.Interfaces.Count > 0)
                    {
                        this.HandleError(
                            new Error(1067,
                                "Class '" + Class.FullName + "' is annotated as being the contract for the abstract class '" +
                                abstractClass.FullName + "' and cannot implement any interfaces.",
                                new SourceContext()));
                    }
                }
            }

            // Make sure that if this class *is* a contractClass, that that class points back to this one

            if (originalType != null)
            {
                TypeNode backPointer = HelperMethods.GetTypeFromAttribute(originalType, ContractNodes.ContractClassAttributeName);
                if (backPointer == null || backPointer != Class)
                {
                    this.HandleError(
                        new Error(1021, "The class '" + Class.FullName
                                        + "' is supposed to be a contract class for '" +
                                        originalType.FullName
                                        + "', but that type does not point back to this class.",
                            new SourceContext()));
                }

                // Checks that contract class matches real class

                if (!GenericConstraintsMatch(originalType, Class))
                {
                    this.HandleError(
                        new Error(1043, "The contract class '" + Class.FullName
                                        + "' and the type '" + originalType.FullName + "' must agree on all generic parameters.",
                            new SourceContext()));
                }

                // Check that they have the same container if they are generic

                if (Class.IsGeneric && Class.DeclaringType != originalType.DeclaringType)
                {
                    this.HandleError(
                        new Error(1044, "The contract class '" + Class.FullName
                                        + "' and the type '" + originalType.FullName
                                        + "' must have the same declaring type if any.",
                            new SourceContext()));
                }
            }

            // No class should have a contract class as a base class

            var baseClass = Class.BaseClass;
            var baseClassIsAContractClass = HelperMethods.GetTypeFromAttribute(baseClass, ContractNodes.ContractClassForAttributeName);
            if (baseClassIsAContractClass != null)
            {
                this.HandleError(
                    new Error(1079, "The class '" + Class.FullName + "' cannot have a base type that is a contract class.",
                        new SourceContext()));
            }
        }
        private void CheckForWrapperImplementationsForInheritedInterfaceImplementations(Class Class, Interface intf)
        {
            Contract.Requires(Class != null);
            Contract.Requires(intf != null);

            var members = intf.Members;
            // if (members == null) return;
            for (int i = 0; i < members.Count; i++)
            {
                var intfMethod = members[i] as Method;
                if (intfMethod == null) continue;

                if (Class.ExplicitImplementation(intfMethod) != null) continue;

                if (Class.GetExactMatchingMethod(intfMethod) != null) continue;

                var contractMethod = HelperMethods.GetContractMethod(intfMethod);
                if (contractMethod == null) continue;

                var contract = contractMethod.Contract;
                if (contract == null) continue;
                
                if (contract.RequiresCount + contract.EnsuresCount == 0) continue;

                // find base implementing method
                var baseMethod = FindInheritedMethod(Class.BaseClass, intfMethod);
                if (baseMethod == null) continue;
                
                var baseMethodImplementsInterfaceMethod = false;
                if (baseMethod.ImplicitlyImplementedInterfaceMethods != null)
                {
                    for (int j = 0; j < baseMethod.ImplicitlyImplementedInterfaceMethods.Count; j++)
                    {
                        if (baseMethod.ImplicitlyImplementedInterfaceMethods[j] == intfMethod)
                        {
                            baseMethodImplementsInterfaceMethod = true;
                            break;
                        }
                    }
                }

                if (baseMethodImplementsInterfaceMethod) continue;

                if (this.runtimeCheckingLevel < 3 && contract.RequiresCount == 0) continue;

                if (this.addInterfaceWrappersWhenNeeded)
                {
                    AddInterfaceImplementationWrapper(Class, intfMethod, baseMethod);
                }
                else
                {
                    this.HandleError(new Warning(1080,
                        string.Format(
                            "Type {0} implements {1} by inheriting {2} causing the interface contract to not be checked at runtime. Consider adding a wrapper method.",
                            Class.FullName, intfMethod.FullName, baseMethod.FullName),
                        default(SourceContext)));
                }
            }
        }
Exemple #26
0
    internal static void Initialize(){
      RuntimeAssembly = Runtime.GetRuntimeAssembly();

      PostCompilationPluginAttributeType = RuntimeAssembly.GetType(Identifier.For("Microsoft.SpecSharp"), Identifier.For("PostCompilationPluginAttribute"));
      ObjectConstructor = SystemTypes.Object.GetConstructor(); 
      IListAdd = SystemTypes.IList.GetMethod(StandardIds.Add, SystemTypes.Object);

#if CCINamespace
      const string ContractsNs = "Microsoft.Contracts";
#else
      const string ContractsNs = "Microsoft.Contracts";
#endif

      MustOverrideAttribute = (Class)GetCompilerRuntimeTypeNodeFor(ContractsNs, "MustOverrideAttribute");
    
    }
        private static Method FindInheritedMethod(Class baseClass, Method interfaceMethod)
        {
            while (baseClass != null)
            {
                if (InterfaceListContains(baseClass.Interfaces, interfaceMethod.DeclaringType))
                {
                    // instrumented in base
                    return null;
                }

                var candidate = baseClass.GetExactMatchingMethod(interfaceMethod);
                
                if (candidate != null) return candidate;
            
                baseClass = baseClass.BaseClass;
            }

            return null;
        }
        /// <summary>
        /// Extracts contracts from a class into the appropriate fields in the CCI tree.
        /// </summary>
        /// <param name="Class">Class to visit.</param>
        /// <returns>The same class but with contracts extracted.</returns>
        public override Class VisitClass(Class Class)
        {
            // Special processing for classes that are holding the contract for an interface or abstract class

            var originalType = HelperMethods.IsContractTypeForSomeOtherTypeUnspecialized(Class, this.contractNodes);
            var originalScrubber = this.currentScrubber;

            if (originalType != null)
            {
                this.currentScrubber = new ScrubContractClass(this, Class, originalType);
            }

            try
            {
                return base.VisitClass(Class);
            }
            finally
            {
                this.currentScrubber = originalScrubber;
            }
        }
 private static bool IsSystemObject(Class Class)
 {
     return Class.Name.Matches(StandardIds.CapitalObject) && Class.Namespace.Matches(StandardIds.System);
 }
        public static bool IsContractTypeForSomeOtherType(Class Class)
        {
            if (Class == null) return false;

            if (Class.Attributes == null) return false;
            
            for (int i = 0; i < Class.Attributes.Count; i++)
            {
                var attr = Class.Attributes[i];
                
                if (attr == null) continue;
                
                if (attr.Type == null) continue;
                
                if (attr.Type.Name == null) continue;
                
                if (attr.Type.Name.Name == "ContractClassForAttribute") return true;
            }

            return false;
        }