private TypeNode ConvertToClassParameter(TypeNode baseType, TypeNode/*!*/ typeParameter) { ClassParameter result; if (typeParameter is MethodTypeParameter) { result = new MethodClassParameter(); } else if (typeParameter is TypeParameter) { result = new ClassParameter(); result.DeclaringType = typeParameter.DeclaringType; } else return typeParameter; //give up result.SourceContext = typeParameter.SourceContext; result.TypeParameterFlags = ((ITypeParameter)typeParameter).TypeParameterFlags; result.Name = typeParameter.Name; result.Namespace = StandardIds.ClassParameter; result.BaseClass = baseType is Class ? (Class)baseType : CoreSystemTypes.Object; result.DeclaringMember = ((ITypeParameter)typeParameter).DeclaringMember; result.DeclaringModule = typeParameter.DeclaringModule; result.Flags = typeParameter.Flags & ~TypeFlags.Interface; //InterfaceList constraints = result.Interfaces = new InterfaceList(); InterfaceList interfaces = typeParameter.Interfaces; for (int i = 1, n = interfaces == null ? 0 : interfaces.Count; i < n; i++) { //^ assert interfaces != null; interfaces.Add(this.VisitInterfaceReference(interfaces[i])); } return result; }
private Method CreateWrapperMethod(bool virtcall, TypeNode virtcallConstraint, Method templateMethod, TypeNode templateType, TypeNode wrapperType, Method methodWithContract, Method instanceMethod, SourceContext callingContext) { bool isProtected = IsProtected(templateMethod); Identifier name = templateMethod.Name; if (virtcall) { if (virtcallConstraint != null) { name = Identifier.For("CV$" + name.Name); } else { name = Identifier.For("V$" + name.Name); } } else { name = Identifier.For("NV$" + name.Name); } Duplicator dup = new Duplicator(this.assemblyBeingRewritten, wrapperType); TypeNodeList typeParameters = null; TypeNodeList typeParameterFormals = new TypeNodeList(); TypeNodeList typeParameterActuals = new TypeNodeList(); if (templateMethod.TemplateParameters != null) { dup.FindTypesToBeDuplicated(templateMethod.TemplateParameters); typeParameters = dup.VisitTypeParameterList(templateMethod.TemplateParameters); for (int i = 0; i < typeParameters.Count; i++) { typeParameterFormals.Add(typeParameters[i]); typeParameterActuals.Add(templateMethod.TemplateParameters[i]); } } ITypeParameter constraintTypeParam = null; if (virtcallConstraint != null) { if (typeParameters == null) { typeParameters = new TypeNodeList(); } var constraint = templateMethod.DeclaringType; var classConstraint = constraint as Class; if (classConstraint != null) { var classParam = new MethodClassParameter(); classParam.BaseClass = classConstraint; classParam.Name = Identifier.For("TC"); classParam.DeclaringType = wrapperType; typeParameters.Add(classParam); constraintTypeParam = classParam; } else { var mtp = new MethodTypeParameter(); Interface intf = constraint as Interface; if (intf != null) { mtp.Interfaces.Add(intf); } mtp.Name = Identifier.For("TC"); mtp.DeclaringType = wrapperType; typeParameters.Add(mtp); constraintTypeParam = mtp; } } var consolidatedTemplateTypeParameters = templateType.ConsolidatedTemplateParameters; if (consolidatedTemplateTypeParameters != null && consolidatedTemplateTypeParameters.Count > 0) { var consolidatedWrapperTypeParameters = wrapperType.ConsolidatedTemplateParameters; for (int i = 0; i < consolidatedTemplateTypeParameters.Count; i++) { typeParameterFormals.Add(consolidatedWrapperTypeParameters[i]); typeParameterActuals.Add(consolidatedTemplateTypeParameters[i]); } } Specializer spec = null; if (typeParameterActuals.Count > 0) { spec = new Specializer(this.assemblyBeingRewritten, typeParameterActuals, typeParameterFormals); } var parameters = new ParameterList(); var asTypeConstraintTypeParam = constraintTypeParam as TypeNode; if (!isProtected && !templateMethod.IsStatic) { TypeNode thisType = GetThisTypeInstance(templateType, wrapperType, asTypeConstraintTypeParam); parameters.Add(new Parameter(Identifier.For("@this"), thisType)); } for (int i = 0; i < templateMethod.Parameters.Count; i++) { parameters.Add((Parameter)dup.VisitParameter(templateMethod.Parameters[i])); } var retType = dup.VisitTypeReference(templateMethod.ReturnType); if (spec != null) { parameters = spec.VisitParameterList(parameters); retType = spec.VisitTypeReference(retType); } var wrapperMethod = new Method(wrapperType, null, name, parameters, retType, null); RewriteHelper.TryAddCompilerGeneratedAttribute(wrapperMethod); if (isProtected) { wrapperMethod.Flags = templateMethod.Flags & ~MethodFlags.Abstract; wrapperMethod.CallingConvention = templateMethod.CallingConvention; } else { wrapperMethod.Flags |= MethodFlags.Static | MethodFlags.Assembly; } if (constraintTypeParam != null) { constraintTypeParam.DeclaringMember = wrapperMethod; } if (typeParameters != null) { if (spec != null) { typeParameters = spec.VisitTypeParameterList(typeParameters); } wrapperMethod.IsGeneric = true; wrapperMethod.TemplateParameters = typeParameters; } // create body var sl = new StatementList(); Block b = new Block(sl); // insert requires AddRequiresToWrapperMethod(wrapperMethod, b, methodWithContract); // create original call var targetType = templateType; if (isProtected) { // need to use base chain instantiation of target type. targetType = instanceMethod.DeclaringType; } else { if (targetType.ConsolidatedTemplateParameters != null && targetType.ConsolidatedTemplateParameters.Count > 0) { // need selfinstantiation targetType = targetType.GetGenericTemplateInstance(this.assemblyBeingRewritten, wrapperType.ConsolidatedTemplateParameters); } } Method targetMethod = GetMatchingMethod(targetType, templateMethod, wrapperMethod); if (targetMethod.IsGeneric) { if (typeParameters.Count > targetMethod.TemplateParameters.Count) { // omit the extra constrained type arg. TypeNodeList origArgs = new TypeNodeList(); for (int i = 0; i < targetMethod.TemplateParameters.Count; i++) { origArgs.Add(typeParameters[i]); } targetMethod = targetMethod.GetTemplateInstance(wrapperType, origArgs); } else { targetMethod = targetMethod.GetTemplateInstance(wrapperType, typeParameters); } } MethodCall call; NodeType callType = virtcall ? NodeType.Callvirt : NodeType.Call; if (isProtected) { var mb = new MemberBinding(wrapperMethod.ThisParameter, targetMethod); var elist = new ExpressionList(wrapperMethod.Parameters.Count); for (int i = 0; i < wrapperMethod.Parameters.Count; i++) { elist.Add(wrapperMethod.Parameters[i]); } call = new MethodCall(mb, elist, callType); } else if (templateMethod.IsStatic) { var elist = new ExpressionList(wrapperMethod.Parameters.Count); for (int i = 0; i < wrapperMethod.Parameters.Count; i++) { elist.Add(wrapperMethod.Parameters[i]); } call = new MethodCall(new MemberBinding(null, targetMethod), elist, callType); } else { var mb = new MemberBinding(wrapperMethod.Parameters[0], targetMethod); var elist = new ExpressionList(wrapperMethod.Parameters.Count - 1); for (int i = 1; i < wrapperMethod.Parameters.Count; i++) { elist.Add(wrapperMethod.Parameters[i]); } call = new MethodCall(mb, elist, callType); } if (constraintTypeParam != null) { call.Constraint = asTypeConstraintTypeParam; } if (HelperMethods.IsVoidType(templateMethod.ReturnType)) { sl.Add(new ExpressionStatement(call,callingContext)); sl.Add(new Return(callingContext)); } else { sl.Add(new Return(call,callingContext)); } wrapperMethod.Body = b; wrapperType.Members.Add(wrapperMethod); return wrapperMethod; }
private static TypeNode NewEqualMethodTypeParameter(ITypeParameter itp, Method declaringMethod, int index) { TypeNode declaringType = declaringMethod.DeclaringType; ClassParameter cp = itp as ClassParameter; if (cp != null) { MethodClassParameter mcp = new MethodClassParameter(); mcp.Interfaces = cp.Interfaces.Clone(); mcp.BaseClass = cp.BaseClass; mcp.TypeParameterFlags = cp.TypeParameterFlags & ~TypeParameterFlags.VarianceMask; mcp.DeclaringType = declaringType; mcp.DeclaringModule = declaringType.DeclaringModule; mcp.Name = cp.Name; mcp.ParameterListIndex = index; mcp.DeclaringMember = declaringMethod; return mcp; } TypeParameter tp = itp as TypeParameter; if (tp != null) { MethodTypeParameter mp = new MethodTypeParameter(); mp.Interfaces = tp.Interfaces.Clone(); mp.TypeParameterFlags = tp.TypeParameterFlags & ~TypeParameterFlags.VarianceMask; mp.DeclaringType = declaringType; mp.DeclaringModule = declaringType.DeclaringModule; mp.Name = tp.Name; mp.ParameterListIndex = index; mp.DeclaringMember = declaringMethod; return mp; } throw new NotImplementedException("unexpected type parameter kind"); }
private Method MakeRequiresWithExceptionMethod(string name) { Parameter conditionParameter = new Parameter(Identifier.For("condition"), SystemTypes.Boolean); Parameter messageParameter = new Parameter(Identifier.For("msg"), SystemTypes.String); Parameter conditionTextParameter = new Parameter(Identifier.For("conditionTxt"), SystemTypes.String); MethodClassParameter typeArg = new MethodClassParameter(); ParameterList pl = new ParameterList(conditionParameter, messageParameter, conditionTextParameter); Block body = new Block(new StatementList()); Method m = new Method(this.RuntimeContractType, null, Identifier.For(name), pl, SystemTypes.Void, body); m.Flags = MethodFlags.Assembly | MethodFlags.Static; m.Attributes = new AttributeList(); m.TemplateParameters = new TypeNodeList(typeArg); m.IsGeneric = true; this.RuntimeContractType.Members.Add(m); typeArg.Name = Identifier.For("TException"); typeArg.DeclaringMember = m; typeArg.BaseClass = SystemTypes.Exception; typeArg.ParameterListIndex = 0; typeArg.DeclaringModule = this.RuntimeContractType.DeclaringModule; Block returnBlock = new Block(new StatementList(new Return())); Block b = new Block(new StatementList()); b.Statements.Add(new Branch(conditionParameter, returnBlock)); // // Generate the following // // // message == null means: yes we handled it. Otherwise it is the localized failure message // var message = RaiseFailureEvent(ContractFailureKind.Precondition, userMessage, conditionString, null); // #if assertOnFailure // if (message != null) { // Assert(false, message); // } // #endif var messageLocal = new Local(Identifier.For("msg"), SystemTypes.String); ExpressionList elist = new ExpressionList(); elist.Add(this.PreconditionKind); elist.Add(messageParameter); elist.Add(conditionTextParameter); elist.Add(Literal.Null); b.Statements.Add(new AssignmentStatement(messageLocal, new MethodCall(new MemberBinding(null, this.RaiseFailureEventMethod), elist))); if (this.AssertOnFailure) { var assertMethod = GetSystemDiagnosticsAssertMethod(); if (assertMethod != null) { var skipAssert = new Block(); b.Statements.Add(new Branch(new UnaryExpression(messageLocal, NodeType.LogicalNot), skipAssert)); // emit assert call ExpressionList assertelist = new ExpressionList(); assertelist.Add(Literal.False); assertelist.Add(messageLocal); b.Statements.Add(new ExpressionStatement(new MethodCall(new MemberBinding(null, assertMethod), assertelist))); b.Statements.Add(skipAssert); } } // // construct exception // Exception obj = null; // ConstructorInfo ci = typeof(TException).GetConstructor(new[] { typeof(string), typeof(string) }); // if (ci != null) // { // if (reflection.firstArgName == "paramName") { // exceptionObject = ci.Invoke(new[] { userMessage, message }) as Exception; // } // else { // exceptionObject = ci.Invoke(new[] { message, userMessage }) as Exception; // } // } // else { // ci = typeof(TException).GetConstructor(new[] { typeof(string) }); // if (ci != null) // { // exceptionObject = ci.Invoke(new[] { message }) as Exception; // } // } var exceptionLocal = new Local(Identifier.For("obj"), SystemTypes.Exception); b.Statements.Add(new AssignmentStatement(exceptionLocal, Literal.Null)); var constructorInfoType = TypeNode.GetTypeNode(typeof(System.Reflection.ConstructorInfo)); Contract.Assume(constructorInfoType != null); var methodBaseType = TypeNode.GetTypeNode(typeof(System.Reflection.MethodBase)); Contract.Assume(methodBaseType != null); var constructorLocal = new Local(Identifier.For("ci"), constructorInfoType); Contract.Assume(SystemTypes.Type != null); var getConstructorMethod = SystemTypes.Type.GetMethod(Identifier.For("GetConstructor"), SystemTypes.Type.GetArrayType(1)); var typeofExceptionArg = GetTypeFromHandleExpression(typeArg); var typeofString = GetTypeFromHandleExpression(SystemTypes.String); var typeArrayLocal = new Local(Identifier.For("typeArray"), SystemTypes.Type.GetArrayType(1)); var typeArray2 = new ConstructArray(); typeArray2.ElementType = SystemTypes.Type; typeArray2.Rank = 1; typeArray2.Operands = new ExpressionList(Literal.Int32Two); var typeArrayInit2 = new Block(new StatementList()); typeArrayInit2.Statements.Add(new AssignmentStatement(typeArrayLocal, typeArray2)); typeArrayInit2.Statements.Add(new AssignmentStatement(new Indexer(typeArrayLocal, new ExpressionList(Literal.Int32Zero), SystemTypes.Type), typeofString)); typeArrayInit2.Statements.Add(new AssignmentStatement(new Indexer(typeArrayLocal, new ExpressionList(Literal.Int32One), SystemTypes.Type), typeofString)); typeArrayInit2.Statements.Add(new ExpressionStatement(typeArrayLocal)); var typeArrayExpression2 = new BlockExpression(typeArrayInit2); b.Statements.Add(new AssignmentStatement(constructorLocal, new MethodCall(new MemberBinding(typeofExceptionArg, getConstructorMethod), new ExpressionList(typeArrayExpression2)))); var elseBlock = new Block(); b.Statements.Add(new Branch(new UnaryExpression(constructorLocal, NodeType.LogicalNot), elseBlock)); var endifBlock2 = new Block(); var invokeMethod = constructorInfoType.GetMethod(Identifier.For("Invoke"), SystemTypes.Object.GetArrayType(1)); var argArray2 = new ConstructArray(); argArray2.ElementType = SystemTypes.Object; argArray2.Rank = 1; argArray2.Operands = new ExpressionList(Literal.Int32Two); var argArrayLocal = new Local(Identifier.For("argArray"), SystemTypes.Object.GetArrayType(1)); var parameterInfoType = TypeNode.GetTypeNode(typeof(System.Reflection.ParameterInfo)); Contract.Assume(parameterInfoType != null); var parametersMethod = methodBaseType.GetMethod(Identifier.For("GetParameters")); var get_NameMethod = parameterInfoType.GetMethod(Identifier.For("get_Name")); var string_op_EqualityMethod = SystemTypes.String.GetMethod(Identifier.For("op_Equality"), SystemTypes.String, SystemTypes.String); var elseArgMsgBlock = new Block(); var endIfArgMsgBlock = new Block(); b.Statements.Add(new Branch(new UnaryExpression(new MethodCall(new MemberBinding(null, string_op_EqualityMethod), new ExpressionList(new MethodCall(new MemberBinding(new Indexer(new MethodCall(new MemberBinding(constructorLocal, parametersMethod), new ExpressionList(), NodeType.Callvirt), new ExpressionList(Literal.Int32Zero), parameterInfoType), get_NameMethod), new ExpressionList(), NodeType.Callvirt), new Literal("paramName", SystemTypes.String))), NodeType.LogicalNot), elseArgMsgBlock)); var argArrayInit2 = new Block(new StatementList()); argArrayInit2.Statements.Add(new AssignmentStatement(argArrayLocal, argArray2)); argArrayInit2.Statements.Add(new AssignmentStatement(new Indexer(argArrayLocal, new ExpressionList(Literal.Int32Zero), SystemTypes.Object), messageParameter)); argArrayInit2.Statements.Add(new AssignmentStatement(new Indexer(argArrayLocal, new ExpressionList(Literal.Int32One), SystemTypes.Object), messageLocal)); argArrayInit2.Statements.Add(new ExpressionStatement(argArrayLocal)); var argArrayExpression2 = new BlockExpression(argArrayInit2); b.Statements.Add(new AssignmentStatement(exceptionLocal, new BinaryExpression(new MethodCall(new MemberBinding(constructorLocal, invokeMethod), new ExpressionList(argArrayExpression2)), new Literal(SystemTypes.Exception), NodeType.Isinst))); b.Statements.Add(new Branch(null, endIfArgMsgBlock)); b.Statements.Add(elseArgMsgBlock); var argArrayInit2_1 = new Block(new StatementList()); argArrayInit2_1.Statements.Add(new AssignmentStatement(argArrayLocal, argArray2)); argArrayInit2_1.Statements.Add(new AssignmentStatement(new Indexer(argArrayLocal, new ExpressionList(Literal.Int32Zero), SystemTypes.Object), messageLocal)); argArrayInit2_1.Statements.Add(new AssignmentStatement(new Indexer(argArrayLocal, new ExpressionList(Literal.Int32One), SystemTypes.Object), messageParameter)); argArrayInit2_1.Statements.Add(new ExpressionStatement(argArrayLocal)); var argArrayExpression2_1 = new BlockExpression(argArrayInit2_1); b.Statements.Add(new AssignmentStatement(exceptionLocal, new BinaryExpression(new MethodCall(new MemberBinding(constructorLocal, invokeMethod), new ExpressionList(argArrayExpression2_1)), new Literal(SystemTypes.Exception), NodeType.Isinst))); b.Statements.Add(endIfArgMsgBlock); b.Statements.Add(new Branch(null, endifBlock2)); b.Statements.Add(elseBlock); var typeArray1 = new ConstructArray(); typeArray1.ElementType = SystemTypes.Type; typeArray1.Rank = 1; typeArray1.Operands = new ExpressionList(Literal.Int32One); var typeArrayInit1 = new Block(new StatementList()); typeArrayInit1.Statements.Add(new AssignmentStatement(typeArrayLocal, typeArray1)); typeArrayInit1.Statements.Add(new AssignmentStatement(new Indexer(typeArrayLocal, new ExpressionList(Literal.Int32Zero), SystemTypes.Type), typeofString)); typeArrayInit1.Statements.Add(new ExpressionStatement(typeArrayLocal)); var typeArrayExpression1 = new BlockExpression(typeArrayInit1); b.Statements.Add(new AssignmentStatement(constructorLocal, new MethodCall(new MemberBinding(typeofExceptionArg, getConstructorMethod), new ExpressionList(typeArrayExpression1)))); b.Statements.Add(new Branch(new UnaryExpression(constructorLocal, NodeType.LogicalNot), endifBlock2)); var argArray1 = new ConstructArray(); argArray1.ElementType = SystemTypes.Object; argArray1.Rank = 1; argArray1.Operands = new ExpressionList(Literal.Int32One); var argArrayInit1 = new Block(new StatementList()); argArrayInit1.Statements.Add(new AssignmentStatement(argArrayLocal, argArray1)); argArrayInit1.Statements.Add(new AssignmentStatement(new Indexer(argArrayLocal, new ExpressionList(Literal.Int32Zero), SystemTypes.Object), messageLocal)); argArrayInit1.Statements.Add(new ExpressionStatement(argArrayLocal)); var argArrayExpression1 = new BlockExpression(argArrayInit1); b.Statements.Add(new AssignmentStatement(exceptionLocal, new BinaryExpression(new MethodCall(new MemberBinding(constructorLocal, invokeMethod), new ExpressionList(argArrayExpression1)), new Literal(SystemTypes.Exception), NodeType.Isinst))); b.Statements.Add(endifBlock2); // // throw it // if (exceptionObject == null) // { // throw new ArgumentException(displayMessage, message); // } // else // { // throw exceptionObject; // } var thenBlock3 = new Block(); b.Statements.Add(new Branch(exceptionLocal, thenBlock3)); b.Statements.Add(new Throw(new Construct(new MemberBinding(null, SystemTypes.ArgumentException.GetConstructor(SystemTypes.String, SystemTypes.String)), new ExpressionList(messageLocal, messageParameter)))); b.Statements.Add(thenBlock3); b.Statements.Add(new Throw(exceptionLocal)); b.Statements.Add(returnBlock); Contract.Assume(body.Statements != null); body.Statements.Add(b); Member constructor = null; AttributeNode attribute = null; #region Add [DebuggerNonUserCodeAttribute] if (this.HideFromDebugger) { TypeNode debuggerNonUserCode = SystemTypes.SystemAssembly.GetType(Identifier.For("System.Diagnostics"), Identifier.For("DebuggerNonUserCodeAttribute")); if (debuggerNonUserCode != null) { constructor = debuggerNonUserCode.GetConstructor(); attribute = new AttributeNode(new MemberBinding(null, constructor), null, AttributeTargets.Method); m.Attributes.Add(attribute); } } #endregion Add [DebuggerNonUserCodeAttribute] TypeNode reliabilityContract = SystemTypes.SystemAssembly.GetType(Identifier.For("System.Runtime.ConstrainedExecution"), Identifier.For("ReliabilityContractAttribute")); TypeNode consistency = SystemTypes.SystemAssembly.GetType(Identifier.For("System.Runtime.ConstrainedExecution"), Identifier.For("Consistency")); TypeNode cer = SystemTypes.SystemAssembly.GetType(Identifier.For("System.Runtime.ConstrainedExecution"), Identifier.For("Cer")); if (reliabilityContract != null && consistency != null && cer != null) { constructor = reliabilityContract.GetConstructor(consistency, cer); if (constructor != null) { attribute = new AttributeNode( new MemberBinding(null, constructor), new ExpressionList( new Literal(System.Runtime.ConstrainedExecution.Consistency.WillNotCorruptState, consistency), new Literal(System.Runtime.ConstrainedExecution.Cer.MayFail, cer)), AttributeTargets.Method ); m.Attributes.Add(attribute); } } return m; }